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_EDITOR_H |
4 | #define GAME_EDITOR_EDITOR_H |
5 | |
6 | #include <base/bezier.h> |
7 | #include <base/system.h> |
8 | |
9 | #include <game/client/render.h> |
10 | #include <game/client/ui.h> |
11 | #include <game/client/ui_listbox.h> |
12 | #include <game/mapitems.h> |
13 | |
14 | #include <game/editor/mapitems/envelope.h> |
15 | #include <game/editor/mapitems/layer.h> |
16 | #include <game/editor/mapitems/layer_front.h> |
17 | #include <game/editor/mapitems/layer_game.h> |
18 | #include <game/editor/mapitems/layer_group.h> |
19 | #include <game/editor/mapitems/layer_quads.h> |
20 | #include <game/editor/mapitems/layer_sounds.h> |
21 | #include <game/editor/mapitems/layer_speedup.h> |
22 | #include <game/editor/mapitems/layer_switch.h> |
23 | #include <game/editor/mapitems/layer_tele.h> |
24 | #include <game/editor/mapitems/layer_tiles.h> |
25 | #include <game/editor/mapitems/layer_tune.h> |
26 | |
27 | #include <engine/console.h> |
28 | #include <engine/editor.h> |
29 | #include <engine/engine.h> |
30 | #include <engine/graphics.h> |
31 | #include <engine/shared/datafile.h> |
32 | #include <engine/shared/jobs.h> |
33 | |
34 | #include "auto_map.h" |
35 | #include "editor_history.h" |
36 | #include "editor_server_settings.h" |
37 | #include "editor_trackers.h" |
38 | #include "editor_ui.h" |
39 | #include "layer_selector.h" |
40 | #include "map_view.h" |
41 | #include "smooth_value.h" |
42 | |
43 | #include <deque> |
44 | #include <functional> |
45 | #include <map> |
46 | #include <memory> |
47 | #include <string> |
48 | #include <vector> |
49 | |
50 | typedef std::function<void(int *pIndex)> FIndexModifyFunction; |
51 | template<typename T> |
52 | using FDropdownRenderCallback = std::function<void(const T &, char (&aOutput)[128], std::vector<STextColorSplit> &)>; |
53 | |
54 | // CEditor SPECIFIC |
55 | enum |
56 | { |
57 | MODE_LAYERS = 0, |
58 | MODE_IMAGES, |
59 | MODE_SOUNDS, |
60 | NUM_MODES, |
61 | |
62 | DIALOG_NONE = 0, |
63 | DIALOG_FILE, |
64 | DIALOG_MAPSETTINGS_ERROR |
65 | }; |
66 | |
67 | class CEditorImage; |
68 | class CEditorSound; |
69 | |
70 | class CEditorMap |
71 | { |
72 | void MakeGameGroup(std::shared_ptr<CLayerGroup> pGroup); |
73 | void MakeGameLayer(const std::shared_ptr<CLayer> &pLayer); |
74 | |
75 | public: |
76 | CEditor *m_pEditor; |
77 | |
78 | CEditorMap() |
79 | { |
80 | Clean(); |
81 | } |
82 | |
83 | ~CEditorMap() |
84 | { |
85 | Clean(); |
86 | } |
87 | |
88 | bool m_Modified; // unsaved changes in manual save |
89 | bool m_ModifiedAuto; // unsaved changes in autosave |
90 | float m_LastModifiedTime; |
91 | float m_LastSaveTime; |
92 | float m_LastAutosaveUpdateTime; |
93 | void OnModify(); |
94 | |
95 | std::vector<std::shared_ptr<CLayerGroup>> m_vpGroups; |
96 | std::vector<std::shared_ptr<CEditorImage>> m_vpImages; |
97 | std::vector<std::shared_ptr<CEnvelope>> m_vpEnvelopes; |
98 | std::vector<std::shared_ptr<CEditorSound>> m_vpSounds; |
99 | |
100 | class CMapInfo |
101 | { |
102 | public: |
103 | char m_aAuthor[32]; |
104 | char m_aVersion[16]; |
105 | char m_aCredits[128]; |
106 | char m_aLicense[32]; |
107 | |
108 | void Reset() |
109 | { |
110 | m_aAuthor[0] = '\0'; |
111 | m_aVersion[0] = '\0'; |
112 | m_aCredits[0] = '\0'; |
113 | m_aLicense[0] = '\0'; |
114 | } |
115 | |
116 | void Copy(const CMapInfo &Source) |
117 | { |
118 | str_copy(dst&: m_aAuthor, src: Source.m_aAuthor); |
119 | str_copy(dst&: m_aVersion, src: Source.m_aVersion); |
120 | str_copy(dst&: m_aCredits, src: Source.m_aCredits); |
121 | str_copy(dst&: m_aLicense, src: Source.m_aLicense); |
122 | } |
123 | }; |
124 | CMapInfo m_MapInfo; |
125 | CMapInfo m_MapInfoTmp; |
126 | |
127 | std::vector<CEditorMapSetting> m_vSettings; |
128 | |
129 | std::shared_ptr<class CLayerGame> m_pGameLayer; |
130 | std::shared_ptr<CLayerGroup> m_pGameGroup; |
131 | |
132 | std::shared_ptr<CEnvelope> NewEnvelope(CEnvelope::EType Type) |
133 | { |
134 | OnModify(); |
135 | std::shared_ptr<CEnvelope> pEnv = std::make_shared<CEnvelope>(args&: Type); |
136 | m_vpEnvelopes.push_back(x: pEnv); |
137 | return pEnv; |
138 | } |
139 | |
140 | void DeleteEnvelope(int Index); |
141 | void SwapEnvelopes(int Index0, int Index1); |
142 | template<typename F> |
143 | void VisitEnvelopeReferences(F &&Visitor); |
144 | |
145 | std::shared_ptr<CLayerGroup> NewGroup() |
146 | { |
147 | OnModify(); |
148 | std::shared_ptr<CLayerGroup> pGroup = std::make_shared<CLayerGroup>(); |
149 | pGroup->m_pMap = this; |
150 | m_vpGroups.push_back(x: pGroup); |
151 | return pGroup; |
152 | } |
153 | |
154 | int SwapGroups(int Index0, int Index1) |
155 | { |
156 | if(Index0 < 0 || Index0 >= (int)m_vpGroups.size()) |
157 | return Index0; |
158 | if(Index1 < 0 || Index1 >= (int)m_vpGroups.size()) |
159 | return Index0; |
160 | if(Index0 == Index1) |
161 | return Index0; |
162 | OnModify(); |
163 | std::swap(a&: m_vpGroups[Index0], b&: m_vpGroups[Index1]); |
164 | return Index1; |
165 | } |
166 | |
167 | void DeleteGroup(int Index) |
168 | { |
169 | if(Index < 0 || Index >= (int)m_vpGroups.size()) |
170 | return; |
171 | OnModify(); |
172 | m_vpGroups.erase(position: m_vpGroups.begin() + Index); |
173 | } |
174 | |
175 | void ModifyImageIndex(FIndexModifyFunction pfnFunc) |
176 | { |
177 | OnModify(); |
178 | for(auto &pGroup : m_vpGroups) |
179 | pGroup->ModifyImageIndex(Func: pfnFunc); |
180 | } |
181 | |
182 | void ModifyEnvelopeIndex(FIndexModifyFunction pfnFunc) |
183 | { |
184 | OnModify(); |
185 | for(auto &pGroup : m_vpGroups) |
186 | pGroup->ModifyEnvelopeIndex(Func: pfnFunc); |
187 | } |
188 | |
189 | void ModifySoundIndex(FIndexModifyFunction pfnFunc) |
190 | { |
191 | OnModify(); |
192 | for(auto &pGroup : m_vpGroups) |
193 | pGroup->ModifySoundIndex(Func: pfnFunc); |
194 | } |
195 | |
196 | void Clean(); |
197 | void CreateDefault(IGraphics::CTextureHandle EntitiesTexture); |
198 | |
199 | // io |
200 | bool Save(const char *pFilename); |
201 | bool Load(const char *pFilename, int StorageType, const std::function<void(const char *pErrorMessage)> &ErrorHandler); |
202 | void PerformSanityChecks(const std::function<void(const char *pErrorMessage)> &ErrorHandler); |
203 | |
204 | // DDRace |
205 | |
206 | std::shared_ptr<class CLayerTele> m_pTeleLayer; |
207 | std::shared_ptr<class CLayerSpeedup> m_pSpeedupLayer; |
208 | std::shared_ptr<class CLayerFront> m_pFrontLayer; |
209 | std::shared_ptr<class CLayerSwitch> m_pSwitchLayer; |
210 | std::shared_ptr<class CLayerTune> m_pTuneLayer; |
211 | void MakeTeleLayer(const std::shared_ptr<CLayer> &pLayer); |
212 | void MakeSpeedupLayer(const std::shared_ptr<CLayer> &pLayer); |
213 | void MakeFrontLayer(const std::shared_ptr<CLayer> &pLayer); |
214 | void MakeSwitchLayer(const std::shared_ptr<CLayer> &pLayer); |
215 | void MakeTuneLayer(const std::shared_ptr<CLayer> &pLayer); |
216 | }; |
217 | |
218 | struct CProperty |
219 | { |
220 | const char *m_pName; |
221 | int m_Value; |
222 | int m_Type; |
223 | int m_Min; |
224 | int m_Max; |
225 | }; |
226 | |
227 | enum |
228 | { |
229 | PROPTYPE_NULL = 0, |
230 | PROPTYPE_BOOL, |
231 | PROPTYPE_INT, |
232 | PROPTYPE_ANGLE_SCROLL, |
233 | PROPTYPE_COLOR, |
234 | PROPTYPE_IMAGE, |
235 | PROPTYPE_ENVELOPE, |
236 | PROPTYPE_SHIFT, |
237 | PROPTYPE_SOUND, |
238 | PROPTYPE_AUTOMAPPER, |
239 | }; |
240 | |
241 | class CDataFileWriterFinishJob : public IJob |
242 | { |
243 | char m_aRealFileName[IO_MAX_PATH_LENGTH]; |
244 | char m_aTempFileName[IO_MAX_PATH_LENGTH]; |
245 | CDataFileWriter m_Writer; |
246 | |
247 | void Run() override |
248 | { |
249 | m_Writer.Finish(); |
250 | } |
251 | |
252 | public: |
253 | CDataFileWriterFinishJob(const char *pRealFileName, const char *pTempFileName, CDataFileWriter &&Writer) : |
254 | m_Writer(std::move(Writer)) |
255 | { |
256 | str_copy(dst&: m_aRealFileName, src: pRealFileName); |
257 | str_copy(dst&: m_aTempFileName, src: pTempFileName); |
258 | } |
259 | |
260 | const char *GetRealFileName() const { return m_aRealFileName; } |
261 | const char *GetTempFileName() const { return m_aTempFileName; } |
262 | }; |
263 | |
264 | class CEditor : public IEditor |
265 | { |
266 | class IInput *m_pInput = nullptr; |
267 | class IClient *m_pClient = nullptr; |
268 | class IConfigManager *m_pConfigManager = nullptr; |
269 | class CConfig *m_pConfig = nullptr; |
270 | class IConsole *m_pConsole = nullptr; |
271 | class IEngine *m_pEngine = nullptr; |
272 | class IGraphics *m_pGraphics = nullptr; |
273 | class ITextRender *m_pTextRender = nullptr; |
274 | class ISound *m_pSound = nullptr; |
275 | class IStorage *m_pStorage = nullptr; |
276 | CRenderTools m_RenderTools; |
277 | CUi m_UI; |
278 | |
279 | std::vector<std::reference_wrapper<CEditorComponent>> m_vComponents; |
280 | CMapView m_MapView; |
281 | CLayerSelector m_LayerSelector; |
282 | |
283 | bool m_EditorWasUsedBefore = false; |
284 | |
285 | IGraphics::CTextureHandle m_EntitiesTexture; |
286 | |
287 | IGraphics::CTextureHandle m_FrontTexture; |
288 | IGraphics::CTextureHandle m_TeleTexture; |
289 | IGraphics::CTextureHandle m_SpeedupTexture; |
290 | IGraphics::CTextureHandle m_SwitchTexture; |
291 | IGraphics::CTextureHandle m_TuneTexture; |
292 | |
293 | int GetTextureUsageFlag() const; |
294 | |
295 | enum EPreviewState |
296 | { |
297 | PREVIEW_UNLOADED, |
298 | PREVIEW_LOADED, |
299 | PREVIEW_ERROR, |
300 | }; |
301 | |
302 | std::shared_ptr<CLayerGroup> m_apSavedBrushes[10]; |
303 | static const ColorRGBA ms_DefaultPropColor; |
304 | |
305 | public: |
306 | class IInput *Input() const { return m_pInput; } |
307 | class IClient *Client() const { return m_pClient; } |
308 | class IConfigManager *ConfigManager() const { return m_pConfigManager; } |
309 | class CConfig *Config() const { return m_pConfig; } |
310 | class IConsole *Console() const { return m_pConsole; } |
311 | class IEngine *Engine() const { return m_pEngine; } |
312 | class IGraphics *Graphics() const { return m_pGraphics; } |
313 | class ISound *Sound() const { return m_pSound; } |
314 | class ITextRender *TextRender() const { return m_pTextRender; } |
315 | class IStorage *Storage() const { return m_pStorage; } |
316 | CUi *Ui() { return &m_UI; } |
317 | CRenderTools *RenderTools() { return &m_RenderTools; } |
318 | |
319 | CMapView *MapView() { return &m_MapView; } |
320 | const CMapView *MapView() const { return &m_MapView; } |
321 | CLayerSelector *LayerSelector() { return &m_LayerSelector; } |
322 | |
323 | CEditor() : |
324 | m_ZoomEnvelopeX(1.0f, 0.1f, 600.0f), |
325 | m_ZoomEnvelopeY(640.0f, 0.1f, 32000.0f), |
326 | m_MapSettingsCommandContext(m_MapSettingsBackend.NewContext(pLineInput: &m_SettingsCommandInput)) |
327 | { |
328 | m_EntitiesTexture.Invalidate(); |
329 | m_FrontTexture.Invalidate(); |
330 | m_TeleTexture.Invalidate(); |
331 | m_SpeedupTexture.Invalidate(); |
332 | m_SwitchTexture.Invalidate(); |
333 | m_TuneTexture.Invalidate(); |
334 | |
335 | m_Mode = MODE_LAYERS; |
336 | m_Dialog = 0; |
337 | |
338 | m_BrushColorEnabled = true; |
339 | |
340 | m_aFileName[0] = '\0'; |
341 | m_aFileNamePending[0] = '\0'; |
342 | m_aFileSaveName[0] = '\0'; |
343 | m_ValidSaveFilename = false; |
344 | |
345 | m_PopupEventActivated = false; |
346 | m_PopupEventWasActivated = false; |
347 | |
348 | m_FileDialogStorageType = 0; |
349 | m_FileDialogLastPopulatedStorageType = 0; |
350 | m_pFileDialogTitle = nullptr; |
351 | m_pFileDialogButtonText = nullptr; |
352 | m_pFileDialogUser = nullptr; |
353 | m_aFileDialogCurrentFolder[0] = '\0'; |
354 | m_aFileDialogCurrentLink[0] = '\0'; |
355 | m_aFilesSelectedName[0] = '\0'; |
356 | m_pFileDialogPath = m_aFileDialogCurrentFolder; |
357 | m_FileDialogOpening = false; |
358 | m_FilesSelectedIndex = -1; |
359 | |
360 | m_FilePreviewImage.Invalidate(); |
361 | m_FilePreviewSound = -1; |
362 | m_FilePreviewState = PREVIEW_UNLOADED; |
363 | |
364 | m_ToolbarPreviewSound = -1; |
365 | |
366 | m_SelectEntitiesImage = "DDNet" ; |
367 | |
368 | m_ResetZoomEnvelope = true; |
369 | m_OffsetEnvelopeX = 0.1f; |
370 | m_OffsetEnvelopeY = 0.5f; |
371 | |
372 | m_ShowMousePointer = true; |
373 | |
374 | m_GuiActive = true; |
375 | m_PreviewZoom = false; |
376 | |
377 | m_ShowTileInfo = SHOW_TILE_OFF; |
378 | m_ShowDetail = true; |
379 | m_Animate = false; |
380 | m_AnimateStart = 0; |
381 | m_AnimateTime = 0; |
382 | m_AnimateSpeed = 1; |
383 | m_AnimateUpdatePopup = false; |
384 | |
385 | m_ShowEnvelopePreview = SHOWENV_NONE; |
386 | m_SelectedQuadEnvelope = -1; |
387 | |
388 | m_vSelectedEnvelopePoints = {}; |
389 | m_UpdateEnvPointInfo = false; |
390 | m_SelectedTangentInPoint = std::pair(-1, -1); |
391 | m_SelectedTangentOutPoint = std::pair(-1, -1); |
392 | m_CurrentQuadIndex = -1; |
393 | |
394 | m_QuadKnifeActive = false; |
395 | m_QuadKnifeCount = 0; |
396 | mem_zero(block: m_aQuadKnifePoints, size: sizeof(m_aQuadKnifePoints)); |
397 | |
398 | for(size_t i = 0; i < std::size(m_aSavedColors); ++i) |
399 | { |
400 | m_aSavedColors[i] = color_cast<ColorRGBA>(hsl: ColorHSLA(i / (float)std::size(m_aSavedColors), 1.0f, 0.5f)); |
401 | } |
402 | |
403 | m_CheckerTexture.Invalidate(); |
404 | m_BackgroundTexture.Invalidate(); |
405 | for(int i = 0; i < NUM_CURSORS; i++) |
406 | m_aCursorTextures[i].Invalidate(); |
407 | |
408 | m_CursorType = CURSOR_NORMAL; |
409 | |
410 | ms_pUiGotContext = nullptr; |
411 | |
412 | // DDRace |
413 | |
414 | m_TeleNumber = 1; |
415 | m_TeleCheckpointNumber = 1; |
416 | m_SwitchNum = 1; |
417 | m_TuningNum = 1; |
418 | m_SwitchDelay = 0; |
419 | m_SpeedupForce = 50; |
420 | m_SpeedupMaxSpeed = 0; |
421 | m_SpeedupAngle = 0; |
422 | m_LargeLayerWasWarned = false; |
423 | m_PreventUnusedTilesWasWarned = false; |
424 | m_AllowPlaceUnusedTiles = 0; |
425 | m_BrushDrawDestructive = true; |
426 | } |
427 | |
428 | class CHoverTile |
429 | { |
430 | public: |
431 | CHoverTile(int Group, int Layer, int x, int y, const CTile Tile) : |
432 | m_Group(Group), |
433 | m_Layer(Layer), |
434 | m_X(x), |
435 | m_Y(y), |
436 | m_Tile(Tile) |
437 | { |
438 | } |
439 | |
440 | int m_Group; |
441 | int m_Layer; |
442 | int m_X; |
443 | int m_Y; |
444 | const CTile m_Tile; |
445 | }; |
446 | std::vector<CHoverTile> m_vHoverTiles; |
447 | const std::vector<CHoverTile> &HoverTiles() const { return m_vHoverTiles; } |
448 | |
449 | void Init() override; |
450 | void OnUpdate() override; |
451 | void OnRender() override; |
452 | void OnActivate() override; |
453 | void OnWindowResize() override; |
454 | void OnClose() override; |
455 | void OnDialogClose() override; |
456 | bool HasUnsavedData() const override { return m_Map.m_Modified; } |
457 | void UpdateMentions() override { m_Mentions++; } |
458 | void ResetMentions() override { m_Mentions = 0; } |
459 | void OnIngameMoved() override { m_IngameMoved = true; } |
460 | void ResetIngameMoved() override { m_IngameMoved = false; } |
461 | |
462 | void HandleCursorMovement(); |
463 | void OnMouseMove(vec2 MousePos); |
464 | void HandleAutosave(); |
465 | bool PerformAutosave(); |
466 | void HandleWriterFinishJobs(); |
467 | |
468 | void RefreshFilteredFileList(); |
469 | void FilelistPopulate(int StorageType, bool KeepSelection = false); |
470 | void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText, |
471 | const char *pBasepath, bool FilenameAsDefault, |
472 | bool (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser); |
473 | struct SStringKeyComparator |
474 | { |
475 | bool operator()(const char *pLhs, const char *pRhs) const |
476 | { |
477 | return str_comp(a: pLhs, b: pRhs) < 0; |
478 | } |
479 | }; |
480 | std::map<const char *, CUi::SMessagePopupContext *, SStringKeyComparator> ; |
481 | void ShowFileDialogError(const char *pFormat, ...) |
482 | GNUC_ATTRIBUTE((format(printf, 2, 3))); |
483 | |
484 | void Reset(bool CreateDefault = true); |
485 | bool Save(const char *pFilename) override; |
486 | bool Load(const char *pFilename, int StorageType) override; |
487 | bool HandleMapDrop(const char *pFilename, int StorageType) override; |
488 | bool Append(const char *pFilename, int StorageType, bool IgnoreHistory = false); |
489 | void LoadCurrentMap(); |
490 | void Render(); |
491 | |
492 | void RenderPressedKeys(CUIRect View); |
493 | void RenderSavingIndicator(CUIRect View); |
494 | void (); |
495 | void UpdateColorPipette(); |
496 | void RenderMousePointer(); |
497 | |
498 | std::vector<CQuad *> GetSelectedQuads(); |
499 | std::shared_ptr<CLayer> GetSelectedLayerType(int Index, int Type) const; |
500 | std::shared_ptr<CLayer> GetSelectedLayer(int Index) const; |
501 | std::shared_ptr<CLayerGroup> GetSelectedGroup() const; |
502 | CSoundSource *GetSelectedSource() const; |
503 | void SelectLayer(int LayerIndex, int GroupIndex = -1); |
504 | void AddSelectedLayer(int LayerIndex); |
505 | void SelectQuad(int Index); |
506 | void ToggleSelectQuad(int Index); |
507 | void DeselectQuads(); |
508 | void DeselectQuadPoints(); |
509 | void SelectQuadPoint(int QuadIndex, int Index); |
510 | void ToggleSelectQuadPoint(int QuadIndex, int Index); |
511 | void DeleteSelectedQuads(); |
512 | bool IsQuadSelected(int Index) const; |
513 | bool IsQuadCornerSelected(int Index) const; |
514 | bool IsQuadPointSelected(int QuadIndex, int Index) const; |
515 | int FindSelectedQuadIndex(int Index) const; |
516 | |
517 | int FindEnvPointIndex(int Index, int Channel) const; |
518 | void SelectEnvPoint(int Index); |
519 | void SelectEnvPoint(int Index, int Channel); |
520 | void ToggleEnvPoint(int Index, int Channel); |
521 | bool IsEnvPointSelected(int Index, int Channel) const; |
522 | bool IsEnvPointSelected(int Index) const; |
523 | void DeselectEnvPoints(); |
524 | void SelectTangentOutPoint(int Index, int Channel); |
525 | bool IsTangentOutPointSelected(int Index, int Channel) const; |
526 | void SelectTangentInPoint(int Index, int Channel); |
527 | bool IsTangentInPointSelected(int Index, int Channel) const; |
528 | bool IsTangentInSelected() const; |
529 | bool IsTangentOutSelected() const; |
530 | bool IsTangentSelected() const; |
531 | std::pair<int, int> EnvGetSelectedTimeAndValue() const; |
532 | |
533 | template<typename E> |
534 | SEditResult<E> DoPropertiesWithState(CUIRect *pToolbox, CProperty *pProps, int *pIds, int *pNewVal, const std::vector<ColorRGBA> &vColors = {}); |
535 | int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIds, int *pNewVal, const std::vector<ColorRGBA> &vColors = {}); |
536 | |
537 | CUi::SColorPickerPopupContext ; |
538 | const void * = nullptr; |
539 | void DoColorPickerButton(const void *pId, const CUIRect *pRect, ColorRGBA Color, const std::function<void(ColorRGBA Color)> &SetColor); |
540 | |
541 | int m_Mode; |
542 | int m_Dialog; |
543 | char m_aTooltip[256] = "" ; |
544 | |
545 | bool m_BrushColorEnabled; |
546 | |
547 | char m_aFileName[IO_MAX_PATH_LENGTH]; |
548 | char m_aFileNamePending[IO_MAX_PATH_LENGTH]; |
549 | char m_aFileSaveName[IO_MAX_PATH_LENGTH]; |
550 | bool m_ValidSaveFilename; |
551 | |
552 | enum |
553 | { |
554 | POPEVENT_EXIT = 0, |
555 | POPEVENT_LOAD, |
556 | POPEVENT_LOADCURRENT, |
557 | POPEVENT_LOADDROP, |
558 | POPEVENT_NEW, |
559 | POPEVENT_SAVE, |
560 | POPEVENT_SAVE_COPY, |
561 | POPEVENT_SAVE_IMG, |
562 | POPEVENT_SAVE_SOUND, |
563 | POPEVENT_LARGELAYER, |
564 | POPEVENT_PREVENTUNUSEDTILES, |
565 | POPEVENT_IMAGEDIV16, |
566 | POPEVENT_IMAGE_MAX, |
567 | POPEVENT_SOUND_MAX, |
568 | POPEVENT_PLACE_BORDER_TILES, |
569 | POPEVENT_PIXELART_BIG_IMAGE, |
570 | POPEVENT_PIXELART_MANY_COLORS, |
571 | POPEVENT_PIXELART_TOO_MANY_COLORS |
572 | }; |
573 | |
574 | int ; |
575 | int ; |
576 | int ; |
577 | bool m_LargeLayerWasWarned; |
578 | bool m_PreventUnusedTilesWasWarned; |
579 | int m_AllowPlaceUnusedTiles; |
580 | bool m_BrushDrawDestructive; |
581 | |
582 | int m_Mentions = 0; |
583 | bool m_IngameMoved = false; |
584 | |
585 | enum |
586 | { |
587 | FILETYPE_MAP, |
588 | FILETYPE_IMG, |
589 | FILETYPE_SOUND, |
590 | NUM_FILETYPES |
591 | }; |
592 | |
593 | int m_FileDialogStorageType; |
594 | int m_FileDialogLastPopulatedStorageType; |
595 | const char *m_pFileDialogTitle; |
596 | const char *m_pFileDialogButtonText; |
597 | bool (*m_pfnFileDialogFunc)(const char *pFileName, int StorageType, void *pUser); |
598 | void *m_pFileDialogUser; |
599 | CLineInputBuffered<IO_MAX_PATH_LENGTH> m_FileDialogFileNameInput; |
600 | char m_aFileDialogCurrentFolder[IO_MAX_PATH_LENGTH]; |
601 | char m_aFileDialogCurrentLink[IO_MAX_PATH_LENGTH]; |
602 | char m_aFilesSelectedName[IO_MAX_PATH_LENGTH]; |
603 | CLineInputBuffered<IO_MAX_PATH_LENGTH> m_FileDialogFilterInput; |
604 | char *m_pFileDialogPath; |
605 | int m_FileDialogFileType; |
606 | bool m_FileDialogMultipleStorages = false; |
607 | bool m_FileDialogShowingRoot = false; |
608 | int m_FilesSelectedIndex; |
609 | CLineInputBuffered<IO_MAX_PATH_LENGTH> m_FileDialogNewFolderNameInput; |
610 | |
611 | IGraphics::CTextureHandle m_FilePreviewImage; |
612 | int m_FilePreviewSound; |
613 | EPreviewState m_FilePreviewState; |
614 | CImageInfo m_FilePreviewImageInfo; |
615 | bool m_FileDialogOpening; |
616 | |
617 | int m_ToolbarPreviewSound; |
618 | |
619 | struct CFilelistItem |
620 | { |
621 | char m_aFilename[IO_MAX_PATH_LENGTH]; |
622 | char m_aName[IO_MAX_PATH_LENGTH]; |
623 | bool m_IsDir; |
624 | bool m_IsLink; |
625 | int m_StorageType; |
626 | time_t m_TimeModified; |
627 | }; |
628 | std::vector<CFilelistItem> m_vCompleteFileList; |
629 | std::vector<const CFilelistItem *> m_vpFilteredFileList; |
630 | |
631 | static bool CompareFilenameAscending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) |
632 | { |
633 | if(str_comp(a: pLhs->m_aFilename, b: ".." ) == 0) |
634 | return true; |
635 | if(str_comp(a: pRhs->m_aFilename, b: ".." ) == 0) |
636 | return false; |
637 | if(pLhs->m_IsLink != pRhs->m_IsLink) |
638 | return pLhs->m_IsLink; |
639 | if(pLhs->m_IsDir != pRhs->m_IsDir) |
640 | return pLhs->m_IsDir; |
641 | return str_comp_filenames(a: pLhs->m_aName, b: pRhs->m_aName) < 0; |
642 | } |
643 | |
644 | static bool CompareFilenameDescending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) |
645 | { |
646 | if(str_comp(a: pLhs->m_aFilename, b: ".." ) == 0) |
647 | return true; |
648 | if(str_comp(a: pRhs->m_aFilename, b: ".." ) == 0) |
649 | return false; |
650 | if(pLhs->m_IsLink != pRhs->m_IsLink) |
651 | return pLhs->m_IsLink; |
652 | if(pLhs->m_IsDir != pRhs->m_IsDir) |
653 | return pLhs->m_IsDir; |
654 | return str_comp_filenames(a: pLhs->m_aName, b: pRhs->m_aName) > 0; |
655 | } |
656 | |
657 | static bool CompareTimeModifiedAscending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) |
658 | { |
659 | if(str_comp(a: pLhs->m_aFilename, b: ".." ) == 0) |
660 | return true; |
661 | if(str_comp(a: pRhs->m_aFilename, b: ".." ) == 0) |
662 | return false; |
663 | if(pLhs->m_IsLink || pRhs->m_IsLink) |
664 | return pLhs->m_IsLink; |
665 | if(pLhs->m_IsDir != pRhs->m_IsDir) |
666 | return pLhs->m_IsDir; |
667 | return pLhs->m_TimeModified < pRhs->m_TimeModified; |
668 | } |
669 | |
670 | static bool CompareTimeModifiedDescending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) |
671 | { |
672 | if(str_comp(a: pLhs->m_aFilename, b: ".." ) == 0) |
673 | return true; |
674 | if(str_comp(a: pRhs->m_aFilename, b: ".." ) == 0) |
675 | return false; |
676 | if(pLhs->m_IsLink || pRhs->m_IsLink) |
677 | return pLhs->m_IsLink; |
678 | if(pLhs->m_IsDir != pRhs->m_IsDir) |
679 | return pLhs->m_IsDir; |
680 | return pLhs->m_TimeModified > pRhs->m_TimeModified; |
681 | } |
682 | |
683 | void SortFilteredFileList(); |
684 | int m_SortByFilename = 1; |
685 | int m_SortByTimeModified = 0; |
686 | |
687 | std::vector<std::string> m_vSelectEntitiesFiles; |
688 | std::string m_SelectEntitiesImage; |
689 | |
690 | // Zooming |
691 | CSmoothValue m_ZoomEnvelopeX; |
692 | CSmoothValue m_ZoomEnvelopeY; |
693 | |
694 | bool m_ResetZoomEnvelope; |
695 | |
696 | float m_OffsetEnvelopeX; |
697 | float m_OffsetEnvelopeY; |
698 | |
699 | bool m_ShowMousePointer; |
700 | bool m_GuiActive; |
701 | |
702 | char [256]; |
703 | bool m_PreviewZoom; |
704 | float m_MouseWorldScale = 1.0f; // Mouse (i.e. UI) scale relative to the World (selected Group) |
705 | vec2 m_MouseWorldPos = vec2(0.0f, 0.0f); |
706 | vec2 m_MouseWorldNoParaPos = vec2(0.0f, 0.0f); |
707 | vec2 m_MouseDeltaWorld = vec2(0.0f, 0.0f); |
708 | const void *m_pContainerPanned; |
709 | const void *m_pContainerPannedLast; |
710 | char m_MapEditorId; // UI element ID for the main map editor |
711 | |
712 | enum EShowTile |
713 | { |
714 | SHOW_TILE_OFF, |
715 | SHOW_TILE_DECIMAL, |
716 | SHOW_TILE_HEXADECIMAL |
717 | }; |
718 | EShowTile m_ShowTileInfo; |
719 | bool m_ShowDetail; |
720 | |
721 | bool m_Animate; |
722 | int64_t m_AnimateStart; |
723 | float m_AnimateTime; |
724 | float m_AnimateSpeed; |
725 | bool ; |
726 | |
727 | enum |
728 | { |
729 | = -1, |
730 | , |
731 | , |
732 | , |
733 | , |
734 | }; |
735 | EExtraEditor = EXTRAEDITOR_NONE; |
736 | float [NUM_EXTRAEDITORS] = {250.0f, 250.0f, 250.0f}; |
737 | float m_ToolBoxWidth = 100.0f; |
738 | |
739 | enum EShowEnvelope |
740 | { |
741 | SHOWENV_NONE = 0, |
742 | SHOWENV_SELECTED, |
743 | SHOWENV_ALL |
744 | }; |
745 | EShowEnvelope m_ShowEnvelopePreview; |
746 | bool m_ShowPicker; |
747 | |
748 | std::vector<int> m_vSelectedLayers; |
749 | std::vector<int> m_vSelectedQuads; |
750 | int m_SelectedQuadPoint; |
751 | int m_SelectedQuadIndex; |
752 | int m_SelectedGroup; |
753 | int m_SelectedQuadPoints; |
754 | int m_SelectedEnvelope; |
755 | std::vector<std::pair<int, int>> m_vSelectedEnvelopePoints; |
756 | int m_SelectedQuadEnvelope; |
757 | int m_CurrentQuadIndex; |
758 | int m_SelectedImage; |
759 | int m_SelectedSound; |
760 | int m_SelectedSource; |
761 | std::pair<int, int> m_SelectedTangentInPoint; |
762 | std::pair<int, int> m_SelectedTangentOutPoint; |
763 | bool m_UpdateEnvPointInfo; |
764 | |
765 | bool m_QuadKnifeActive; |
766 | int m_QuadKnifeCount; |
767 | vec2 m_aQuadKnifePoints[4]; |
768 | |
769 | // Color palette and pipette |
770 | ColorRGBA m_aSavedColors[8]; |
771 | ColorRGBA m_PipetteColor = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); |
772 | bool m_ColorPipetteActive = false; |
773 | |
774 | IGraphics::CTextureHandle m_CheckerTexture; |
775 | IGraphics::CTextureHandle m_BackgroundTexture; |
776 | |
777 | enum ECursorType |
778 | { |
779 | CURSOR_NORMAL, |
780 | CURSOR_RESIZE_V, |
781 | CURSOR_RESIZE_H, |
782 | NUM_CURSORS |
783 | }; |
784 | IGraphics::CTextureHandle m_aCursorTextures[ECursorType::NUM_CURSORS]; |
785 | ECursorType m_CursorType; |
786 | |
787 | IGraphics::CTextureHandle GetEntitiesTexture(); |
788 | |
789 | std::shared_ptr<CLayerGroup> m_pBrush; |
790 | std::shared_ptr<CLayerTiles> m_pTilesetPicker; |
791 | std::shared_ptr<CLayerQuads> m_pQuadsetPicker; |
792 | |
793 | static const void *ms_pUiGotContext; |
794 | |
795 | CEditorMap m_Map; |
796 | std::deque<std::shared_ptr<CDataFileWriterFinishJob>> m_WriterFinishJobs; |
797 | |
798 | int m_ShiftBy; |
799 | |
800 | static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser); |
801 | |
802 | CLineInputBuffered<256> m_SettingsCommandInput; |
803 | CMapSettingsBackend m_MapSettingsBackend; |
804 | CMapSettingsBackend::CContext m_MapSettingsCommandContext; |
805 | |
806 | CImageInfo m_TileartImageInfo; |
807 | char m_aTileartFilename[IO_MAX_PATH_LENGTH]; |
808 | void AddTileart(bool IgnoreHistory = false); |
809 | void TileartCheckColors(); |
810 | |
811 | void PlaceBorderTiles(); |
812 | |
813 | void UpdateTooltip(const void *pId, const CUIRect *pRect, const char *pToolTip); |
814 | int DoButton_Editor_Common(const void *pId, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); |
815 | int DoButton_Editor(const void *pId, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); |
816 | int DoButton_Env(const void *pId, const char *pText, int Checked, const CUIRect *pRect, const char *pToolTip, ColorRGBA Color, int Corners); |
817 | |
818 | int DoButton_Ex(const void *pId, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize = EditorFontSizes::MENU, int Align = TEXTALIGN_MC); |
819 | int DoButton_FontIcon(const void *pId, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize = 10.0f); |
820 | int (const void *pId, const char *pText, int Checked, const CUIRect *pRect, int Flags = 0, const char *pToolTip = nullptr); |
821 | |
822 | int DoButton_DraggableEx(const void *pId, const char *pText, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted, int Flags, const char *pToolTip = nullptr, int Corners = IGraphics::CORNER_ALL, float FontSize = 10.0f); |
823 | |
824 | bool DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const char *pToolTip = nullptr, const std::vector<STextColorSplit> &vColorSplits = {}); |
825 | bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const char *pToolTip = nullptr, const std::vector<STextColorSplit> &vColorSplits = {}); |
826 | |
827 | void DoMapSettingsEditBox(CMapSettingsBackend::CContext *pContext, const CUIRect *pRect, float FontSize, float DropdownMaxHeight, int Corners = IGraphics::CORNER_ALL, const char *pToolTip = nullptr); |
828 | |
829 | template<typename T> |
830 | int DoEditBoxDropdown(SEditBoxDropdownContext *pDropdown, CLineInput *pLineInput, const CUIRect *pEditBoxRect, int x, float MaxHeight, bool AutoWidth, const std::vector<T> &vData, const FDropdownRenderCallback<T> &fnMatchCallback); |
831 | template<typename T> |
832 | int RenderEditBoxDropdown(SEditBoxDropdownContext *pDropdown, CUIRect View, CLineInput *pLineInput, int x, float MaxHeight, bool AutoWidth, const std::vector<T> &vData, const FDropdownRenderCallback<T> &fnMatchCallback); |
833 | |
834 | void RenderBackground(CUIRect View, IGraphics::CTextureHandle Texture, float Size, float Brightness) const; |
835 | |
836 | SEditResult<int> UiDoValueSelector(void *pId, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip, bool IsDegree = false, bool IsHex = false, int corners = IGraphics::CORNER_ALL, const ColorRGBA *pColor = nullptr, bool ShowValue = true); |
837 | |
838 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
839 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
840 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
841 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
842 | struct : public SPopupMenuId |
843 | { |
844 | CEditor *; |
845 | std::vector<std::shared_ptr<CLayerTiles>> ; |
846 | std::vector<int> ; |
847 | CLayerTiles::SCommonPropState ; |
848 | }; |
849 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
850 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
851 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
852 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
853 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
854 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
855 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
856 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
857 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
858 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
859 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
860 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
861 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
862 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
863 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
864 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
865 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
866 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
867 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
868 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
869 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
870 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
871 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
872 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
873 | |
874 | static bool CallbackOpenMap(const char *pFileName, int StorageType, void *pUser); |
875 | static bool CallbackAppendMap(const char *pFileName, int StorageType, void *pUser); |
876 | static bool CallbackSaveMap(const char *pFileName, int StorageType, void *pUser); |
877 | static bool CallbackSaveCopyMap(const char *pFileName, int StorageType, void *pUser); |
878 | static bool CallbackAddTileart(const char *pFilepath, int StorageType, void *pUser); |
879 | static bool CallbackSaveImage(const char *pFileName, int StorageType, void *pUser); |
880 | static bool CallbackSaveSound(const char *pFileName, int StorageType, void *pUser); |
881 | |
882 | void (int Current, float x, float y); |
883 | int (); |
884 | |
885 | void (float x, float y); |
886 | int (); |
887 | |
888 | void (int Current, float x, float y); |
889 | int (); |
890 | |
891 | void (int Current, float x, float y); |
892 | int (); |
893 | |
894 | void DoQuadEnvelopes(const std::vector<CQuad> &vQuads, IGraphics::CTextureHandle Texture = IGraphics::CTextureHandle()); |
895 | void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex); |
896 | void DoQuadPoint(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int v); |
897 | void SetHotQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer); |
898 | |
899 | float TriangleArea(vec2 A, vec2 B, vec2 C); |
900 | bool IsInTriangle(vec2 Point, vec2 A, vec2 B, vec2 C); |
901 | void DoQuadKnife(int QuadIndex); |
902 | |
903 | void DoSoundSource(int LayerIndex, CSoundSource *pSource, int Index); |
904 | |
905 | enum class EAxis |
906 | { |
907 | AXIS_NONE = 0, |
908 | AXIS_X, |
909 | AXIS_Y |
910 | }; |
911 | struct SAxisAlignedBoundingBox |
912 | { |
913 | enum |
914 | { |
915 | POINT_TL = 0, |
916 | POINT_TR, |
917 | POINT_BL, |
918 | POINT_BR, |
919 | POINT_CENTER, |
920 | NUM_POINTS |
921 | }; |
922 | CPoint m_aPoints[NUM_POINTS]; |
923 | }; |
924 | void DoMapEditor(CUIRect View); |
925 | void DoToolbarLayers(CUIRect Toolbar); |
926 | void DoToolbarSounds(CUIRect Toolbar); |
927 | void DoQuad(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int Index); |
928 | void PreparePointDrag(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int PointIndex); |
929 | void DoPointDrag(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int PointIndex, int OffsetX, int OffsetY); |
930 | EAxis GetDragAxis(int OffsetX, int OffsetY) const; |
931 | void DrawAxis(EAxis Axis, CPoint &OriginalPoint, CPoint &Point) const; |
932 | void DrawAABB(const SAxisAlignedBoundingBox &AABB, int OffsetX = 0, int OffsetY = 0) const; |
933 | ColorRGBA GetButtonColor(const void *pId, int Checked); |
934 | |
935 | // Alignment methods |
936 | // These methods take `OffsetX` and `OffsetY` because the calculations are made with the original positions |
937 | // of the quad(s), before we started dragging. This allows us to edit `OffsetX` and `OffsetY` based on the previously |
938 | // calculated alignments. |
939 | struct SAlignmentInfo |
940 | { |
941 | CPoint m_AlignedPoint; // The "aligned" point, which we want to align/snap to |
942 | union |
943 | { |
944 | // The current changing value when aligned to this point. When aligning to a point on the X axis, then the X value is changing because |
945 | // we aligned the Y values (X axis aligned => Y values are the same, Y axis aligned => X values are the same). |
946 | int m_X; |
947 | int m_Y; |
948 | }; |
949 | EAxis m_Axis; // The axis we are aligning on |
950 | int m_PointIndex; // The point index we are aligning |
951 | int m_Diff; // Store the difference |
952 | }; |
953 | void ComputePointAlignments(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int PointIndex, int OffsetX, int OffsetY, std::vector<SAlignmentInfo> &vAlignments, bool Append = false) const; |
954 | void ComputePointsAlignments(const std::shared_ptr<CLayerQuads> &pLayer, bool Pivot, int OffsetX, int OffsetY, std::vector<SAlignmentInfo> &vAlignments) const; |
955 | void ComputeAABBAlignments(const std::shared_ptr<CLayerQuads> &pLayer, const SAxisAlignedBoundingBox &AABB, int OffsetX, int OffsetY, std::vector<SAlignmentInfo> &vAlignments) const; |
956 | void DrawPointAlignments(const std::vector<SAlignmentInfo> &vAlignments, int OffsetX, int OffsetY) const; |
957 | void QuadSelectionAABB(const std::shared_ptr<CLayerQuads> &pLayer, SAxisAlignedBoundingBox &OutAABB); |
958 | void ApplyAlignments(const std::vector<SAlignmentInfo> &vAlignments, int &OffsetX, int &OffsetY); |
959 | void ApplyAxisAlignment(int &OffsetX, int &OffsetY) const; |
960 | |
961 | bool ReplaceImage(const char *pFilename, int StorageType, bool CheckDuplicate); |
962 | static bool ReplaceImageCallback(const char *pFilename, int StorageType, void *pUser); |
963 | bool ReplaceSound(const char *pFileName, int StorageType, bool CheckDuplicate); |
964 | static bool ReplaceSoundCallback(const char *pFileName, int StorageType, void *pUser); |
965 | static bool AddImage(const char *pFilename, int StorageType, void *pUser); |
966 | static bool AddSound(const char *pFileName, int StorageType, void *pUser); |
967 | |
968 | bool IsEnvelopeUsed(int EnvelopeIndex) const; |
969 | void RemoveUnusedEnvelopes(); |
970 | |
971 | static bool IsVanillaImage(const char *pImage); |
972 | |
973 | void RenderLayers(CUIRect LayersBox); |
974 | void RenderImagesList(CUIRect Toolbox); |
975 | void RenderSelectedImage(CUIRect View); |
976 | void RenderSounds(CUIRect Toolbox); |
977 | void RenderModebar(CUIRect View); |
978 | void RenderStatusbar(CUIRect View, CUIRect *pTooltipRect); |
979 | void RenderTooltip(CUIRect TooltipRect); |
980 | |
981 | void RenderEnvelopeEditor(CUIRect View); |
982 | |
983 | void RenderMapSettingsErrorDialog(); |
984 | void RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEditorLast); |
985 | static void MapSettingsDropdownRenderCallback(const SPossibleValueMatch &Match, char (&aOutput)[128], std::vector<STextColorSplit> &vColorSplits); |
986 | |
987 | void RenderEditorHistory(CUIRect View); |
988 | |
989 | enum class EDragSide // Which side is the drag bar on |
990 | { |
991 | SIDE_BOTTOM, |
992 | SIDE_LEFT, |
993 | SIDE_TOP, |
994 | SIDE_RIGHT |
995 | }; |
996 | void DoEditorDragBar(CUIRect View, CUIRect *pDragBar, EDragSide Side, float *pValue, float MinValue = 100.0f, float MaxValue = 400.0f); |
997 | |
998 | void SetHotEnvelopePoint(const CUIRect &View, const std::shared_ptr<CEnvelope> &pEnvelope, int ActiveChannels); |
999 | |
1000 | void (CUIRect ); |
1001 | void RenderFileDialog(); |
1002 | |
1003 | void SelectGameLayer(); |
1004 | std::vector<int> SortImages(); |
1005 | |
1006 | void DoAudioPreview(CUIRect View, const void *pPlayPauseButtonId, const void *pStopButtonId, const void *pSeekBarId, const int SampleId); |
1007 | |
1008 | // Tile Numbers For Explanations - TODO: Add/Improve tiles and explanations |
1009 | enum |
1010 | { |
1011 | TILE_PUB_AIR, |
1012 | TILE_PUB_HOOKABLE, |
1013 | TILE_PUB_DEATH, |
1014 | TILE_PUB_UNHOOKABLE, |
1015 | |
1016 | TILE_PUB_CREDITS1 = 140, |
1017 | TILE_PUB_CREDITS2, |
1018 | TILE_PUB_CREDITS3, |
1019 | TILE_PUB_CREDITS4, |
1020 | TILE_PUB_CREDITS5 = 156, |
1021 | TILE_PUB_CREDITS6, |
1022 | TILE_PUB_CREDITS7, |
1023 | TILE_PUB_CREDITS8, |
1024 | |
1025 | TILE_PUB_ENTITIES_OFF1 = 190, |
1026 | TILE_PUB_ENTITIES_OFF2, |
1027 | }; |
1028 | |
1029 | enum |
1030 | { |
1031 | TILE_FNG_SPIKE_GOLD = 7, |
1032 | TILE_FNG_SPIKE_NORMAL, |
1033 | TILE_FNG_SPIKE_RED, |
1034 | TILE_FNG_SPIKE_BLUE, |
1035 | TILE_FNG_SCORE_RED, |
1036 | TILE_FNG_SCORE_BLUE, |
1037 | |
1038 | TILE_FNG_SPIKE_GREEN = 14, |
1039 | TILE_FNG_SPIKE_PURPLE, |
1040 | |
1041 | TILE_FNG_SPAWN = 192, |
1042 | TILE_FNG_SPAWN_RED, |
1043 | TILE_FNG_SPAWN_BLUE, |
1044 | TILE_FNG_FLAG_RED, |
1045 | TILE_FNG_FLAG_BLUE, |
1046 | TILE_FNG_SHIELD, |
1047 | TILE_FNG_HEART, |
1048 | TILE_FNG_SHOTGUN, |
1049 | TILE_FNG_GRENADE, |
1050 | TILE_FNG_NINJA, |
1051 | TILE_FNG_LASER, |
1052 | |
1053 | TILE_FNG_SPIKE_OLD1 = 208, |
1054 | TILE_FNG_SPIKE_OLD2, |
1055 | TILE_FNG_SPIKE_OLD3 |
1056 | }; |
1057 | |
1058 | enum |
1059 | { |
1060 | TILE_VANILLA_SPAWN = 192, |
1061 | TILE_VANILLA_SPAWN_RED, |
1062 | TILE_VANILLA_SPAWN_BLUE, |
1063 | TILE_VANILLA_FLAG_RED, |
1064 | TILE_VANILLA_FLAG_BLUE, |
1065 | TILE_VANILLA_SHIELD, |
1066 | TILE_VANILLA_HEART, |
1067 | TILE_VANILLA_SHOTGUN, |
1068 | TILE_VANILLA_GRENADE, |
1069 | TILE_VANILLA_NINJA, |
1070 | TILE_VANILLA_LASER, |
1071 | }; |
1072 | |
1073 | // Explanations |
1074 | enum class EExplanation |
1075 | { |
1076 | NONE, |
1077 | DDNET, |
1078 | FNG, |
1079 | RACE, |
1080 | VANILLA, |
1081 | BLOCKWORLDS |
1082 | }; |
1083 | static const char *ExplainDDNet(int Tile, int Layer); |
1084 | static const char *ExplainFNG(int Tile, int Layer); |
1085 | static const char *ExplainVanilla(int Tile, int Layer); |
1086 | static const char *Explain(EExplanation Explanation, int Tile, int Layer); |
1087 | |
1088 | // Zooming |
1089 | void ZoomAdaptOffsetX(float ZoomFactor, const CUIRect &View); |
1090 | void UpdateZoomEnvelopeX(const CUIRect &View); |
1091 | |
1092 | void ZoomAdaptOffsetY(float ZoomFactor, const CUIRect &View); |
1093 | void UpdateZoomEnvelopeY(const CUIRect &View); |
1094 | |
1095 | void ResetZoomEnvelope(const std::shared_ptr<CEnvelope> &pEnvelope, int ActiveChannels); |
1096 | void RemoveTimeOffsetEnvelope(const std::shared_ptr<CEnvelope> &pEnvelope); |
1097 | float ScreenToEnvelopeX(const CUIRect &View, float x) const; |
1098 | float EnvelopeToScreenX(const CUIRect &View, float x) const; |
1099 | float ScreenToEnvelopeY(const CUIRect &View, float y) const; |
1100 | float EnvelopeToScreenY(const CUIRect &View, float y) const; |
1101 | float ScreenToEnvelopeDX(const CUIRect &View, float dx); |
1102 | float ScreenToEnvelopeDY(const CUIRect &View, float dy); |
1103 | |
1104 | // DDRace |
1105 | |
1106 | IGraphics::CTextureHandle GetFrontTexture(); |
1107 | IGraphics::CTextureHandle GetTeleTexture(); |
1108 | IGraphics::CTextureHandle GetSpeedupTexture(); |
1109 | IGraphics::CTextureHandle GetSwitchTexture(); |
1110 | IGraphics::CTextureHandle GetTuneTexture(); |
1111 | |
1112 | unsigned char m_TeleNumber; |
1113 | unsigned char m_TeleCheckpointNumber; |
1114 | unsigned char m_ViewTeleNumber; |
1115 | |
1116 | unsigned char m_TuningNum; |
1117 | |
1118 | unsigned char m_SpeedupForce; |
1119 | unsigned char m_SpeedupMaxSpeed; |
1120 | short m_SpeedupAngle; |
1121 | |
1122 | unsigned char m_SwitchNum; |
1123 | unsigned char m_SwitchDelay; |
1124 | unsigned char m_ViewSwitch; |
1125 | |
1126 | void AdjustBrushSpecialTiles(bool UseNextFree, int Adjust = 0); |
1127 | int FindNextFreeSwitchNumber(); |
1128 | int FindNextFreeTeleNumber(bool IsCheckpoint = false); |
1129 | |
1130 | public: |
1131 | // Undo/Redo |
1132 | CEditorHistory m_EditorHistory; |
1133 | CEditorHistory m_ServerSettingsHistory; |
1134 | CEditorHistory m_EnvelopeEditorHistory; |
1135 | CQuadEditTracker m_QuadTracker; |
1136 | CEnvelopeEditorOperationTracker m_EnvOpTracker; |
1137 | |
1138 | private: |
1139 | void UndoLastAction(); |
1140 | void RedoLastAction(); |
1141 | |
1142 | private: |
1143 | std::map<int, CPoint[5]> m_QuadDragOriginalPoints; |
1144 | }; |
1145 | |
1146 | // make sure to inline this function |
1147 | inline class IGraphics *CLayer::Graphics() { return m_pEditor->Graphics(); } |
1148 | inline class ITextRender *CLayer::TextRender() { return m_pEditor->TextRender(); } |
1149 | |
1150 | #endif |
1151 | |