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