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