Skip to content

Commit 5834a3d

Browse files
committed
Refactor outlines and make it work
1 parent 886d4c2 commit 5834a3d

File tree

1 file changed

+103
-215
lines changed

1 file changed

+103
-215
lines changed

src/game/client/components/tclient/outlines.cpp

Lines changed: 103 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@
99

1010
#include "outlines.h"
1111

12-
static int ClampedIndex(int x, int y, int w, int h)
13-
{
14-
x = std::clamp(x, 0, w - 1);
15-
y = std::clamp(y, 0, h - 1);
16-
return x + y * w;
17-
}
18-
1912
void COutlines::OnConsoleInit()
2013
{
2114
auto FixColorAlpha = [&](const char *pName, unsigned int &ColorInt) {
@@ -48,37 +41,31 @@ void COutlines::OnRender()
4841
if(!g_Config.m_TcOutline)
4942
return;
5043

51-
auto RenderGameTileOutlines = [&](CTile *pTiles, int w, int h, float Scale, int TileType) {
52-
// Config
53-
float Width;
54-
ColorRGBA Color;
55-
if(TileType == TILE_SOLID)
56-
{
57-
Width = g_Config.m_TcOutlineWidthSolid;
58-
Color = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_TcOutlineColorSolid));
59-
}
60-
else if(TileType == TILE_FREEZE)
61-
{
62-
Width = g_Config.m_TcOutlineWidthFreeze;
63-
Color = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_TcOutlineColorFreeze));
64-
}
65-
else if(TileType == TILE_UNFREEZE)
66-
{
67-
Width = g_Config.m_TcOutlineWidthUnfreeze;
68-
Color = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_TcOutlineColorUnfreeze));
69-
}
70-
else if(TileType == TILE_DEATH)
71-
{
72-
Width = g_Config.m_TcOutlineWidthKill;
73-
Color = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_TcOutlineColorKill));
74-
}
75-
else
76-
{
77-
dbg_assert(false, "Invalid value for TileType");
78-
}
44+
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
45+
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
46+
const float Scale = 32.0f;
47+
48+
Graphics()->TextureClear();
49+
Graphics()->QuadsBegin();
50+
51+
auto DoLayer = [&](CMapItemLayerTilemap *pTMap, int CMapItemLayerTilemap::* pTMapData) {
52+
if(!pTMap)
53+
return;
54+
CTile *pTiles = (CTile *)GameClient()->Layers()->Map()->GetData(pTMap->*pTMapData);
55+
if (!pTiles)
56+
return;
57+
const unsigned Size = GameClient()->Layers()->Map()->GetDataSize(pTMap->*pTMapData);
58+
if (Size < (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTile))
59+
return;
7960

80-
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
81-
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
61+
const int w = pTMap->m_Width;
62+
const int h = pTMap->m_Height;
63+
auto ClampedIndex = [&](int x, int y)
64+
{
65+
x = std::clamp(x, 0, w - 1);
66+
y = std::clamp(y, 0, h - 1);
67+
return x + y * w;
68+
};
8269

8370
int StartY = (int)(ScreenY0 / Scale) - 1;
8471
int StartX = (int)(ScreenX0 / Scale) - 1;
@@ -94,193 +81,94 @@ void COutlines::OnRender()
9481
StartY += EdgeY / 2;
9582
EndY -= EdgeY / 2;
9683
}
97-
Graphics()->TextureClear();
98-
Graphics()->QuadsBegin();
99-
Graphics()->SetColor(Color);
10084

