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