1//////////////////////////////////////////////////////////////////////
2// This file is part of Remere's Map Editor
3//////////////////////////////////////////////////////////////////////
4// Remere's Map Editor is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Remere's Map Editor is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//////////////////////////////////////////////////////////////////////
17
18#ifndef RME_GUI_H_
19#define RME_GUI_H_
20
21#include "graphics.h"
22#include "position.h"
23
24#include "copybuffer.h"
25#include "dcbutton.h"
26#include "brush_enums.h"
27#include "gui_ids.h"
28#include "editor_tabs.h"
29#include "map_tab.h"
30#include "palette_window.h"
31#include "client_version.h"
32#include <memory> // For smart pointers
33
34class BaseMap;
35class Map;
36
37class Editor;
38class Brush;
39class HouseBrush;
40class HouseExitBrush;
41class WaypointBrush;
42class OptionalBorderBrush;
43class EraserBrush;
44class SpawnBrush;
45class DoorBrush;
46class FlagBrush;
47
48class MainFrame;
49class WelcomeDialog;
50class MapWindow;
51class MapCanvas;
52
53class SearchResultWindow;
54class MapSummaryWindow;
55class MinimapWindow;
56class PaletteWindow;
57class OldPropertiesWindow;
58class TilesetWindow;
59class EditTownsDialog;
60class ItemButton;
61
62class LiveSocket;
63
64class SelectionDialog;
65class FindItemDialog;
66class LoadOptionsDialog;
67class PropertiesDialog;
68class PreferencesWindow;
69class ItemEditor;
70class BorderEditorDialog;
71
72extern const wxEventType EVT_UPDATE_MENUS;
73
74#define EVT_ON_UPDATE_MENUS(id, fn) \
75 DECLARE_EVENT_TABLE_ENTRY( \
76 EVT_UPDATE_MENUS, id, wxID_ANY, \
77 (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxCommandEventFunction, &fn), \
78 (wxObject*)nullptr \
79 ),
80
81class Hotkey {
82public:
83 Hotkey();
84 Hotkey(Position pos);
85 Hotkey(Brush* brush);
86 Hotkey(std::string _brushname);
87 ~Hotkey();
88
89 bool IsPosition() const {
90 return type == POSITION;
91 }
92 bool IsBrush() const {
93 return type == BRUSH;
94 }
95 Position GetPosition() const {
96 ASSERT(IsPosition());
97 return pos;
98 }
99 std::string GetBrushname() const {
100 ASSERT(IsBrush());
101 return brushname;
102 }
103
104private:
105 enum {
106 NONE,
107 POSITION,
108 BRUSH,
109 } type;
110
111 Position pos;
112 std::string brushname;
113
114 friend std::ostream& operator<<(std::ostream& os, const Hotkey& hotkey);
115 friend std::istream& operator>>(std::istream& os, Hotkey& hotkey);
116};
117
118std::ostream& operator<<(std::ostream& os, const Hotkey& hotkey);
119std::istream& operator>>(std::istream& os, Hotkey& hotkey);
120
121class GUI {
122public: // dtor and ctor
123 GUI();
124 ~GUI();
125
126private:
127 GUI(const GUI& g_gui); // Don't copy me
128 GUI& operator=(const GUI& g_gui); // Don't assign me
129 bool operator==(const GUI& g_gui); // Don't compare me
130
131public:
132 /**
133 * Saves the perspective to the configuration file
134 * This is the position of all windows etc. in the editor
135 */
136 void SavePerspective();
137
138 /**
139 * Loads the stored perspective from the configuration file
140 */
141 void LoadPerspective();
142
143 /**
144 * Creates a loading bar with the specified message, title is always "Loading"
145 * The default scale is 0 - 100
146 */
147 void CreateLoadBar(wxString message, bool canCancel = false);
148
149 /**
150 * Sets how much of the load has completed, the scale can be set with
151 * SetLoadScale.
152 * If this returns false, the user has hit the quit button and you should
153 * abort the loading.
154 */
155 bool SetLoadDone(int32_t done, const wxString& newMessage = "");
156
157 /**
158 * Sets the scale of the loading bar.
159 * Calling this with (50, 80) means that setting 50 as 'done',
160 * it will display as 0% loaded, 80 will display as 100% loaded.
161 */
162 void SetLoadScale(int32_t from, int32_t to);
163
164 void ShowWelcomeDialog(const wxBitmap& icon);
165 void FinishWelcomeDialog();
166 bool IsWelcomeDialogShown();
167
168 /**
169 * Destroys (hides) the current loading bar.
170 */
171 void DestroyLoadBar();
172
173 void UpdateMenubar();
174
175 bool IsRenderingEnabled() const {
176 return disabled_counter == 0;
177 }
178
179 void EnableHotkeys();
180 void DisableHotkeys();
181 bool AreHotkeysEnabled() const;
182
183 // This sends the event to the main window (redirecting from other controls)
184 void AddPendingCanvasEvent(wxEvent& event);
185
186 void OnWelcomeDialogClosed(wxCloseEvent& event);
187 void OnWelcomeDialogAction(wxCommandEvent& event);
188
189protected:
190 void DisableRendering() {
191 ++disabled_counter;
192 }
193 void EnableRendering() {
194 --disabled_counter;
195 }
196
197public:
198 void SetTitle(wxString newtitle);
199 void UpdateTitle();
200 void UpdateMenus();
201 void ShowToolbar(ToolBarID id, bool show);
202 void SetStatusText(wxString text);
203
204 long PopupDialog(wxWindow* parent, wxString title, wxString text, long style, wxString configsavename = wxEmptyString, uint32_t configsavevalue = 0);
205 long PopupDialog(wxString title, wxString text, long style, wxString configsavename = wxEmptyString, uint32_t configsavevalue = 0);
206
207 void ListDialog(wxWindow* parent, wxString title, const wxArrayString& vec);
208 void ListDialog(const wxString& title, const wxArrayString& vec) {
209 ListDialog(nullptr, title, vec);
210 }
211
212 void ShowTextBox(wxWindow* parent, wxString title, wxString contents);
213 void ShowTextBox(const wxString& title, const wxString& contents) {
214 ShowTextBox(nullptr, title, contents);
215 }
216
217 // Get the current GL context
218 // Param is required if the context is to be created.
219 wxGLContext* GetGLContext(wxGLCanvas* win);
220
221 // Search Results
222 SearchResultWindow* GetSearchWindow();
223 SearchResultWindow* ShowSearchWindow();
224 void HideSearchWindow();
225
226 // Map Summary
227 MapSummaryWindow* GetMapSummaryWindow();
228 MapSummaryWindow* ShowMapSummaryWindow();
229 void HideMapSummaryWindow();
230
231 // Search state persistence
232 void StoreSearchState(uint16_t itemId, bool onSelection);
233 void RestoreSearchState(SearchResultWindow* window);
234 bool HasStoredSearch() const { return has_last_search; }
235
236 // Minimap
237 void CreateMinimap();
238 void HideMinimap();
239 void ShowMinimap();
240 void DestroyMinimap();
241 void UpdateMinimap(bool immediate = false);
242 bool IsMinimapVisible() const;
243
244 int GetCurrentFloor();
245 void ChangeFloor(int newfloor);
246
247 double GetCurrentZoom();
248 void SetCurrentZoom(double zoom);
249
250 void SwitchMode();
251 void SetSelectionMode();
252 void SetDrawingMode();
253 bool IsSelectionMode() const {
254 return mode == SELECTION_MODE;
255 }
256 bool IsDrawingMode() const {
257 return mode == DRAWING_MODE;
258 }
259
260 void SetHotkey(int index, Hotkey& hotkey);
261 const Hotkey& GetHotkey(int index) const;
262 void SaveHotkeys() const;
263 void LoadHotkeys();
264
265 // Brushes
266 void FillDoodadPreviewBuffer();
267 // Selects the currently seleceted brush in the active palette
268 void SelectBrush();
269 // Updates the palette AND selects the brush, second parameter is first palette to look in
270 // Returns true if the brush was found and selected
271 bool SelectBrush(const Brush* brush, PaletteType pt = TILESET_UNKNOWN);
272 // Selects the brush selected before the current brush
273 void SelectPreviousBrush();
274 // Only selects the brush, doesn't update the palette
275 void SelectBrushInternal(Brush* brush);
276 // Get different brush parameters
277 Brush* GetCurrentBrush() const;
278 BrushShape GetBrushShape() const;
279 int GetBrushSize() const;
280 int GetBrushVariation() const;
281 int GetSpawnTime() const;
282
283 // Additional brush parameters
284 void SetSpawnTime(int time) {
285 creature_spawntime = time;
286 }
287 void SetBrushSize(int nz);
288 void SetBrushSizeInternal(int nz);
289 void SetBrushShape(BrushShape bs);
290 void SetBrushVariation(int nz);
291 void SetBrushThickness(int low, int ceil);
292 void SetBrushThickness(bool on, int low = -1, int ceil = -1);
293 // Helper functions for size
294 void DecreaseBrushSize(bool wrap = false);
295 void IncreaseBrushSize(bool wrap = false);
296 // Door brush options
297 void SetDoorLocked(bool on);
298 bool HasDoorLocked();
299
300 // Fetch different useful directories
301 static wxString GetExecDirectory();
302 static wxString GetDataDirectory();
303 static wxString GetLocalDataDirectory();
304 static wxString GetLocalDirectory();
305 static wxString GetExtensionsDirectory();
306
307 void discoverDataDirectory(const wxString& existentFile);
308 wxString getFoundDataDirectory() {
309 return m_dataDirectory;
310 }
311
312 // Load/unload a client version (takes care of dialogs aswell)
313 void UnloadVersion();
314 bool LoadVersion(ClientVersionID ver, wxString& error, wxArrayString& warnings, bool force = false);
315 // The current version loaded (returns CLIENT_VERSION_NONE if no version is loaded)
316 const ClientVersion& GetCurrentVersion() const;
317 ClientVersionID GetCurrentVersionID() const;
318 // If any version is loaded at all
319 bool IsVersionLoaded() const {
320 return loaded_version != CLIENT_VERSION_NONE;
321 }
322
323 // Centers current view on position
324 void SetScreenCenterPosition(Position pos);
325 // Refresh the view canvas
326 void RefreshView();
327 // Fit all/specified current map view to map dimensions
328 void FitViewToMap();
329 void FitViewToMap(MapTab* mt);
330
331 void DoCut();
332 void DoCopy();
333 void DoPaste();
334 void PreparePaste();
335 void StartPasting();
336 void EndPasting();
337 bool IsPasting() const {
338 return pasting;
339 }
340
341 bool CanUndo();
342 bool CanRedo();
343 bool DoUndo();
344 bool DoRedo();
345
346 // Editor interface
347 wxAuiManager* GetAuiManager() const {
348 return aui_manager;
349 }
350 EditorTab* GetCurrentTab();
351 EditorTab* GetTab(int idx);
352 int GetTabCount() const;
353 bool IsAnyEditorOpen() const;
354 bool IsEditorOpen() const;
355 void CloseCurrentEditor();
356 Editor* GetCurrentEditor();
357 MapTab* GetCurrentMapTab() const;
358 void CycleTab(bool forward = true);
359 bool CloseLiveEditors(LiveSocket* sock);
360 bool CloseAllEditors();
361 void NewMapView();
362 void NewDetachedMapView();
363
364 // Detached views management
365 void RegisterDetachedView(Editor* editor, wxFrame* frame);
366 void RegisterDockableView(Editor* editor, MapWindow* window);
367 void UnregisterDetachedView(Editor* editor, wxFrame* frame);
368 void UnregisterDockableView(Editor* editor, MapWindow* window);
369 bool HasDetachedViews(Editor* editor) const;
370 bool CloseDetachedViews(Editor* editor);
371 void UpdateDetachedViewsTitle(Editor* editor);
372
373 // Map
374 Map& GetCurrentMap();
375 int GetOpenMapCount();
376 bool ShouldSave();
377 void SaveCurrentMap(FileName filename, bool showdialog); // "" means default filename
378 void SaveCurrentMap(bool showdialog = true) {
379 SaveCurrentMap(wxString(""), showdialog);
380 }
381 bool NewMap();
382 void OpenMap();
383 void SaveMap();
384 void SaveMapAs();
385 bool LoadMap(const FileName& fileName);
386
387protected:
388 bool LoadDataFiles(wxString& error, wxArrayString& warnings);
389 ClientVersion* getLoadedVersion() const {
390 return loaded_version == CLIENT_VERSION_NONE ? nullptr : ClientVersion::get(loaded_version);
391 }
392
393 // Method to clean up brush pointers
394 void CleanupBrushes();
395
396 //=========================================================================
397 // Palette Interface
398public:
399 // Spawn a newd palette
400 PaletteWindow* NewPalette();
401 // Bring this palette to the front (as the 'active' palette)
402 void ActivatePalette(PaletteWindow* p);
403 // Rebuild forces palette to reload the entire contents
404 void RebuildPalettes();
405 // Refresh only updates the content (such as house/waypoint list)
406 void RefreshPalettes(Map* m = nullptr, bool usedfault = true);
407 // Won't refresh the palette in the parameter
408 void RefreshOtherPalettes(PaletteWindow* p);
409 // If no palette is shown, this displays the primary palette
410 // else does nothing.
411 void ShowPalette();
412 // Select a particular page on the primary palette
413 void SelectPalettePage(PaletteType pt);
414
415 // Returns primary palette
416 PaletteWindow* GetPalette() const;
417 // Returns list of all palette, first in the list is primary
418 const std::list<PaletteWindow*>& GetPalettes();
419
420 void DestroyPalettes();
421 // Hidden from public view
422protected:
423 PaletteWindow* CreatePalette();
424
425 //=========================================================================
426 // Public members
427 //=========================================================================
428public:
429 wxString m_dataDirectory;
430 wxAuiManager* aui_manager;
431 MapTabbook* tabbook;
432 MainFrame* root; // The main frame
433 WelcomeDialog* welcomeDialog;
434 CopyBuffer copybuffer;
435
436 MinimapWindow* minimap;
437 DCButton* gem; // The small gem in the lower-right corner
438 SearchResultWindow* search_result_window;
439 MapSummaryWindow* map_summary_window;
440 GraphicManager gfx;
441
442 BaseMap* secondary_map; // A non-owning pointer to doodad_buffer_map when needed
443 std::unique_ptr<BaseMap> doodad_buffer_map; // The map in which doodads are temporarily stored
444
445 //=========================================================================
446 // Brush references
447 //=========================================================================
448
449 HouseBrush* house_brush;
450 HouseExitBrush* house_exit_brush;
451 WaypointBrush* waypoint_brush;
452 OptionalBorderBrush* optional_brush;
453 EraserBrush* eraser;
454 SpawnBrush* spawn_brush;
455 DoorBrush* normal_door_brush;
456 DoorBrush* locked_door_brush;
457 DoorBrush* magic_door_brush;
458 DoorBrush* quest_door_brush;
459 DoorBrush* hatch_door_brush;
460 DoorBrush* normal_door_alt_brush;
461 DoorBrush* archway_door_brush;
462 DoorBrush* window_door_brush;
463 FlagBrush* pz_brush;
464 FlagBrush* rook_brush;
465 FlagBrush* nolog_brush;
466 FlagBrush* pvp_brush;
467 FlagBrush* zone_brush;
468
469protected:
470 //=========================================================================
471 // Global GUI state
472 //=========================================================================
473 typedef std::list<PaletteWindow*> PaletteList;
474 PaletteList palettes;
475
476 std::unique_ptr<wxGLContext> OGLContext;
477
478 ClientVersionID loaded_version;
479 EditorMode mode;
480 bool pasting;
481
482 Hotkey hotkeys[10];
483 bool hotkeys_enabled;
484
485 //=========================================================================
486 // Internal brush data
487 //=========================================================================
488 Brush* current_brush;
489 Brush* previous_brush;
490 BrushShape brush_shape;
491 int brush_size;
492 int brush_variation;
493 int creature_spawntime;
494
495 bool draw_locked_doors;
496 bool use_custom_thickness;
497 float custom_thickness_mod;
498
499 //=========================================================================
500 // Progress bar tracking
501 //=========================================================================
502 wxString progressText;
503 wxGenericProgressDialog* progressBar;
504
505 int32_t progressFrom;
506 int32_t progressTo;
507 int32_t currentProgress;
508
509 wxWindowDisabler* winDisabler;
510 int disabled_counter;
511
512 friend class RenderingLock;
513 friend MapTab::MapTab(MapTabbook*, Editor*);
514 friend MapTab::MapTab(const MapTab*);
515
516public:
517 int GetHotkeyEventId(const std::string& action);
518
519 // Add after line 395 (public members section)
520 bool minimap_enabled;
521
522 // Map to track detached views for each editor
523 std::map<Editor*, std::list<wxFrame*>> detached_views;
524 std::map<Editor*, std::list<MapWindow*>> dockable_views;
525
526 void CheckAutoSave();
527 uint32_t last_autosave;
528 uint32_t last_autosave_check;
529
530 // Dark mode
531 void ApplyDarkMode();
532
533 // Search state variables
534 bool has_last_search;
535 uint16_t last_search_itemid;
536 bool last_search_on_selection;
537 wxString last_ignored_ids_text;
538 bool last_ignored_ids_enabled;
539
540 // Add after line 400 (public members section)
541 uint16_t GetCurrentActionID() const;
542 bool IsCurrentActionIDEnabled() const;
543};
544
545extern GUI g_gui;
546
547class RenderingLock {
548 bool acquired;
549
550public:
551 RenderingLock() :
552 acquired(true) {
553 g_gui.DisableRendering();
554 }
555 ~RenderingLock() {
556 release();
557 }
558 void release() {
559 g_gui.EnableRendering();
560 acquired = false;
561 }
562
563 MinimapWindow* GetMinimapWindow() { return g_gui.minimap; }
564};
565
566/**
567 * Will push a loading bar when it is constructed
568 * which will the be popped when it destructs.
569 * Look in the GUI class for documentation of what the methods mean.
570 */
571class ScopedLoadingBar {
572public:
573 ScopedLoadingBar(wxString message, bool canCancel = false) {
574 g_gui.CreateLoadBar(message, canCancel);
575 }
576 ~ScopedLoadingBar() {
577 g_gui.DestroyLoadBar();
578 }
579
580 void SetLoadDone(int32_t done, const wxString& newmessage = wxEmptyString) {
581 g_gui.SetLoadDone(done, newmessage);
582 }
583
584 void SetLoadScale(int32_t from, int32_t to) {
585 g_gui.SetLoadScale(from, to);
586 }
587};
588
589#define UnnamedRenderingLock() RenderingLock __unnamed_rendering_lock_##__LINE__
590
591void SetWindowToolTip(wxWindow* a, const wxString& tip);
592void SetWindowToolTip(wxWindow* a, wxWindow* b, const wxString& tip);
593
594
595
596#endif
597