10185
for(int y = StartY; y < EndY; y++)
10286
{
10387
for(int x = StartX; x < EndX; x++)
10488
{
105-
int mx = x;
106-
int my = y;
107-
108-
int c = ClampedIndex(mx, my, w, h);
109-
110-
const unsigned char Index = pTiles[c].m_Index;
111-
const bool IsSolid = Index == TILE_SOLID || Index == TILE_NOHOOK;
112-
const bool IsFreeze = Index == TILE_FREEZE || Index == TILE_DFREEZE;
113-
const bool IsUnfreeze = Index == TILE_UNFREEZE || Index == TILE_DUNFREEZE;
114-
const bool IsKill = Index == TILE_DEATH;
115-
const bool Render = (TileType == TILE_SOLID && IsSolid) ||
116-
(TileType == TILE_FREEZE && IsFreeze) ||
117-
(TileType == TILE_UNFREEZE && IsUnfreeze) ||
118-
(TileType == TILE_DEATH && IsKill);
119-
if(!Render)
120-
continue;
121-
122-
IGraphics::CQuadItem Array[8];
123-
bool Neighbors[8];
124-
int Tile;
125-
if(IsFreeze && TileType == TILE_FREEZE)
126-
{
127-
Tile = pTiles[ClampedIndex(mx - 1, my - 1, w, h)].m_Index;
128-
Neighbors[0] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
129-
Tile = pTiles[ClampedIndex(mx - 0, my - 1, w, h)].m_Index;
130-
Neighbors[1] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
131-
Tile = pTiles[ClampedIndex(mx + 1, my - 1, w, h)].m_Index;
132-
Neighbors[2] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
133-
Tile = pTiles[ClampedIndex(mx - 1, my + 0, w, h)].m_Index;
134-
Neighbors[3] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
135-
Tile = pTiles[ClampedIndex(mx + 1, my + 0, w, h)].m_Index;
136-
Neighbors[4] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
137-
Tile = pTiles[ClampedIndex(mx - 1, my + 1, w, h)].m_Index;
138-
Neighbors[5] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
139-
Tile = pTiles[ClampedIndex(mx + 0, my + 1, w, h)].m_Index;
140-
Neighbors[6] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
141-
Tile = pTiles[ClampedIndex(mx + 1, my + 1, w, h)].m_Index;
142-
Neighbors[7] = Tile == TILE_AIR || Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE;
143-
}
144-
else if(IsSolid && TileType == TILE_SOLID)
145-
{
146-
Tile = pTiles[ClampedIndex(mx - 1, my - 1, w, h)].m_Index;
147-
Neighbors[0] = Tile != TILE_NOHOOK && Tile != Index;
148-
Tile = pTiles[ClampedIndex(mx - 0, my - 1, w, h)].m_Index;
149-
Neighbors[1] = Tile != TILE_NOHOOK && Tile != Index;
150-
Tile = pTiles[ClampedIndex(mx + 1, my - 1, w, h)].m_Index;
151-
Neighbors[2] = Tile != TILE_NOHOOK && Tile != Index;
152-
Tile = pTiles[ClampedIndex(mx - 1, my + 0, w, h)].m_Index;
153-
Neighbors[3] = Tile != TILE_NOHOOK && Tile != Index;
154-
Tile = pTiles[ClampedIndex(mx + 1, my + 0, w, h)].m_Index;
155-
Neighbors[4] = Tile != TILE_NOHOOK && Tile != Index;
156-
Tile = pTiles[ClampedIndex(mx - 1, my + 1, w, h)].m_Index;
157-
Neighbors[5] = Tile != TILE_NOHOOK && Tile != Index;
158-
Tile = pTiles[ClampedIndex(mx + 0, my + 1, w, h)].m_Index;
159-
Neighbors[6] = Tile != TILE_NOHOOK && Tile != Index;
160-
Tile = pTiles[ClampedIndex(mx + 1, my + 1, w, h)].m_Index;
161-
Neighbors[7] = Tile != TILE_NOHOOK && Tile != Index;
162-
}
163-
else if(IsKill && TileType == TILE_DEATH)
164-
{
165-
Tile = pTiles[ClampedIndex(mx - 1, my - 1, w, h)].m_Index;
166-
Neighbors[0] = Tile != TILE_DEATH && Tile != Index;
167-
Tile = pTiles[ClampedIndex(mx - 0, my - 1, w, h)].m_Index;
168-
Neighbors[1] = Tile != TILE_DEATH && Tile != Index;
169-
Tile = pTiles[ClampedIndex(mx + 1, my - 1, w, h)].m_Index;
170-
Neighbors[2] = Tile != TILE_DEATH && Tile != Index;
171-
Tile = pTiles[ClampedIndex(mx - 1, my + 0, w, h)].m_Index;
172-
Neighbors[3] = Tile != TILE_DEATH && Tile != Index;
173-
Tile = pTiles[ClampedIndex(mx + 1, my + 0, w, h)].m_Index;
174-
Neighbors[4] = Tile != TILE_DEATH && Tile != Index;
175-
Tile = pTiles[ClampedIndex(mx - 1, my + 1, w, h)].m_Index;
176-
Neighbors[5] = Tile != TILE_DEATH && Tile != Index;
177-
Tile = pTiles[ClampedIndex(mx + 0, my + 1, w, h)].m_Index;
178-
Neighbors[6] = Tile != TILE_DEATH && Tile != Index;
179-
Tile = pTiles[ClampedIndex(mx + 1, my + 1, w, h)].m_Index;
180-
Neighbors[7] = Tile != TILE_DEATH && Tile != Index;
181-
}
182-
else
183-
{
184-
Tile = pTiles[ClampedIndex(mx - 1, my - 1, w, h)].m_Index;
185-
Neighbors[0] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
186-
Tile = pTiles[ClampedIndex(mx - 0, my - 1, w, h)].m_Index;
187-
Neighbors[1] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
188-
Tile = pTiles[ClampedIndex(mx + 1, my - 1, w, h)].m_Index;
189-
Neighbors[2] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
190-
Tile = pTiles[ClampedIndex(mx - 1, my + 0, w, h)].m_Index;
191-
Neighbors[3] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
192-
Tile = pTiles[ClampedIndex(mx + 1, my + 0, w, h)].m_Index;
193-
Neighbors[4] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
194-
Tile = pTiles[ClampedIndex(mx - 1, my + 1, w, h)].m_Index;
195-
Neighbors[5] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
196-
Tile = pTiles[ClampedIndex(mx + 0, my + 1, w, h)].m_Index;
197-
Neighbors[6] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
198-
Tile = pTiles[ClampedIndex(mx + 1, my + 1, w, h)].m_Index;
199-
Neighbors[7] = Tile != TILE_UNFREEZE && Tile != TILE_DUNFREEZE;
200-
}
201-
202-
int NumQuads = 0;
203-
204-
// Do lonely corners first
205-
if(Neighbors[0] && !Neighbors[1] && !Neighbors[3])
206-
{
207-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale, Width, Width);
208-
NumQuads++;
209-
}
210-
if(Neighbors[2] && !Neighbors[1] && !Neighbors[4])
211-
{
212-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale, Width, Width);
213-
NumQuads++;
214-
}
215-
if(Neighbors[5] && !Neighbors[3] && !Neighbors[6])
216-
{
217-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale + Scale - Width, Width, Width);
218-
NumQuads++;
219-
}
220-
if(Neighbors[7] && !Neighbors[6] && !Neighbors[4])
221-
{
222-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale + Scale - Width, Width, Width);
223-
NumQuads++;
224-
}
225-
// Top
226-
if(Neighbors[1])
227-
{
228-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale, Scale, Width);
229-
NumQuads++;
230-
}
231-
// Bottom
232-
if(Neighbors[6])
233-
{
234-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale + Scale - Width, Scale, Width);
235-
NumQuads++;
236-
}
237-
// Left
238-
if(Neighbors[3])
239-
{
240-
if(!Neighbors[1] && !Neighbors[6])
241-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale, Width, Scale);
242-
else if(!Neighbors[6])
243-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale + Width, Width, Scale - Width);
244-
else if(!Neighbors[1])
245-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale, Width, Scale - Width);
246-
else
247-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale, my * Scale + Width, Width, Scale - Width * 2.0f);
248-
NumQuads++;
249-
}
250-
// Right
251-
if(Neighbors[4])
252-
{
253-
if(!Neighbors[1] && !Neighbors[6])
254-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale, Width, Scale);
255-
else if(!Neighbors[6])
256-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale + Width, Width, Scale - Width);
257-
else if(!Neighbors[1])
258-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale, Width, Scale - Width);
259-
else
260-
Array[NumQuads] = IGraphics::CQuadItem(mx * Scale + Scale - Width, my * Scale + Width, Width, Scale - Width * 2.0f);
261-
NumQuads++;
262-
}
263-
264-
Graphics()->QuadsDrawTL(Array, NumQuads);
89+
const unsigned char Index = pTiles[ClampedIndex(x, y)].m_Index;
90+
auto DoType = [&](const bool &Enable, bool (*IsMatchingType)(unsigned char), const int &Width, const unsigned int &Color) {
91+
if(!Enable)
92+
return;
93+
if(!IsMatchingType(Index))
94+
return;
95+
// Find neighbours
96+
const bool aNeighbors[8] = {
97+
IsMatchingType(pTiles[ClampedIndex(x - 1, y - 1)].m_Index),
98+
IsMatchingType(pTiles[ClampedIndex(x - 0, y - 1)].m_Index),
99+
IsMatchingType(pTiles[ClampedIndex(x + 1, y - 1)].m_Index),
100+
IsMatchingType(pTiles[ClampedIndex(x - 1, y + 0)].m_Index),
101+
IsMatchingType(pTiles[ClampedIndex(x + 1, y + 0)].m_Index),
102+
IsMatchingType(pTiles[ClampedIndex(x - 1, y + 1)].m_Index),
103+
IsMatchingType(pTiles[ClampedIndex(x + 0, y + 1)].m_Index),
104+
IsMatchingType(pTiles[ClampedIndex(x + 1, y + 1)].m_Index),
105+
};
106+
// Figure out edges
107+
IGraphics::CQuadItem aQuads[8];
108+
int NumQuads = 0;
109+
// Lone corners first
110+
if(!aNeighbors[0] && aNeighbors[1] && aNeighbors[3])
111+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Width);
112+
if(!aNeighbors[2] && aNeighbors[1] && aNeighbors[4])
113+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Width);
114+
if(!aNeighbors[5] && aNeighbors[3] && aNeighbors[6])
115+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Scale - Width, Width, Width);
116+
if(!aNeighbors[7] && aNeighbors[6] && aNeighbors[4])
117+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Scale - Width, Width, Width);
118+
// Top
119+
if(!aNeighbors[1])
120+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Scale, Width);
121+
// Bottom
122+
if(!aNeighbors[6])
123+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Scale - Width, Scale, Width);
124+
// Left
125+
if(!aNeighbors[3])
126+
{
127+
if(aNeighbors[1] && aNeighbors[6])
128+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Scale);
129+
else if(aNeighbors[6])
130+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Width, Width, Scale - Width);
131+
else if(aNeighbors[1])
132+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Scale - Width);
133+
else
134+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Width, Width, Scale - Width * 2.0f);
135+
}
136+
// Right
137+
if(!aNeighbors[4])
138+
{
139+
if(aNeighbors[1] && aNeighbors[6])
140+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Scale);
141+
else if(aNeighbors[6])
142+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Width, Width, Scale - Width);
143+
else if(aNeighbors[1])
144+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Scale - Width);
145+
else
146+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Width, Width, Scale - Width * 2.0f);
147+
}
148+
if(NumQuads <= 0)
149+
return;
150+
Graphics()->SetColor(color_cast<ColorRGBA>(ColorHSLA(Color)));
151+
Graphics()->QuadsDrawTL(aQuads, NumQuads);
152+
};
153+
DoType(g_Config.m_TcOutlineSolid, [](unsigned char Tile){ return Tile == TILE_SOLID || Tile == TILE_NOHOOK; }, g_Config.m_TcOutlineWidthSolid, g_Config.m_TcOutlineColorSolid);
154+
DoType(g_Config.m_TcOutlineFreeze, [](unsigned char Tile){ return Tile == TILE_FREEZE || Tile == TILE_DFREEZE || Tile == TILE_LFREEZE; }, g_Config.m_TcOutlineWidthFreeze, g_Config.m_TcOutlineColorFreeze);
155+
DoType(g_Config.m_TcOutlineUnfreeze, [](unsigned char Tile){ return Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE || Tile == TILE_LUNFREEZE; }, g_Config.m_TcOutlineWidthUnfreeze, g_Config.m_TcOutlineColorUnfreeze);
156+
DoType(g_Config.m_TcOutlineKill, [](unsigned char Tile){ return Tile == TILE_DEATH; }, g_Config.m_TcOutlineWidthKill, g_Config.m_TcOutlineColorKill);
157+
DoType(g_Config.m_TcOutlineKill, [](unsigned char Tile){ return Tile == TILE_DEATH; }, g_Config.m_TcOutlineWidthKill, g_Config.m_TcOutlineColorKill);
158+
DoType(g_Config.m_TcOutlineTele, [](unsigned char Tile){ return Tile == TILE_TELEOUT || Tile == TILE_TELEIN || Tile == TILE_TELEINEVIL || Tile == TILE_TELECHECKIN || Tile == TILE_TELECHECKINEVIL || Tile == TILE_TELEINHOOK || Tile == TILE_TELEINWEAPON; }, g_Config.m_TcOutlineWidthTele, g_Config.m_TcOutlineColorTele);
265159
}
266160
}
267-
Graphics()->QuadsEnd();
268-
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
269161
};
270162

