1#include "proof_mode.h"
2
3#include <game/client/components/menu_background.h>
4
5#include "editor.h"
6
7void CProofMode::Init(CEditor *pEditor)
8{
9 CEditorComponent::Init(pEditor);
10 SetMenuBackgroundPositionNames();
11 OnReset();
12 OnMapLoad();
13}
14
15void CProofMode::OnReset()
16{
17 m_ProofBorders = PROOF_BORDER_OFF;
18 m_CurrentMenuProofIndex = 0;
19}
20
21void CProofMode::OnMapLoad()
22{
23 m_vMenuBackgroundCollisions = {};
24 ResetMenuBackgroundPositions();
25}
26
27void CProofMode::SetMenuBackgroundPositionNames()
28{
29 m_vpMenuBackgroundPositionNames.resize(new_size: CMenuBackground::NUM_POS);
30 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_START] = "start";
31 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_INTERNET] = "browser(internet)";
32 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_LAN] = "browser(lan)";
33 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_DEMOS] = "demos";
34 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_NEWS] = "news";
35 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_FAVORITES] = "favorites";
36 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_LANGUAGE] = "settings(language)";
37 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_GENERAL] = "settings(general)";
38 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_PLAYER] = "settings(player)";
39 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_TEE] = "settings(tee)";
40 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_APPEARANCE] = "settings(appearance)";
41 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_CONTROLS] = "settings(controls)";
42 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_GRAPHICS] = "settings(graphics)";
43 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_SOUND] = "settings(sound)";
44 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_DDNET] = "settings(ddnet)";
45 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_ASSETS] = "settings(assets)";
46 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_CUSTOM0] = "custom(1)";
47 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_CUSTOM1] = "custom(2)";
48 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_CUSTOM2] = "custom(3)";
49 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_CUSTOM3] = "custom(4)";
50 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_BROWSER_CUSTOM4] = "custom(5)";
51 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_RESERVED0] = "reserved settings(1)";
52 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_SETTINGS_RESERVED1] = "reserved settings(2)";
53 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_RESERVED0] = "reserved(1)";
54 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_RESERVED1] = "reserved(2)";
55 m_vpMenuBackgroundPositionNames[CMenuBackground::POS_RESERVED2] = "reserved(3)";
56}
57
58void CProofMode::ResetMenuBackgroundPositions()
59{
60 std::array<vec2, CMenuBackground::NUM_POS> aBackgroundPositions = GenerateMenuBackgroundPositions();
61 m_vMenuBackgroundPositions.assign(first: aBackgroundPositions.begin(), last: aBackgroundPositions.end());
62
63 if(Editor()->m_Map.m_pGameLayer)
64 {
65 for(int y = 0; y < Editor()->m_Map.m_pGameLayer->m_Height; ++y)
66 {
67 for(int x = 0; x < Editor()->m_Map.m_pGameLayer->m_Width; ++x)
68 {
69 CTile Tile = Editor()->m_Map.m_pGameLayer->GetTile(x, y);
70 if(Tile.m_Index >= TILE_TIME_CHECKPOINT_FIRST && Tile.m_Index <= TILE_TIME_CHECKPOINT_LAST)
71 {
72 int ArrayIndex = clamp<int>(val: (Tile.m_Index - TILE_TIME_CHECKPOINT_FIRST), lo: 0, hi: CMenuBackground::NUM_POS);
73 m_vMenuBackgroundPositions[ArrayIndex] = vec2(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
74 }
75
76 x += Tile.m_Skip;
77 }
78 }
79 }
80
81 m_vMenuBackgroundCollisions.clear();
82 m_vMenuBackgroundCollisions.resize(new_size: m_vMenuBackgroundPositions.size());
83 for(size_t i = 0; i < m_vMenuBackgroundPositions.size(); i++)
84 {
85 for(size_t j = i + 1; j < m_vMenuBackgroundPositions.size(); j++)
86 {
87 if(i != j && distance(a: m_vMenuBackgroundPositions[i], b: m_vMenuBackgroundPositions[j]) < 0.001f)
88 m_vMenuBackgroundCollisions.at(n: i).push_back(x: j);
89 }
90 }
91}
92
93void CProofMode::RenderScreenSizes()
94{
95 const vec2 WorldOffset = Editor()->MapView()->GetWorldOffset();
96
97 // render screen sizes
98 if(m_ProofBorders != PROOF_BORDER_OFF && !Editor()->MapView()->m_ShowPicker)
99 {
100 std::shared_ptr<CLayerGroup> pGameGroup = Editor()->m_Map.m_pGameGroup;
101 pGameGroup->MapScreen();
102
103 Graphics()->TextureClear();
104 Graphics()->LinesBegin();
105
106 // possible screen sizes (white border)
107 float aLastPoints[4];
108 float Start = 1.0f; // 9.0f/16.0f;
109 float End = 16.0f / 9.0f;
110 const int NumSteps = 20;
111 for(int i = 0; i <= NumSteps; i++)
112 {
113 float aPoints[4];
114 float Aspect = Start + (End - Start) * (i / (float)NumSteps);
115
116 float Zoom = (m_ProofBorders == PROOF_BORDER_MENU) ? 0.7f : 1.0f;
117 RenderTools()->MapScreenToWorld(
118 CenterX: WorldOffset.x, CenterY: WorldOffset.y,
119 ParallaxX: 100.0f, ParallaxY: 100.0f, ParallaxZoom: 100.0f, OffsetX: 0.0f, OffsetY: 0.0f, Aspect, Zoom, pPoints: aPoints);
120
121 if(i == 0)
122 {
123 IGraphics::CLineItem aArray[2] = {
124 IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[2], aPoints[1]),
125 IGraphics::CLineItem(aPoints[0], aPoints[3], aPoints[2], aPoints[3])};
126 Graphics()->LinesDraw(pArray: aArray, Num: std::size(aArray));
127 }
128
129 if(i != 0)
130 {
131 IGraphics::CLineItem aArray[4] = {
132 IGraphics::CLineItem(aPoints[0], aPoints[1], aLastPoints[0], aLastPoints[1]),
133 IGraphics::CLineItem(aPoints[2], aPoints[1], aLastPoints[2], aLastPoints[1]),
134 IGraphics::CLineItem(aPoints[0], aPoints[3], aLastPoints[0], aLastPoints[3]),
135 IGraphics::CLineItem(aPoints[2], aPoints[3], aLastPoints[2], aLastPoints[3])};
136 Graphics()->LinesDraw(pArray: aArray, Num: std::size(aArray));
137 }
138
139 if(i == NumSteps)
140 {
141 IGraphics::CLineItem aArray[2] = {
142 IGraphics::CLineItem(aPoints[0], aPoints[1], aPoints[0], aPoints[3]),
143 IGraphics::CLineItem(aPoints[2], aPoints[1], aPoints[2], aPoints[3])};
144 Graphics()->LinesDraw(pArray: aArray, Num: std::size(aArray));
145 }
146
147 mem_copy(dest: aLastPoints, source: aPoints, size: sizeof(aPoints));
148 }
149
150 // two screen sizes (green and red border)
151 {
152 Graphics()->SetColor(r: 1, g: 0, b: 0, a: 1);
153 for(int i = 0; i < 2; i++)
154 {
155 float aPoints[4];
156 const float aAspects[] = {4.0f / 3.0f, 16.0f / 10.0f, 5.0f / 4.0f, 16.0f / 9.0f};
157 float Aspect = aAspects[i];
158
159 float Zoom = (m_ProofBorders == PROOF_BORDER_MENU) ? 0.7f : 1.0f;
160 RenderTools()->MapScreenToWorld(
161 CenterX: WorldOffset.x, CenterY: WorldOffset.y,
162 ParallaxX: 100.0f, ParallaxY: 100.0f, ParallaxZoom: 100.0f, OffsetX: 0.0f, OffsetY: 0.0f, Aspect, Zoom, pPoints: aPoints);
163
164 CUIRect r;
165 r.x = aPoints[0];
166 r.y = aPoints[1];
167 r.w = aPoints[2] - aPoints[0];
168 r.h = aPoints[3] - aPoints[1];
169
170 IGraphics::CLineItem aArray[4] = {
171 IGraphics::CLineItem(r.x, r.y, r.x + r.w, r.y),
172 IGraphics::CLineItem(r.x + r.w, r.y, r.x + r.w, r.y + r.h),
173 IGraphics::CLineItem(r.x + r.w, r.y + r.h, r.x, r.y + r.h),
174 IGraphics::CLineItem(r.x, r.y + r.h, r.x, r.y)};
175 Graphics()->LinesDraw(pArray: aArray, Num: std::size(aArray));
176 Graphics()->SetColor(r: 0, g: 1, b: 0, a: 1);
177 }
178 }
179 Graphics()->LinesEnd();
180
181 // tee position (blue circle) and other screen positions
182 {
183 Graphics()->TextureClear();
184 Graphics()->QuadsBegin();
185 Graphics()->SetColor(r: 0, g: 0, b: 1, a: 0.3f);
186 Graphics()->DrawCircle(CenterX: WorldOffset.x, CenterY: WorldOffset.y - 3.0f, Radius: 20.0f, Segments: 32);
187
188 if(m_ProofBorders == PROOF_BORDER_MENU)
189 {
190 Graphics()->SetColor(r: 0, g: 1, b: 0, a: 0.3f);
191
192 std::set<int> Indices;
193 for(int i = 0; i < (int)m_vMenuBackgroundPositions.size(); i++)
194 Indices.insert(x: i);
195
196 while(!Indices.empty())
197 {
198 int i = *Indices.begin();
199 Indices.erase(x: i);
200 for(int k : m_vMenuBackgroundCollisions.at(n: i))
201 Indices.erase(x: k);
202
203 vec2 Pos = m_vMenuBackgroundPositions[i];
204 Pos += WorldOffset - m_vMenuBackgroundPositions[m_CurrentMenuProofIndex];
205
206 if(Pos == WorldOffset)
207 continue;
208
209 Graphics()->DrawCircle(CenterX: Pos.x, CenterY: Pos.y - 3.0f, Radius: 20.0f, Segments: 32);
210 }
211 }
212
213 Graphics()->QuadsEnd();
214 }
215 }
216}
217
218bool CProofMode::IsEnabled() const
219{
220 return m_ProofBorders != PROOF_BORDER_OFF;
221}
222
223bool CProofMode::IsModeMenu() const
224{
225 return m_ProofBorders == PROOF_BORDER_MENU;
226}
227
228bool CProofMode::IsModeIngame() const
229{
230 return m_ProofBorders == PROOF_BORDER_INGAME;
231}
232
233void CProofMode::Toggle()
234{
235 m_ProofBorders = m_ProofBorders == PROOF_BORDER_OFF ? PROOF_BORDER_INGAME : PROOF_BORDER_OFF;
236}
237
238void CProofMode::SetModeIngame()
239{
240 m_ProofBorders = PROOF_BORDER_INGAME;
241}
242
243void CProofMode::SetModeMenu()
244{
245 m_ProofBorders = PROOF_BORDER_MENU;
246}
247