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