Skip to content

Commit 39265a2

Browse files
committed
Refactor outlines and make it work
1 parent 886d4c2 commit 39265a2

File tree

1 file changed

+97
-208
lines changed

1 file changed

+97
-208
lines changed

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

Lines changed: 97 additions & 208 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,35 +41,26 @@ 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+
auto DoLayer = [&](CMapItemLayerTilemap *pTMap) {
45+
if(!pTMap)
46+
return;
47+
CTile *pTiles = (CTile *)GameClient()->Layers()->Map()->GetData(pTMap->m_Data);
48+
if (!pTiles)
49+
return;
50+
const unsigned Size = GameClient()->Layers()->Map()->GetDataSize(pTMap->m_Data);
51+
if (Size < (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTile))
52+
return;
7953

54+
const int w = pTMap->m_Width;
55+
const int h = pTMap->m_Height;
56+
auto ClampedIndex = [&](int x, int y)
57+
{
58+
x = std::clamp(x, 0, w - 1);
59+
y = std::clamp(y, 0, h - 1);
60+
return x + y * w;
61+
};
62+
const float Scale = 32.0f;
63+
8064
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
8165
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
8266

@@ -94,193 +78,98 @@ void COutlines::OnRender()
9478
StartY += EdgeY / 2;
9579
EndY -= EdgeY / 2;
9680
}
81+
9782
Graphics()->TextureClear();
9883
Graphics()->QuadsBegin();
99-
Graphics()->SetColor(Color);
100-
10184
for(int y = StartY; y < EndY; y++)
10285
{
10386
for(int x = StartX; x < EndX; x++)
10487
{
105-
int mx = x;
106-
int my = y;
10788

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 = [&](bool (*IsMatchingType)(unsigned char), const int &Width, const unsigned int &Color) {
91+
if(!IsMatchingType(Index))
92+
return;
93+
// Find neighbours
94+
const bool aNeighbors[8] = {
95+
IsMatchingType(pTiles[ClampedIndex(x - 1, y - 1)].m_Index),
96+
IsMatchingType(pTiles[ClampedIndex(x - 0, y - 1)].m_Index),
97+
IsMatchingType(pTiles[ClampedIndex(x + 1, y - 1)].m_Index),
98+
IsMatchingType(pTiles[ClampedIndex(x - 1, y + 0)].m_Index),
99+
IsMatchingType(pTiles[ClampedIndex(x + 1, y + 0)].m_Index),
100+
IsMatchingType(pTiles[ClampedIndex(x - 1, y + 1)].m_Index),
101+
IsMatchingType(pTiles[ClampedIndex(x + 0, y + 1)].m_Index),
102+
IsMatchingType(pTiles[ClampedIndex(x + 1, y + 1)].m_Index),
103+
};
104+
// Figure out edges
105+
IGraphics::CQuadItem aQuads[8];
106+
int NumQuads = 0;
107+
// Lone corners first
108+
if(!aNeighbors[0] && aNeighbors[1] && aNeighbors[3])
109+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Width);
110+
if(!aNeighbors[2] && aNeighbors[1] && aNeighbors[4])
111+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Width);
112+
if(!aNeighbors[5] && aNeighbors[3] && aNeighbors[6])
113+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Scale - Width, Width, Width);
114+
if(!aNeighbors[7] && aNeighbors[6] && aNeighbors[4])
115+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Scale - Width, Width, Width);
116+
// Top
117+
if(!aNeighbors[1])
118+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Scale, Width);
119+
// Bottom
120+
if(!aNeighbors[6])
121+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Scale - Width, Scale, Width);
122+
// Left
123+
if(!aNeighbors[3])
124+
{
125+
if(aNeighbors[1] && aNeighbors[6])
126+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Scale);
127+
else if(aNeighbors[6])
128+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Width, Width, Scale - Width);
129+
else if(aNeighbors[1])
130+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale, Width, Scale - Width);
131+
else
132+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale, y * Scale + Width, Width, Scale - Width * 2.0f);
133+
}
134+
// Right
135+
if(!aNeighbors[4])
136+
{
137+
if(aNeighbors[1] && aNeighbors[6])
138+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Scale);
139+
else if(aNeighbors[6])
140+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Width, Width, Scale - Width);
141+
else if(aNeighbors[1])
142+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale, Width, Scale - Width);
143+
else
144+
aQuads[NumQuads++] = IGraphics::CQuadItem(x * Scale + Scale - Width, y * Scale + Width, Width, Scale - Width * 2.0f);
145+
}
146+
if(NumQuads <= 0)
147+
return;
148+
Graphics()->SetColor(color_cast<ColorRGBA>(ColorHSLA(Color)));
149+
Graphics()->QuadsDrawTL(aQuads, NumQuads);
150+
};
151+
if(g_Config.m_TcOutlineSolid)
152+
DoType([](unsigned char Tile){ return Tile == TILE_SOLID || Tile == TILE_NOHOOK; }, g_Config.m_TcOutlineWidthSolid, g_Config.m_TcOutlineColorSolid);
153+
if(g_Config.m_TcOutlineFreeze)
154+
DoType([](unsigned char Tile){ return Tile == TILE_FREEZE || Tile == TILE_DFREEZE || Tile == TILE_LFREEZE; }, g_Config.m_TcOutlineWidthFreeze, g_Config.m_TcOutlineColorFreeze);
155+
if(g_Config.m_TcOutlineUnfreeze)
156+
DoType([](unsigned char Tile){ return Tile == TILE_UNFREEZE || Tile == TILE_DUNFREEZE || Tile == TILE_LUNFREEZE; }, g_Config.m_TcOutlineWidthUnfreeze, g_Config.m_TcOutlineColorUnfreeze);
157+
if(g_Config.m_TcOutlineKill)
158+
DoType([](unsigned char Tile){ return Tile == TILE_DEATH; }, g_Config.m_TcOutlineWidthKill, g_Config.m_TcOutlineColorKill);
159+
if(g_Config.m_TcOutlineKill)
160+
DoType([](unsigned char Tile){ return Tile == TILE_DEATH; }, g_Config.m_TcOutlineWidthKill, g_Config.m_TcOutlineColorKill);
161+
if(g_Config.m_TcOutlineTele)
162+
DoType([](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);
265163
}
266164
}
267165
Graphics()->QuadsEnd();
268166
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
269167
};
270-
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-
};
282168
if(g_Config.m_TcOutlineSolid || g_Config.m_TcOutlineFreeze || g_Config.m_TcOutlineUnfreeze || g_Config.m_TcOutlineKill)
169+
{
283170
DoLayer(GameClient()->Layers()->GameLayer());
171+
DoLayer(GameClient()->Layers()->FrontLayer());
172+
}
284173
if(g_Config.m_TcOutlineTele)
285174
DoLayer(GameClient()->Layers()->TeleLayer());
286175
}

0 commit comments

Comments
 (0)