minimap_window.h

main 203 lines · 5.5 KB Raw
Alex Alex Commit Map Editor 18/10/2026 23:40
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_MINIMAP_WINDOW_H_
19#define RME_MINIMAP_WINDOW_H_
20
21#include "position.h"
22#include <wx/panel.h>
23#include <memory>
24#include <map>
25#include <thread>
26#include <mutex>
27#include <atomic>
28#include <wx/timer.h>
29#include <wx/pen.h>
30#include <vector>
31#include <wx/combobox.h>
32#include <wx/button.h>
33#include <wx/xml/xml.h>
34#include <wx/checkbox.h>
35
36class MinimapWindow : public wxPanel {
37public:
38 enum {
39 ID_MINIMAP_UPDATE = 45000, // Choose a number that won't conflict with other IDs
40 ID_RESIZE_TIMER = 45001 // Timer ID for resize completion detection
41 };
42
43 MinimapWindow(wxWindow* parent);
44 virtual ~MinimapWindow();
45
46 void OnPaint(wxPaintEvent&);
47 void OnEraseBackground(wxEraseEvent&) { }
48 void OnMouseClick(wxMouseEvent&);
49 void OnSize(wxSizeEvent&);
50 void OnClose(wxCloseEvent&);
51 void OnResizeTimer(wxTimerEvent&);
52
53 void DelayedUpdate();
54 void OnDelayedUpdate(wxTimerEvent& event);
55 void OnKey(wxKeyEvent& event);
56
57 void ClearCache();
58
59 // Pre-cache method for building the entire minimap at load time
60 void PreCacheEntireMap();
61
62 // Method to initialize minimap loading progressively on startup
63 void InitialLoad();
64
65 void UpdateDrawnTiles(const PositionVector& positions);
66
67 static const int BLOCK_SIZE = 256; // 256 IS most optimal 512 is too laggy and 64 is too small
68
69 struct MinimapBlock {
70 wxBitmap bitmap;
71 bool needsUpdate = true;
72 bool wasSeen = false;
73 int floor = -1;
74
75 MinimapBlock() : needsUpdate(true), wasSeen(false) {}
76 };
77
78 using BlockPtr = std::shared_ptr<MinimapBlock>;
79 using BlockMap = std::map<uint32_t, BlockPtr>;
80
81 bool needs_update;
82
83 void MarkBlockForUpdate(int x, int y) {
84 if (auto block = getBlock(x, y)) {
85 block->needsUpdate = true;
86 }
87 }
88
89 // Minimap waypoint support
90 struct MinimapWaypoint {
91 wxString name;
92 Position pos;
93 MinimapWaypoint(const wxString& n, const Position& p) : name(n), pos(p) {}
94 };
95 std::vector<MinimapWaypoint> minimap_waypoints;
96 int selected_minimap_waypoint_idx = -1;
97 wxComboBox* minimap_waypoint_combo = nullptr;
98 wxButton* add_minimap_waypoint_btn = nullptr;
99
100 void UpdateMinimapWaypointCombo();
101 void OnMinimapWaypointSelected(wxCommandEvent& event);
102 void OnAddMinimapWaypoint(wxCommandEvent& event);
103 void TeleportToMinimapWaypoint(int idx);
104
105 // Save/Load buttons for minimap waypoints
106 wxButton* save_minimap_waypoints_btn = nullptr;
107 wxButton* load_minimap_waypoints_btn = nullptr;
108
109 void SaveMinimapWaypointsToXML();
110 void LoadMinimapWaypointsFromXML();
111 void OnSaveMinimapWaypoints(wxCommandEvent& event);
112 void OnLoadMinimapWaypoints(wxCommandEvent& event);
113 void SetMinimapFloor(int floor);
114
115private:
116 BlockMap m_blocks;
117 std::mutex m_mutex;
118
119 // Empty tile atlas for faster rendering
120 wxBitmap empty_tile_atlas;
121 bool empty_tile_atlas_initialized;
122
123 // Minimap floor (separate from editor floor)
124 int minimap_floor;
125
126 // Button rectangles for header UI
127 wxRect btn_cache;
128 wxRect btn_up;
129 wxRect btn_down;
130
131 // Helper methods
132 uint32_t getBlockIndex(int x, int y) const {
133 return ((x / BLOCK_SIZE) * (65536 / BLOCK_SIZE)) + (y / BLOCK_SIZE);
134 }
135
136 wxPoint getBlockOffset(int x, int y) {
137 return wxPoint(x - x % BLOCK_SIZE, y - y % BLOCK_SIZE);
138 }
139
140 BlockPtr getBlock(int x, int y);
141 void updateBlock(BlockPtr block, int startX, int startY, int floor);
142
143 wxBitmap buffer;
144 std::mutex buffer_mutex;
145 std::thread render_thread;
146 std::atomic<bool> thread_running;
147
148 // Window resizing handling
149 bool is_resizing;
150 wxTimer resize_timer;
151
152 void RenderThreadFunction();
153 void StartRenderThread();
154 void StopRenderThread();
155
156 // Store last known state to detect changes
157 int last_center_x;
158 int last_center_y;
159 int last_floor;
160
161 wxPen* pens[256];
162 wxTimer update_timer;
163 int last_start_x;
164 int last_start_y;
165
166 // Helper methods
167 void InitializeEmptyTileAtlas();
168 void DrawEmptyTileAtlas(wxDC& dc, int startX, int startY, int width, int height);
169
170 void DrawHeaderButtons(wxDC& dc, int windowWidth, int headerHeight);
171 void HandleHeaderButtonClick(const wxPoint& pt);
172 void StartCacheCurrentFloor();
173 void BatchCacheFloor(int floor);
174
175 // Block-based cache
176 struct BlockKey {
177 int bx, by, z;
178 bool operator<(const BlockKey& other) const {
179 if (z != other.z) return z < other.z;
180 if (bx != other.bx) return bx < other.bx;
181 return by < other.by;
182 }
183 };
184 std::map<BlockKey, wxBitmap> block_cache;
185
186 // UI: Save cache to disk checkbox
187 wxCheckBox* save_cache_checkbox = nullptr;
188 bool save_cache_to_disk = false;
189
190 // Block cache logic
191 void CacheFilledBlocksForFloor(int floor);
192 void SaveBlockCacheToDisk(int floor);
193 void LoadBlockCacheFromDisk(int floor);
194 void ClearBlockCache();
195 bool IsBlockFilled(int bx, int by, int floor);
196 wxBitmap RenderBlock(int bx, int by, int floor);
197 wxString GetCurrentMapName() const;
198
199 DECLARE_EVENT_TABLE()
200};
201
202#endif
203
Top