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