forked from MUME/MMapper
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCharacters.h
More file actions
231 lines (200 loc) 路 7.22 KB
/
Copy pathCharacters.h
File metadata and controls
231 lines (200 loc) 路 7.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#pragma once
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2019 The MMapper Authors
#include "../global/RuleOf5.h"
#include "../global/utils.h"
#include "../map/coordinate.h"
#include "../opengl/Font.h"
#include "../opengl/OpenGLTypes.h"
#include <cassert>
#include <cstddef>
#include <map>
#include <memory>
#include <stack>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <QColor>
class MapScreen;
class OpenGL;
struct MapCanvasTextures;
// TODO: find a better home for this. It's common to characters and room selections.
class NODISCARD DistantObjectTransform final
{
public:
const glm::vec3 offset{};
// rotation counterclockwise around the Z axis, starting at the +X axis.
const float rotationDegrees = 0.f;
public:
explicit DistantObjectTransform(const glm::vec3 &offset_, const float rotationDegrees_)
: offset{offset_}
, rotationDegrees{rotationDegrees_}
{}
public:
// Caller must apply the correct translation and rotation.
NODISCARD static DistantObjectTransform construct(const glm::vec3 &pos,
const MapScreen &mapScreen,
float marginPixels);
};
class NODISCARD CharacterBatch final
{
private:
static constexpr const float FILL_ALPHA = 0.1f;
static constexpr const float BEACON_ALPHA = 0.10f;
static constexpr const float LINE_ALPHA = 0.9f;
private:
struct NODISCARD Matrices final
{
// glm::mat4 proj = glm::mat4(1);
glm::mat4 modelView = glm::mat4(1);
};
class NODISCARD MatrixStack final : private std::stack<Matrices>
{
private:
using base = std::stack<Matrices>;
public:
MatrixStack() { base::push(Matrices()); }
~MatrixStack() { assert(base::size() == 1); }
void push() { base::push(top()); }
using base::pop;
using base::top;
};
class NODISCARD CharFakeGL final
{
private:
struct NODISCARD CoordCompare final
{
// REVISIT: just make this the global operator<(),
// so it can be picked up by std::less<Coordinate>.
bool operator()(const Coordinate &lhs, const Coordinate &rhs) const
{
if (lhs.x < rhs.x) {
return true;
}
if (rhs.x < lhs.x) {
return false;
}
if (lhs.y < rhs.y) {
return true;
}
if (rhs.y < lhs.y) {
return false;
}
return lhs.z < rhs.z;
}
};
private:
Color m_color;
MatrixStack m_stack;
std::vector<ColorVert> m_charTris;
std::vector<ColorVert> m_charBeaconQuads;
std::vector<ColoredTexVert> m_charTokenQuads;
std::vector<QString> m_charTokenKeys;
std::vector<ColorVert> m_charLines;
std::vector<ColorVert> m_pathPoints;
std::vector<ColorVert> m_pathLineVerts;
std::vector<ColoredTexVert> m_charRoomQuads;
std::vector<FontVert3d> m_screenSpaceArrows;
std::map<Coordinate, int, CoordCompare> m_coordCounts;
public:
CharFakeGL() = default;
~CharFakeGL() = default;
DELETE_CTORS_AND_ASSIGN_OPS(CharFakeGL);
public:
void reallyDraw(OpenGL &gl, const MapCanvasTextures &textures)
{
reallyDrawCharacters(gl, textures);
reallyDrawPaths(gl);
}
private:
void reallyDrawCharacters(OpenGL &gl, const MapCanvasTextures &textures);
void reallyDrawPaths(OpenGL &gl);
public:
void setColor(const Color &color) { m_color = color; }
void reserve(Coordinate c) { m_coordCounts[c]++; }
void clear(Coordinate c) { m_coordCounts[c] = 0; }
public:
void glPushMatrix() { m_stack.push(); }
void glPopMatrix() { m_stack.pop(); }
void glRotateZ(float degrees)
{
auto &m = m_stack.top().modelView;
m = glm::rotate(m, glm::radians(degrees), glm::vec3{0, 0, 1});
}
void glScalef(float x, float y, float z)
{
auto &m = m_stack.top().modelView;
m = glm::scale(m, glm::vec3{x, y, z});
}
void glTranslatef(const glm::vec3 &v)
{
auto &m = m_stack.top().modelView;
m = glm::translate(m, v);
}
void drawArrow(bool fill, bool beacon);
void drawBox(const Coordinate &coord, bool fill, bool beacon, bool isFar,const QString &dispName);
void addScreenSpaceArrow(const glm::vec3 &pos, float degrees, const Color &color, bool fill);
// with blending, without depth; always size 4
void drawPathLineStrip(const Color &color, const std::vector<glm::vec3> &points)
{
for (size_t i = 1, size = points.size(); i < size; ++i) {
m_pathLineVerts.emplace_back(color, points[i - 1]);
m_pathLineVerts.emplace_back(color, points[i]);
}
}
// with blending, without depth; always size 8
void drawPathPoint(const Color &color, const glm::vec3 &pos)
{
m_pathPoints.emplace_back(color, pos);
}
private:
enum class NODISCARD QuadOptsEnum : uint32_t {
NONE = 0,
OUTLINE = 1,
FILL = 2,
BEACON = 4
};
NODISCARD friend QuadOptsEnum operator|(const QuadOptsEnum lhs, const QuadOptsEnum rhs)
{
return static_cast<QuadOptsEnum>(static_cast<uint32_t>(lhs)
| static_cast<uint32_t>(rhs));
}
NODISCARD friend QuadOptsEnum operator&(const QuadOptsEnum lhs, const QuadOptsEnum rhs)
{
return static_cast<QuadOptsEnum>(static_cast<uint32_t>(lhs)
& static_cast<uint32_t>(rhs));
}
void drawQuadCommon(const glm::vec2 &a,
const glm::vec2 &b,
const glm::vec2 &c,
const glm::vec2 &d,
QuadOptsEnum options);
};
private:
const MapScreen &m_mapScreen;
const int m_currentLayer;
const float m_scale;
CharFakeGL m_fakeGL;
public:
explicit CharacterBatch(const MapScreen &mapScreen, const int currentLayer, const float scale)
: m_mapScreen(mapScreen)
, m_currentLayer(currentLayer)
, m_scale(scale)
{}
protected:
NODISCARD CharFakeGL &getOpenGL() { return m_fakeGL; }
public:
void incrementCount(const Coordinate &c) { getOpenGL().reserve(c); }
void resetCount(const Coordinate &c) { getOpenGL().clear(c); }
NODISCARD bool isVisible(const Coordinate &c, float margin) const;
public:
void drawCharacter(const Coordinate &coordinate, const Color &color, bool fill = true,const QString &dispName = QString());
void drawPreSpammedPath(const Coordinate &coordinate,
const std::vector<Coordinate> &path,
const Color &color);
public:
void reallyDraw(OpenGL &gl, const MapCanvasTextures &textures)
{
m_fakeGL.reallyDraw(gl, textures);
}
};