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