1#include "map_grid.h"
2
3#include "editor.h"
4
5#include <engine/keys.h>
6
7static constexpr int MIN_GRID_FACTOR = 1;
8static constexpr int MAX_GRID_FACTOR = 15;
9
10void CMapGrid::OnReset()
11{
12 m_GridActive = false;
13 m_GridFactor = 1;
14}
15
16void CMapGrid::OnRender(CUIRect View)
17{
18 if(!m_GridActive)
19 {
20 return;
21 }
22
23 std::shared_ptr<CLayerGroup> pGroup = Editor()->GetSelectedGroup();
24 if(!pGroup)
25 {
26 return;
27 }
28
29 pGroup->MapScreen();
30
31 float aGroupPoints[4];
32 pGroup->Mapping(pPoints: aGroupPoints);
33
34 float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
35 Graphics()->GetScreen(pTopLeftX: &ScreenX0, pTopLeftY: &ScreenY0, pBottomRightX: &ScreenX1, pBottomRightY: &ScreenY1);
36
37 const int LineDistance = GridLineDistance();
38
39 const int XOffset = aGroupPoints[0] / LineDistance;
40 const int YOffset = aGroupPoints[1] / LineDistance;
41 const int XGridOffset = XOffset % m_GridFactor;
42 const int YGridOffset = YOffset % m_GridFactor;
43
44 const int NumColumns = (int)std::ceil(x: (ScreenX1 - ScreenX0) / LineDistance) + 1;
45 const int NumRows = (int)std::ceil(x: (ScreenY1 - ScreenY0) / LineDistance) + 1;
46
47 Graphics()->TextureClear();
48
49 IGraphics::CLineItemBatch LineItemBatch;
50 if(m_GridFactor > 1)
51 {
52 Graphics()->LinesBatchBegin(pBatch: &LineItemBatch);
53 Graphics()->SetColor(r: 1.0f, g: 1.0f, b: 1.0f, a: 0.15f);
54 for(int y = 0; y < NumRows; y++)
55 {
56 if((y + YGridOffset) % m_GridFactor == 0)
57 {
58 continue;
59 }
60 const float PosY = LineDistance * (y + YOffset);
61 const IGraphics::CLineItem Line = IGraphics::CLineItem(ScreenX0, PosY, ScreenX1, PosY);
62 Graphics()->LinesBatchDraw(pBatch: &LineItemBatch, pArray: &Line, Num: 1);
63 }
64 for(int x = 0; x < NumColumns; x++)
65 {
66 if((x + XGridOffset) % m_GridFactor == 0)
67 {
68 continue;
69 }
70 const float PosX = LineDistance * (x + XOffset);
71 const IGraphics::CLineItem Line = IGraphics::CLineItem(PosX, ScreenY0, PosX, ScreenY1);
72 Graphics()->LinesBatchDraw(pBatch: &LineItemBatch, pArray: &Line, Num: 1);
73 }
74 Graphics()->LinesBatchEnd(pBatch: &LineItemBatch);
75 }
76
77 Graphics()->LinesBatchBegin(pBatch: &LineItemBatch);
78 Graphics()->SetColor(r: 1.0f, g: 0.3f, b: 0.3f, a: 0.3f);
79 for(int y = 0; y < NumRows; y++)
80 {
81 if((y + YGridOffset) % m_GridFactor != 0)
82 {
83 continue;
84 }
85 const float PosY = LineDistance * (y + YOffset);
86 const IGraphics::CLineItem Line = IGraphics::CLineItem(ScreenX0, PosY, ScreenX1, PosY);
87 Graphics()->LinesBatchDraw(pBatch: &LineItemBatch, pArray: &Line, Num: 1);
88 }
89 for(int x = 0; x < NumColumns; x++)
90 {
91 if((x + XGridOffset) % m_GridFactor != 0)
92 {
93 continue;
94 }
95 const float PosX = LineDistance * (x + XOffset);
96 const IGraphics::CLineItem Line = IGraphics::CLineItem(PosX, ScreenY0, PosX, ScreenY1);
97 Graphics()->LinesBatchDraw(pBatch: &LineItemBatch, pArray: &Line, Num: 1);
98 }
99 Graphics()->LinesBatchEnd(pBatch: &LineItemBatch);
100}
101
102int CMapGrid::GridLineDistance() const
103{
104 const float ZoomValue = Editor()->MapView()->Zoom()->GetValue();
105 if(ZoomValue <= 10.0f)
106 return 4;
107 else if(ZoomValue <= 50.0f)
108 return 8;
109 else if(ZoomValue <= 100.0f)
110 return 16;
111 else if(ZoomValue <= 250.0f)
112 return 32;
113 else if(ZoomValue <= 450.0f)
114 return 64;
115 else if(ZoomValue <= 850.0f)
116 return 128;
117 else if(ZoomValue <= 1550.0f)
118 return 256;
119 else
120 return 512;
121}
122
123void CMapGrid::SnapToGrid(vec2 &Position) const
124{
125 const int GridDistance = GridLineDistance() * m_GridFactor;
126 Position.x = (int)((Position.x + (Position.x >= 0 ? 1.0f : -1.0f) * GridDistance / 2) / GridDistance) * GridDistance;
127 Position.y = (int)((Position.y + (Position.y >= 0 ? 1.0f : -1.0f) * GridDistance / 2) / GridDistance) * GridDistance;
128}
129
130bool CMapGrid::IsEnabled() const
131{
132 return m_GridActive;
133}
134
135void CMapGrid::Toggle()
136{
137 m_GridActive = !m_GridActive;
138}
139
140int CMapGrid::Factor() const
141{
142 return m_GridFactor;
143}
144
145void CMapGrid::SetFactor(int Factor)
146{
147 m_GridFactor = std::clamp(val: Factor, lo: MIN_GRID_FACTOR, hi: MAX_GRID_FACTOR);
148}
149
150void CMapGrid::DoSettingsPopup(vec2 Position)
151{
152 Ui()->DoPopupMenu(pId: &m_PopupGridSettingsId, X: Position.x, Y: Position.y, Width: 120.0f, Height: 37.0f, pContext: this, pfnFunc: PopupGridSettings);
153}
154
155CUi::EPopupMenuFunctionResult CMapGrid::PopupGridSettings(void *pContext, CUIRect View, bool Active)
156{
157 CMapGrid *pMapGrid = static_cast<CMapGrid *>(pContext);
158
159 enum
160 {
161 PROP_SIZE = 0,
162 NUM_PROPS,
163 };
164 CProperty aProps[] = {
165 {"Size", pMapGrid->Factor(), PROPTYPE_INT, MIN_GRID_FACTOR, MAX_GRID_FACTOR},
166 {nullptr},
167 };
168
169 static int s_aIds[NUM_PROPS];
170 int NewVal;
171 int Prop = pMapGrid->Editor()->DoProperties(pToolbox: &View, pProps: aProps, pIds: s_aIds, pNewVal: &NewVal);
172
173 if(Prop == PROP_SIZE)
174 {
175 pMapGrid->SetFactor(NewVal);
176 }
177
178 CUIRect Button;
179 View.HSplitBottom(Cut: 12.0f, pTop: &View, pBottom: &Button);
180
181 static char s_DefaultButton;
182 if(pMapGrid->Editor()->DoButton_Ex(pId: &s_DefaultButton, pText: "Default", Checked: 0, pRect: &Button, Flags: BUTTONFLAG_LEFT, pToolTip: "Reset to normal grid size.", Corners: IGraphics::CORNER_ALL))
183 {
184 pMapGrid->SetFactor(1);
185 }
186
187 return CUi::POPUP_KEEP_OPEN;
188}
189