1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef GAME_EDITOR_MAPITEMS_MAP_H
4#define GAME_EDITOR_MAPITEMS_MAP_H
5
6#include <base/types.h>
7
8#include <engine/shared/datafile.h>
9#include <engine/shared/jobs.h>
10
11#include <game/editor/editor_history.h>
12#include <game/editor/editor_server_settings.h>
13#include <game/editor/editor_trackers.h>
14#include <game/editor/mapitems/envelope.h>
15#include <game/editor/mapitems/layer.h>
16
17#include <functional>
18#include <memory>
19#include <vector>
20
21class CEditor;
22class CEditorImage;
23class CEditorSound;
24class CLayerFront;
25class CLayerGroup;
26class CLayerGame;
27class CLayerImage;
28class CLayerSound;
29class CLayerSpeedup;
30class CLayerSwitch;
31class CLayerTele;
32class CLayerTune;
33class CQuad;
34class IEditorEnvelopeReference;
35
36class CDataFileWriterFinishJob : public IJob
37{
38 char m_aRealFilename[IO_MAX_PATH_LENGTH];
39 char m_aTempFilename[IO_MAX_PATH_LENGTH];
40 CDataFileWriter m_Writer;
41
42 void Run() override;
43
44public:
45 CDataFileWriterFinishJob(const char *pRealFilename, const char *pTempFilename, CDataFileWriter &&Writer);
46 const char *GetRealFilename() const { return m_aRealFilename; }
47 const char *GetTempFilename() const { return m_aTempFilename; }
48};
49
50using FErrorHandler = std::function<void(const char *pErrorMessage)>;
51
52class CEditorMap
53{
54public:
55 explicit CEditorMap(CEditor *pEditor) :
56 m_EditorHistory(this),
57 m_ServerSettingsHistory(this),
58 m_EnvelopeEditorHistory(this),
59 m_QuadTracker(this),
60 m_EnvOpTracker(this),
61 m_LayerGroupPropTracker(this),
62 m_LayerPropTracker(this),
63 m_LayerTilesCommonPropTracker(this),
64 m_LayerTilesPropTracker(this),
65 m_LayerQuadPropTracker(this),
66 m_LayerSoundsPropTracker(this),
67 m_SoundSourceOperationTracker(this),
68 m_SoundSourcePropTracker(this),
69 m_SoundSourceRectShapePropTracker(this),
70 m_SoundSourceCircleShapePropTracker(this),
71 m_pEditor(pEditor)
72 {
73 }
74
75 const CEditor *Editor() const { return m_pEditor; }
76 CEditor *Editor() { return m_pEditor; }
77
78 char m_aFilename[IO_MAX_PATH_LENGTH];
79 bool m_ValidSaveFilename;
80 /**
81 * Map has unsaved changes for manual save.
82 */
83 bool m_Modified;
84 /**
85 * Map has unsaved changes for autosave.
86 */
87 bool m_ModifiedAuto;
88 float m_LastModifiedTime;
89 float m_LastSaveTime;
90 void OnModify();
91 void ResetModifiedState();
92
93 std::vector<std::shared_ptr<CLayerGroup>> m_vpGroups;
94 std::vector<std::shared_ptr<CEditorImage>> m_vpImages;
95 std::vector<std::shared_ptr<CEnvelope>> m_vpEnvelopes;
96 std::vector<std::shared_ptr<CEditorSound>> m_vpSounds;
97 std::vector<CEditorMapSetting> m_vSettings;
98
99 std::shared_ptr<CLayerGroup> m_pGameGroup;
100 std::shared_ptr<CLayerGame> m_pGameLayer;
101 std::shared_ptr<CLayerTele> m_pTeleLayer;
102 std::shared_ptr<CLayerSpeedup> m_pSpeedupLayer;
103 std::shared_ptr<CLayerFront> m_pFrontLayer;
104 std::shared_ptr<CLayerSwitch> m_pSwitchLayer;
105 std::shared_ptr<CLayerTune> m_pTuneLayer;
106
107 class CMapInfo
108 {
109 public:
110 char m_aAuthor[32];
111 char m_aVersion[16];
112 char m_aCredits[128];
113 char m_aLicense[32];
114
115 void Reset();
116 void Copy(const CMapInfo &Source);
117 };
118 CMapInfo m_MapInfo;
119 CMapInfo m_MapInfoTmp;
120
121 // Undo/Redo
122 CEditorHistory m_EditorHistory;
123 CEditorHistory m_ServerSettingsHistory;
124 CEditorHistory m_EnvelopeEditorHistory;
125 CQuadEditTracker m_QuadTracker;
126 CEnvelopeEditorOperationTracker m_EnvOpTracker;
127 CLayerGroupPropTracker m_LayerGroupPropTracker;
128 CLayerPropTracker m_LayerPropTracker;
129 CLayerTilesCommonPropTracker m_LayerTilesCommonPropTracker;
130 CLayerTilesPropTracker m_LayerTilesPropTracker;
131 CLayerQuadsPropTracker m_LayerQuadPropTracker;
132 CLayerSoundsPropTracker m_LayerSoundsPropTracker;
133 CSoundSourceOperationTracker m_SoundSourceOperationTracker;
134 CSoundSourcePropTracker m_SoundSourcePropTracker;
135 CSoundSourceRectShapePropTracker m_SoundSourceRectShapePropTracker;
136 CSoundSourceCircleShapePropTracker m_SoundSourceCircleShapePropTracker;
137
138 // Selections
139 int m_SelectedGroup;
140 std::vector<int> m_vSelectedLayers;
141 std::vector<int> m_vSelectedQuads;
142 int m_SelectedQuadPoints;
143 int m_SelectedQuadEnvelope;
144 int m_CurrentQuadIndex;
145 int m_SelectedEnvelope;
146 bool m_UpdateEnvPointInfo;
147 std::vector<std::pair<int, int>> m_vSelectedEnvelopePoints;
148 std::pair<int, int> m_SelectedTangentInPoint;
149 std::pair<int, int> m_SelectedTangentOutPoint;
150 int m_SelectedImage;
151 int m_SelectedSound;
152 int m_SelectedSoundSource;
153
154 int m_ShiftBy;
155
156 // Quad knife
157 class CQuadKnife
158 {
159 public:
160 bool m_Active;
161 int m_SelectedQuadIndex;
162 int m_Count;
163 vec2 m_aPoints[4];
164 };
165 CQuadKnife m_QuadKnife;
166
167 // Housekeeping
168 void Clean();
169 void CreateDefault();
170 void CheckIntegrity();
171
172 // Indices
173 void ModifyImageIndex(const FIndexModifyFunction &IndexModifyFunction);
174 void ModifyEnvelopeIndex(const FIndexModifyFunction &IndexModifyFunction);
175 void ModifySoundIndex(const FIndexModifyFunction &IndexModifyFunction);
176
177 // I/O
178 bool Save(const char *pFilename, const FErrorHandler &ErrorHandler);
179 bool PerformPreSaveSanityChecks(const FErrorHandler &ErrorHandler);
180 bool Load(const char *pFilename, int StorageType, const FErrorHandler &ErrorHandler);
181 bool Append(const char *pFilename, int StorageType, bool IgnoreHistory, const FErrorHandler &ErrorHandler);
182 void PerformSanityChecks(const FErrorHandler &ErrorHandler);
183 bool PerformAutosave(const FErrorHandler &ErrorHandler);
184
185 // Groups
186 std::shared_ptr<CLayerGroup> SelectedGroup() const;
187 std::shared_ptr<CLayerGroup> NewGroup();
188 int MoveGroup(int IndexFrom, int IndexTo);
189 void DeleteGroup(int Index);
190 void MakeGameGroup(std::shared_ptr<CLayerGroup> pGroup);
191
192 // Layers
193 std::shared_ptr<CLayer> SelectedLayer(int Index) const;
194 std::shared_ptr<CLayer> SelectedLayerType(int Index, int Type) const;
195 void SelectLayer(int LayerIndex, int GroupIndex = -1);
196 void AddSelectedLayer(int LayerIndex);
197 void SelectNextLayer();
198 void SelectPreviousLayer();
199 void SelectGameLayer();
200 void MakeGameLayer(const std::shared_ptr<CLayer> &pLayer);
201 void MakeTeleLayer(const std::shared_ptr<CLayer> &pLayer);
202 void MakeSpeedupLayer(const std::shared_ptr<CLayer> &pLayer);
203 void MakeFrontLayer(const std::shared_ptr<CLayer> &pLayer);
204 void MakeSwitchLayer(const std::shared_ptr<CLayer> &pLayer);
205 void MakeTuneLayer(const std::shared_ptr<CLayer> &pLayer);
206
207 // Quads
208 std::vector<CQuad *> SelectedQuads();
209 bool IsQuadSelected(int Index) const;
210 int FindSelectedQuadIndex(int Index) const;
211 void SelectQuad(int Index);
212 void ToggleSelectQuad(int Index);
213 void DeselectQuads();
214 bool IsQuadCornerSelected(int Index) const;
215 bool IsQuadPointSelected(int QuadIndex, int Index) const;
216 void SelectQuadPoint(int QuadIndex, int Index);
217 void ToggleSelectQuadPoint(int QuadIndex, int Index);
218 void DeselectQuadPoints();
219 void DeleteSelectedQuads();
220
221 // Envelopes
222 std::shared_ptr<CEnvelope> NewEnvelope(CEnvelope::EType Type);
223 void InsertEnvelope(int Index, std::shared_ptr<CEnvelope> &pEnvelope);
224 void UpdateEnvelopeReferences(int Index, std::shared_ptr<CEnvelope> &pEnvelope, std::vector<std::shared_ptr<IEditorEnvelopeReference>> &vpEditorObjectReferences);
225 std::vector<std::shared_ptr<IEditorEnvelopeReference>> DeleteEnvelope(int Index);
226 int MoveEnvelope(int IndexFrom, int IndexTo);
227 template<typename F>
228 std::vector<std::shared_ptr<IEditorEnvelopeReference>> VisitEnvelopeReferences(F &&Visitor);
229 bool IsEnvelopeUsed(int EnvelopeIndex) const;
230 void RemoveUnusedEnvelopes();
231
232 // Envelope points
233 int FindEnvPointIndex(int Index, int Channel) const;
234 void SelectEnvPoint(int Index);
235 void SelectEnvPoint(int Index, int Channel);
236 void ToggleEnvPoint(int Index, int Channel);
237 bool IsEnvPointSelected(int Index, int Channel) const;
238 bool IsEnvPointSelected(int Index) const;
239 void DeselectEnvPoints();
240 bool IsTangentSelected() const;
241 bool IsTangentOutPointSelected(int Index, int Channel) const;
242 bool IsTangentOutSelected() const;
243 void SelectTangentOutPoint(int Index, int Channel);
244 bool IsTangentInPointSelected(int Index, int Channel) const;
245 bool IsTangentInSelected() const;
246 void SelectTangentInPoint(int Index, int Channel);
247 std::pair<CFixedTime, int> SelectedEnvelopeTimeAndValue() const;
248
249 // Images
250 std::shared_ptr<CEditorImage> SelectedImage() const;
251 void SelectImage(const std::shared_ptr<CEditorImage> &pImage);
252 void SelectNextImage();
253 void SelectPreviousImage();
254 bool IsImageUsed(int ImageIndex) const;
255 std::vector<int> SortImages();
256
257 // Sounds
258 std::shared_ptr<CEditorSound> SelectedSound() const;
259 void SelectSound(const std::shared_ptr<CEditorSound> &pSound);
260 void SelectNextSound();
261 void SelectPreviousSound();
262 bool IsSoundUsed(int SoundIndex) const;
263 CSoundSource *SelectedSoundSource() const;
264
265 void PlaceBorderTiles();
266
267private:
268 CEditor *m_pEditor;
269};
270
271#endif
272