271-
auto DoLayer = [&](CMapItemLayerTilemap *pTMap) {
272-
if(!pTMap)
273-
return;
274-
CTile *pTiles = (CTile *)GameClient()->Layers()->Map()->GetData(pTMap->m_Data);
275-
if (!pTiles)
276-
return;
277-
const unsigned Size = GameClient()->Layers()->Map()->GetDataSize(pTMap->m_Data);
278-
if (Size < (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTile))
279-
return;
280-
RenderGameTileOutlines(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, TILE_SOLID);
281-
};
282163
if(g_Config.m_TcOutlineSolid || g_Config.m_TcOutlineFreeze || g_Config.m_TcOutlineUnfreeze || g_Config.m_TcOutlineKill)
283-
DoLayer(GameClient()->Layers()->GameLayer());
164+
{
165+
DoLayer(GameClient()->Layers()->GameLayer(), &CMapItemLayerTilemap::m_Data);
166+
DoLayer(GameClient()->Layers()->FrontLayer(), &CMapItemLayerTilemap::m_Front);
167+
}
284168
if(g_Config.m_TcOutlineTele)
285-
DoLayer(GameClient()->Layers()->TeleLayer());
169+
{
170+
DoLayer(GameClient()->Layers()->TeleLayer(), &CMapItemLayerTilemap::m_Tele);
171+
}
172+
173+
Graphics()->QuadsEnd();
286174
}

0 commit comments

Comments
 (0)