1#ifndef GAME_EDITOR_MAPITEMS_LAYER_TILES_H
2#define GAME_EDITOR_MAPITEMS_LAYER_TILES_H
3
4#include <game/editor/editor_trackers.h>
5#include <map>
6
7#include "layer.h"
8
9struct STileStateChange
10{
11 bool m_Changed;
12 CTile m_Previous;
13 CTile m_Current;
14};
15
16template<typename T>
17using EditorTileStateChangeHistory = std::map<int, std::map<int, T>>;
18
19enum
20{
21 DIRECTION_LEFT = 0,
22 DIRECTION_RIGHT,
23 DIRECTION_UP,
24 DIRECTION_DOWN,
25};
26
27struct RECTi
28{
29 int x, y;
30 int w, h;
31};
32
33class CLayerTiles : public CLayer
34{
35protected:
36 template<typename T>
37 void ShiftImpl(T *pTiles, int Direction, int ShiftBy)
38 {
39 switch(Direction)
40 {
41 case DIRECTION_LEFT:
42 ShiftBy = minimum(a: ShiftBy, b: m_Width);
43 for(int y = 0; y < m_Height; ++y)
44 {
45 if(ShiftBy < m_Width)
46 mem_move(&pTiles[y * m_Width], &pTiles[y * m_Width + ShiftBy], (m_Width - ShiftBy) * sizeof(T));
47 mem_zero(&pTiles[y * m_Width + (m_Width - ShiftBy)], ShiftBy * sizeof(T));
48 }
49 break;
50 case DIRECTION_RIGHT:
51 ShiftBy = minimum(a: ShiftBy, b: m_Width);
52 for(int y = 0; y < m_Height; ++y)
53 {
54 if(ShiftBy < m_Width)
55 mem_move(&pTiles[y * m_Width + ShiftBy], &pTiles[y * m_Width], (m_Width - ShiftBy) * sizeof(T));
56 mem_zero(&pTiles[y * m_Width], ShiftBy * sizeof(T));
57 }
58 break;
59 case DIRECTION_UP:
60 ShiftBy = minimum(a: ShiftBy, b: m_Height);
61 for(int y = ShiftBy; y < m_Height; ++y)
62 {
63 mem_copy(&pTiles[(y - ShiftBy) * m_Width], &pTiles[y * m_Width], m_Width * sizeof(T));
64 }
65 for(int y = m_Height - ShiftBy; y < m_Height; ++y)
66 {
67 mem_zero(&pTiles[y * m_Width], m_Width * sizeof(T));
68 }
69 break;
70 case DIRECTION_DOWN:
71 ShiftBy = minimum(a: ShiftBy, b: m_Height);
72 for(int y = m_Height - ShiftBy - 1; y >= 0; --y)
73 {
74 mem_copy(&pTiles[(y + ShiftBy) * m_Width], &pTiles[y * m_Width], m_Width * sizeof(T));
75 }
76 for(int y = 0; y < ShiftBy; ++y)
77 {
78 mem_zero(&pTiles[y * m_Width], m_Width * sizeof(T));
79 }
80 break;
81 }
82 }
83 template<typename T>
84 void BrushFlipXImpl(T *pTiles)
85 {
86 for(int y = 0; y < m_Height; y++)
87 for(int x = 0; x < m_Width / 2; x++)
88 std::swap(pTiles[y * m_Width + x], pTiles[(y + 1) * m_Width - 1 - x]);
89 }
90 template<typename T>
91 void BrushFlipYImpl(T *pTiles)
92 {
93 for(int y = 0; y < m_Height / 2; y++)
94 for(int x = 0; x < m_Width; x++)
95 std::swap(pTiles[y * m_Width + x], pTiles[(m_Height - 1 - y) * m_Width + x]);
96 }
97
98public:
99 CLayerTiles(CEditor *pEditor, int w, int h);
100 CLayerTiles(const CLayerTiles &Other);
101 ~CLayerTiles();
102
103 virtual CTile GetTile(int x, int y);
104 virtual void SetTile(int x, int y, CTile Tile);
105 void SetTileIgnoreHistory(int x, int y, CTile Tile) const;
106
107 virtual void Resize(int NewW, int NewH);
108 virtual void Shift(int Direction);
109
110 void MakePalette() const;
111 void Render(bool Tileset = false) override;
112
113 int ConvertX(float x) const;
114 int ConvertY(float y) const;
115 void Convert(CUIRect Rect, RECTi *pOut) const;
116 void Snap(CUIRect *pRect) const;
117 void Clamp(RECTi *pRect) const;
118
119 virtual bool IsEntitiesLayer() const override;
120
121 virtual bool IsEmpty(const std::shared_ptr<CLayerTiles> &pLayer);
122 void BrushSelecting(CUIRect Rect) override;
123 int BrushGrab(std::shared_ptr<CLayerGroup> pBrush, CUIRect Rect) override;
124 void FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect) override;
125 void BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy) override;
126 void BrushFlipX() override;
127 void BrushFlipY() override;
128 void BrushRotate(float Amount) override;
129
130 std::shared_ptr<CLayer> Duplicate() const override;
131 const char *TypeName() const override;
132
133 virtual void ShowInfo();
134 CUi::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) override;
135
136 struct SCommonPropState
137 {
138 enum
139 {
140 MODIFIED_SIZE = 1 << 0,
141 MODIFIED_COLOR = 1 << 1,
142 };
143 int m_Modified = 0;
144 int m_Width = -1;
145 int m_Height = -1;
146 int m_Color = 0;
147 };
148 static CUi::EPopupMenuFunctionResult RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector<std::shared_ptr<CLayerTiles>> &vpLayers, std::vector<int> &vLayerIndices);
149
150 void ModifyImageIndex(FIndexModifyFunction pfnFunc) override;
151 void ModifyEnvelopeIndex(FIndexModifyFunction pfnFunc) override;
152
153 void PrepareForSave();
154 void ExtractTiles(int TilemapItemVersion, const CTile *pSavedTiles, size_t SavedTilesSize) const;
155
156 void GetSize(float *pWidth, float *pHeight) override
157 {
158 *pWidth = m_Width * 32.0f;
159 *pHeight = m_Height * 32.0f;
160 }
161
162 void FlagModified(int x, int y, int w, int h);
163
164 int m_Game;
165 int m_Image;
166 int m_Width;
167 int m_Height;
168 CColor m_Color;
169 int m_ColorEnv;
170 int m_ColorEnvOffset;
171 CTile *m_pTiles;
172
173 // DDRace
174
175 int m_AutoMapperConfig;
176 int m_Seed;
177 bool m_AutoAutoMap;
178 int m_Tele;
179 int m_Speedup;
180 int m_Front;
181 int m_Switch;
182 int m_Tune;
183 char m_aFileName[IO_MAX_PATH_LENGTH];
184
185 EditorTileStateChangeHistory<STileStateChange> m_TilesHistory;
186 inline virtual void ClearHistory() { m_TilesHistory.clear(); }
187
188 static bool HasAutomapEffect(ETilesProp Prop);
189
190protected:
191 void RecordStateChange(int x, int y, CTile Previous, CTile Tile);
192
193 void ShowPreventUnusedTilesWarning();
194
195 friend class CAutoMapper;
196};
197
198#endif
199