1#include "layer_group.h"
2
3#include <base/math.h>
4
5#include <engine/shared/config.h>
6
7#include <game/editor/editor.h>
8
9CLayerGroup::CLayerGroup(CEditorMap *pMap) :
10 CMapObject(pMap)
11{
12 m_vpLayers.clear();
13 m_aName[0] = 0;
14 m_Visible = true;
15 m_Collapse = false;
16 m_GameGroup = false;
17 m_OffsetX = 0;
18 m_OffsetY = 0;
19 m_ParallaxX = 100;
20 m_ParallaxY = 100;
21
22 m_UseClipping = 0;
23 m_ClipX = 0;
24 m_ClipY = 0;
25 m_ClipW = 0;
26 m_ClipH = 0;
27}
28
29void CLayerGroup::OnAttach(CEditorMap *pMap)
30{
31 CMapObject::OnAttach(pMap);
32 for(const auto &pLayer : m_vpLayers)
33 {
34 pLayer->OnAttach(pMap);
35 }
36}
37
38void CLayerGroup::Convert(CUIRect *pRect) const
39{
40 pRect->x += m_OffsetX;
41 pRect->y += m_OffsetY;
42}
43
44void CLayerGroup::Mapping(float *pPoints) const
45{
46 float NormalParallaxZoom = std::clamp(val: (double)(maximum(a: m_ParallaxX, b: m_ParallaxY)), lo: 0., hi: 100.);
47 float ParallaxZoom = Editor()->m_PreviewZoom ? NormalParallaxZoom : 100.0f;
48
49 Graphics()->MapScreenToWorld(
50 CenterX: Editor()->MapView()->GetWorldOffset().x, CenterY: Editor()->MapView()->GetWorldOffset().y,
51 ParallaxX: m_ParallaxX, ParallaxY: m_ParallaxY, ParallaxZoom, OffsetX: m_OffsetX, OffsetY: m_OffsetY,
52 Aspect: Graphics()->ScreenAspect(), Zoom: Editor()->MapView()->GetWorldZoom(), pPoints);
53
54 pPoints[0] += Editor()->MapView()->GetEditorOffset().x;
55 pPoints[1] += Editor()->MapView()->GetEditorOffset().y;
56 pPoints[2] += Editor()->MapView()->GetEditorOffset().x;
57 pPoints[3] += Editor()->MapView()->GetEditorOffset().y;
58}
59
60void CLayerGroup::MapScreen()
61{
62 float aPoints[4];
63 Mapping(pPoints: aPoints);
64 Graphics()->MapScreen(TopLeftX: aPoints[0], TopLeftY: aPoints[1], BottomRightX: aPoints[2], BottomRightY: aPoints[3]);
65}
66
67void CLayerGroup::Render()
68{
69 MapScreen();
70
71 if(m_UseClipping)
72 {
73 float aPoints[4];
74 Map()->m_pGameGroup->Mapping(pPoints: aPoints);
75 float ScreenWidth = aPoints[2] - aPoints[0];
76 float ScreenHeight = aPoints[3] - aPoints[1];
77 float Left = m_ClipX - aPoints[0];
78 float Top = m_ClipY - aPoints[1];
79 float Right = (m_ClipX + m_ClipW) - aPoints[0];
80 float Bottom = (m_ClipY + m_ClipH) - aPoints[1];
81
82 int ClipX = (int)std::round(x: Left * Graphics()->ScreenWidth() / ScreenWidth);
83 int ClipY = (int)std::round(x: Top * Graphics()->ScreenHeight() / ScreenHeight);
84
85 Graphics()->ClipEnable(
86 x: ClipX,
87 y: ClipY,
88 w: (int)std::round(x: Right * Graphics()->ScreenWidth() / ScreenWidth) - ClipX,
89 h: (int)std::round(x: Bottom * Graphics()->ScreenHeight() / ScreenHeight) - ClipY);
90 }
91
92 for(auto &pLayer : m_vpLayers)
93 {
94 if(pLayer->m_Visible)
95 {
96 if(pLayer->m_Type == LAYERTYPE_TILES)
97 {
98 std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(r: pLayer);
99
100 if(g_Config.m_EdShowIngameEntities &&
101 pLayer->IsEntitiesLayer() &&
102 (pLayer == Map()->m_pGameLayer || pLayer == Map()->m_pFrontLayer || pLayer == Map()->m_pSwitchLayer))
103 {
104 if(pLayer != Map()->m_pSwitchLayer)
105 Editor()->RenderGameEntities(pTiles);
106 Editor()->RenderSwitchEntities(pTiles);
107 }
108
109 if(pTiles->m_HasGame || pTiles->m_HasFront || pTiles->m_HasTele || pTiles->m_HasSpeedup || pTiles->m_HasTune || pTiles->m_HasSwitch)
110 continue;
111 }
112 if(Editor()->m_ShowDetail || !(pLayer->m_Flags & LAYERFLAG_DETAIL))
113 pLayer->Render();
114 }
115 }
116
117 for(auto &pLayer : m_vpLayers)
118 {
119 if(pLayer->m_Visible && pLayer->m_Type == LAYERTYPE_TILES && !pLayer->IsEntitiesLayer())
120 {
121 std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(r: pLayer);
122 if(pTiles->m_HasGame || pTiles->m_HasFront || pTiles->m_HasTele || pTiles->m_HasSpeedup || pTiles->m_HasTune || pTiles->m_HasSwitch)
123 {
124 pLayer->Render();
125 }
126 }
127 }
128
129 if(m_UseClipping)
130 Graphics()->ClipDisable();
131}
132
133void CLayerGroup::AddLayer(const std::shared_ptr<CLayer> &pLayer)
134{
135 Map()->OnModify();
136 m_vpLayers.push_back(x: pLayer);
137}
138
139void CLayerGroup::DeleteLayer(int Index)
140{
141 if(Index < 0 || Index >= (int)m_vpLayers.size())
142 return;
143 m_vpLayers.erase(position: m_vpLayers.begin() + Index);
144 Map()->OnModify();
145}
146
147void CLayerGroup::DuplicateLayer(int Index)
148{
149 if(Index < 0 || Index >= (int)m_vpLayers.size())
150 return;
151
152 std::shared_ptr<CLayer> pDup = m_vpLayers[Index]->Duplicate();
153 m_vpLayers.insert(position: m_vpLayers.begin() + Index + 1, x: pDup);
154
155 Map()->OnModify();
156}
157
158void CLayerGroup::GetSize(float *pWidth, float *pHeight) const
159{
160 *pWidth = 0.0f;
161 *pHeight = 0.0f;
162 for(const auto &pLayer : m_vpLayers)
163 {
164 float LayerWidth, LayerHeight;
165 pLayer->GetSize(pWidth: &LayerWidth, pHeight: &LayerHeight);
166 *pWidth = maximum(a: *pWidth, b: LayerWidth);
167 *pHeight = maximum(a: *pHeight, b: LayerHeight);
168 }
169}
170
171int CLayerGroup::MoveLayer(int IndexFrom, int IndexTo)
172{
173 if(IndexFrom < 0 || IndexFrom >= (int)m_vpLayers.size())
174 return IndexFrom;
175 if(IndexTo < 0 || IndexTo >= (int)m_vpLayers.size())
176 return IndexFrom;
177 if(IndexFrom == IndexTo)
178 return IndexFrom;
179 Map()->OnModify();
180 auto pMovedLayer = m_vpLayers[IndexFrom];
181 m_vpLayers.erase(position: m_vpLayers.begin() + IndexFrom);
182 m_vpLayers.insert(position: m_vpLayers.begin() + IndexTo, x: pMovedLayer);
183 return IndexTo;
184}
185
186bool CLayerGroup::IsEmpty() const
187{
188 return m_vpLayers.empty();
189}
190
191void CLayerGroup::Clear()
192{
193 m_vpLayers.clear();
194}
195
196void CLayerGroup::ModifyImageIndex(const FIndexModifyFunction &IndexModifyFunction)
197{
198 for(auto &pLayer : m_vpLayers)
199 {
200 pLayer->ModifyImageIndex(IndexModifyFunction);
201 }
202}
203
204void CLayerGroup::ModifyEnvelopeIndex(const FIndexModifyFunction &IndexModifyFunction)
205{
206 for(auto &pLayer : m_vpLayers)
207 {
208 pLayer->ModifyEnvelopeIndex(IndexModifyFunction);
209 }
210}
211
212void CLayerGroup::ModifySoundIndex(const FIndexModifyFunction &IndexModifyFunction)
213{
214 for(auto &pLayer : m_vpLayers)
215 {
216 pLayer->ModifySoundIndex(IndexModifyFunction);
217 }
218}
219