yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
canvas_navigation_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_OVERWORLD_CANVAS_NAVIGATION_MANAGER_H
2#define YAZE_APP_EDITOR_OVERWORLD_CANVAS_NAVIGATION_MANAGER_H
3
4#include <array>
5#include <functional>
6#include <memory>
7#include <optional>
8#include <vector>
9
10#include "absl/status/status.h"
12#include "app/gfx/core/bitmap.h"
16#include "rom/rom.h"
17#include "zelda3/common.h"
19
20namespace yaze::editor {
21
22// Forward declarations
23class OverworldEntityRenderer;
24
31 ImVec2 residual{0.0f, 0.0f};
32 float idle_seconds = 0.0f;
33
38 ImVec2 Consume(ImVec2 wheel, float dt, float step_px, float snap_px);
39};
40
43ImVec2 ScrollForZoomAtAnchor(ImVec2 scroll, ImVec2 anchor, float old_scale,
44 float new_scale);
45
46// =============================================================================
47// CanvasNavigationManager
48// =============================================================================
49//
50// Extracted from OverworldEditor to encapsulate all canvas navigation logic:
51// - Map hover detection and lazy loading (CheckForCurrentMap)
52// - Pan and zoom controls
53// - Map interaction (context menus, lock toggle)
54// - Background preloading of adjacent maps
55// - Blockset selector synchronization
56//
57// The manager holds pointers to shared editor state (via NavigationContext)
58// and uses callbacks for operations that remain in the editor (e.g. map
59// refresh, texture creation).
60// =============================================================================
61
64 // Canvas references
66
67 // Data model
69 Rom* rom = nullptr;
70
71 // Selection state (mutable pointers into editor fields)
72 int* current_map = nullptr;
73 int* current_world = nullptr;
74 int* current_parent = nullptr;
75 int* current_tile16 = nullptr;
76 int* hovered_map = nullptr;
77
78 // Mode state
80 bool* current_map_lock = nullptr;
81 bool* is_dragging_entity = nullptr;
82
83 // Graphics
84 std::array<gfx::Bitmap, zelda3::kExpandedMapCount>* maps_bmp = nullptr;
86
87 // Widgets (read-only pointer to editor's unique_ptr)
88 std::unique_ptr<gui::TileSelectorWidget>* blockset_selector = nullptr;
89};
90
93 // Display-only project maps have no OverworldMap in the ROM model.
94 std::function<int()> displayed_map_count;
95 std::function<bool(int)> is_project_terrain_map;
96 std::function<void()> refresh_overworld_map;
97 std::function<absl::Status()> refresh_tile16_blockset;
98 std::function<void(int)> ensure_map_texture;
99 std::function<void(int, bool)> select_map_for_editing;
100 std::function<bool()> pick_tile16_from_hovered_canvas;
102 std::function<bool()> is_entity_hovered;
104 std::function<void()> open_map_properties;
105};
106
110 bool left_released = false;
111 bool left_dragged = false; // Moved past the drag threshold while down.
112 // The left press this release ends also landed on this canvas, on the map
113 // now under the cursor. False for a press that dismissed a popup or menu,
114 // or began on another window or another map.
115 bool left_press_owned = false;
116 bool right_clicked = false;
117 bool shift = false;
118 bool entity_hovered = false;
119};
120
127bool IsMapSelectClick(const MapClickInput& input);
128
130 public:
132
134 void Initialize(const CanvasNavigationContext& context,
135 const CanvasNavigationCallbacks& callbacks);
136
137 // ===========================================================================
138 // Map Detection and Loading
139 // ===========================================================================
140
143 absl::Status CheckForCurrentMap();
144
145 // Update hover and unpinned selection using scaled canvas-local coordinates.
146 // Separate from rendering so all edit modes share the same tracking policy.
147 std::optional<int> TrackMapAtCanvasPosition(ImVec2 scaled_position);
148
149 // ===========================================================================
150 // Map Interaction
151 // ===========================================================================
152
157
162
163 // ===========================================================================
164 // Pan and Zoom
165 // ===========================================================================
166 //
167 // All scrolling of the canvas child goes through this manager:
168 // BeginCanvasViewport() immediately before BeginChild: applies zoom,
169 // drag pan and wheel input via SetNextWindowScroll
170 // so the frame draws with its final scroll.
171 // EndCanvasViewport() inside the child after BeginCanvas: records the
172 // viewport rect, scroll and hover for next frame.
173 // The child is created with ImGuiWindowFlags_NoScrollWithMouse so ImGui's
174 // own fractional wheel scroll never runs on the canvas.
175
176 void BeginCanvasViewport();
177 void EndCanvasViewport(bool canvas_item_hovered);
178
180 void ZoomIn();
181
183 void ZoomOut();
184
186 void ZoomToFit();
187
189 void ResetOverworldView();
190
192 void CenterOverworldView();
193
195 void CenterOnMap(int map_id);
196 void CenterOnWorldTile(int world_x, int world_y);
197
198 bool is_panning() const { return pan_active_; }
199
203
204 // ===========================================================================
205 // Blockset Selector Synchronization
206 // ===========================================================================
207
211
214
215 // ===========================================================================
216 // Background Pre-loading
217 // ===========================================================================
218
220 void QueueAdjacentMapsForPreload(int center_map);
221
223 void ProcessPreloadQueue();
224
225 private:
228
229 // Map under the cursor: the hover-tracked map, else the canvas position.
230 std::optional<int> MapUnderCursor() const;
231
232 // Left press owned by this canvas (see MapClickInput::left_press_owned):
233 // ImGuiIO::MouseClickedTime of that press and the map it landed on.
234 double left_press_time_ = -1.0;
235 std::optional<int> left_press_map_;
236
237 // Hover debounce state
239 float hover_time_ = 0.0f;
240 static constexpr float kHoverBuildDelay = 0.15f;
241
242 // Background pre-loading state
243 std::vector<int> preload_queue_;
244 static constexpr float kPreloadStartDelay = 0.3f;
245
246 // Zoom by `steps` of kOverworldZoomStep about a viewport-local anchor.
247 void ZoomBySteps(int steps, ImVec2 anchor);
248 void SetScaleAboutAnchor(float new_scale, ImVec2 anchor);
249 ImVec2 ClampScroll(ImVec2 scroll) const;
250 ImVec2 ContentSize() const;
251
252 // Viewport state recorded by EndCanvasViewport (previous frame).
253 ImVec2 viewport_min_{0.0f, 0.0f};
254 ImVec2 viewport_size_{0.0f, 0.0f};
255 ImVec2 last_scroll_{0.0f, 0.0f};
258 bool viewport_known_ = false;
259
260 std::optional<ImVec2> hover_follow_suspended_at_;
261
262 // Scroll to apply at the next BeginCanvasViewport.
263 std::optional<ImVec2> pending_scroll_;
264 std::optional<int> pending_center_map_;
265
266 // Wheel state
268 float zoom_residual_ = 0.0f;
269 float zoom_idle_seconds_ = 0.0f;
270
271 // Drag pan: content stays pinned to the point grabbed at mouse-down.
272 int pan_button_ = -1;
273 bool pan_active_ = false;
274 ImVec2 pan_anchor_mouse_{0.0f, 0.0f};
275 ImVec2 pan_anchor_scroll_{0.0f, 0.0f};
276};
277
278} // namespace yaze::editor
279
280#endif // YAZE_APP_EDITOR_OVERWORLD_CANVAS_NAVIGATION_MANAGER_H
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:52
void ScrollBlocksetCanvasToCurrentTile()
Scroll the blockset (tile16 selector) to show the currently selected tile16.
absl::Status CheckForCurrentMap()
Detect which map the mouse is over, trigger lazy loading, draw the selection outline,...
void CenterOnMap(int map_id)
Center the viewport on map_id (same world grid).
void UpdateBlocksetSelectorState()
Push current tile count and selection into the blockset widget.
void ProcessPreloadQueue()
Process one map from the preload queue (call once per frame).
void SetScaleAboutAnchor(float new_scale, ImVec2 anchor)
std::optional< int > TrackMapAtCanvasPosition(ImVec2 scaled_position)
void CenterOnWorldTile(int world_x, int world_y)
void QueueAdjacentMapsForPreload(int center_map)
Queue the 4-connected neighbors of center_map for lazy build.
void Initialize(const CanvasNavigationContext &context, const CanvasNavigationCallbacks &callbacks)
Initialize with shared state and callbacks.
void HandleMapInteraction()
Click selection (see IsMapSelectClick) and double-click to open properties. The paint-tool right-clic...
void ZoomToFit()
Scale so the whole current world fits the viewport.
void ZoomOut()
Decrease canvas zoom by one step, keeping the view center fixed.
void CenterOverworldView()
Center the viewport on the current map.
bool SelectMapUnderCursor()
Make the map under the cursor the current map, ignoring the pin (the pin, if on, then holds this map)...
void EndCanvasViewport(bool canvas_item_hovered)
void ZoomIn()
Increase canvas zoom by one step, keeping the view center fixed.
void ResetOverworldView()
Reset scroll to top-left and scale to 1.0.
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:64
Editors are the view controllers for the application.
ImVec2 ScrollForZoomAtAnchor(ImVec2 scroll, ImVec2 anchor, float old_scale, float new_scale)
bool IsMapSelectClick(const MapClickInput &input)
Callbacks for operations that remain in the OverworldEditor.
std::function< absl::Status()> refresh_tile16_blockset
std::function< void(int, bool)> select_map_for_editing
std::function< bool()> is_entity_hovered
Returns true if an entity is currently hovered (for pan suppression).
std::function< void()> open_map_properties
Opens (and focuses) the Map Properties window. Double-click target.
Shared state pointers that the navigation manager reads/writes.
std::array< gfx::Bitmap, zelda3::kExpandedMapCount > * maps_bmp
std::unique_ptr< gui::TileSelectorWidget > * blockset_selector
One frame of canvas mouse input, reduced to what map selection needs.
ImVec2 Consume(ImVec2 wheel, float dt, float step_px, float snap_px)
Tilemap structure for SNES tile-based graphics management.
Definition tilemap.h:118