yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_object_interaction.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_DUNGEON_DUNGEON_OBJECT_INTERACTION_H
2#define YAZE_APP_EDITOR_DUNGEON_DUNGEON_OBJECT_INTERACTION_H
3
4#include <functional>
5#include <memory>
6#include <optional>
7#include <utility>
8#include <vector>
9
21#include "imgui/imgui.h"
26#include "zelda3/dungeon/room.h"
29
30#include "rom/rom.h"
31
32namespace yaze {
33namespace editor {
34
44 public:
51
52 // ========================================================================
53 // Context and Configuration
54 // ========================================================================
55
68
78
79 // Last mutation/invalidation domain (best-effort). Used by editors to route
80 // undo capture and avoid expensive rerenders for overlay-only edits.
87
88 // Legacy setter - kept for backwards compatibility
93
94 // Main interaction handling
97 void PlaceObjectAtPosition(int room_x, int room_y);
98
99 void DrawSelectionHighlights(); // Draw highlights for selected objects
101 const std::vector<zelda3::RoomObject>& objects); // Draw hover indicator
102
103 // Drag and select box functionality
104 void DrawGhostPreview(); // Draw ghost preview for object placement
105
106 // Coordinate conversion
107 std::pair<int, int> RoomToCanvasCoordinates(int room_x, int room_y) const;
108 std::pair<int, int> CanvasToRoomCoordinates(int canvas_x, int canvas_y) const;
109 bool IsWithinCanvasBounds(int canvas_x, int canvas_y, int margin = 32) const;
110
111 // State management
112 void SetCurrentRoom(DungeonRoomStore* rooms, int room_id);
113 void SetPreviewObject(const zelda3::RoomObject& object, bool loaded);
119
120 // Mode manager access
123
124 // Mode queries - delegate to mode manager
128
129 void CancelPlacement();
130
131 // Door placement mode
149
150 // Sprite placement mode
151 void SetSpritePlacementMode(bool enabled, uint8_t sprite_id = 0);
158 uint8_t GetPreviewSpriteId() const {
159 return mode_manager_.GetModeState().preview_sprite_id.value_or(0);
160 }
166
167 // Item placement mode
168 void SetItemPlacementMode(bool enabled, uint8_t item_id = 0);
172 void SetPreviewItemId(uint8_t id) {
174 }
175 uint8_t GetPreviewItemId() const {
176 return mode_manager_.GetModeState().preview_item_id.value_or(0);
177 }
183
184 // Selection state - delegates to ObjectSelection
185 std::vector<size_t> GetSelectedObjectIndices() const {
187 }
188 void SetSelectedObjects(const std::vector<size_t>& indices) {
191 for (size_t idx : indices) {
193 }
194 }
198 void ClearSelection();
199 bool IsObjectSelected(size_t index) const {
200 return selection_.IsObjectSelected(index);
201 }
202 size_t GetSelectionCount() const { return selection_.GetSelectionCount(); }
203
204 // Selection change notification
205 void SetSelectionChangeCallback(std::function<void()> callback) {
206 selection_.SetSelectionChangedCallback(std::move(callback));
207 }
208
209 // Helper for click selection with proper mode handling
210
211 // Object manipulation
212 void HandleScrollWheelResize(); // Resize selected objects with scroll wheel
213
214 // Move the current canvas selection by one editor nudge step. Tile objects
215 // move by room-tile units; doors, sprites, and items use their native grids.
216 // Mixed selections move together so keyboard nudging follows the same grammar
217 // as marquee and additive selection.
218 bool NudgeSelected(int delta_x, int delta_y);
221 void HandleCopySelected();
222 void HandlePasteObjects();
227
228 // Inspector-friendly mutation helpers (with undo + rerender integration).
229 // These are intended for UI panels that want to edit a single object without
230 // duplicating mutation/invalidation boilerplate.
231 bool SetObjectId(size_t index, int16_t id);
232 bool SetObjectSize(size_t index, uint8_t size);
233 bool SetObjectLayer(size_t index, zelda3::RoomObject::LayerType layer);
234
235 // Stored placement assignment for selected objects. Stream 2 is available
236 // only when every selected object belongs to the room object stream; torches
237 // and pushable blocks use a two-value special-table draw selector instead.
238 bool CanAssignSelectedObjectsToLayer(int target_layer) const;
239 bool SendSelectedToLayer(int target_layer);
240
241 // Object ordering (changes draw order within the layer)
242 // SNES draws objects in list order - first objects appear behind, last on top
243 void
244 SendSelectedToFront(); // Move to end of list (drawn last, appears on top)
245 void
246 SendSelectedToBack(); // Move to start of list (drawn first, appears behind)
247 void BringSelectedForward(); // Move up one position in list
248 void SendSelectedBackward(); // Move down one position in list
249
250 // Layer filter access (delegates to ObjectSelection)
251 void SetLayerFilter(int layer) { selection_.SetLayerFilter(layer); }
252 int GetLayerFilter() const { return selection_.GetLayerFilter(); }
255 const char* GetLayerFilterName() const {
257 }
258 void SetLayersMerged(bool merged) { selection_.SetLayersMerged(merged); }
259 bool AreLayersMerged() const { return selection_.AreLayersMerged(); }
260
261 // Check keyboard shortcuts for layer operations
263
264 // Callbacks - stored in interaction_context_ (single source of truth)
266 std::function<void(const zelda3::RoomObject&)> callback) {
267 object_placed_callback_ = std::move(callback);
268 }
269 void SetCacheInvalidationCallback(std::function<void()> callback) {
270 interaction_context_.on_invalidate_cache = std::move(callback);
272 }
273 void SetMutationCallback(std::function<void()> callback) {
274 interaction_context_.on_mutation = std::move(callback);
276 }
278 editor_system_ = system;
279 }
280
281 // Entity selection (doors, sprites, items)
282 void SelectEntity(EntityType type, size_t index);
290
291 // Draw entity selection highlights
293 void DrawDoorSnapIndicators(); // Show valid snap positions during door drag
294
295 // Callbacks for entity changes
296 void SetEntityChangedCallback(std::function<void()> callback) {
297 interaction_context_.on_entity_changed = std::move(callback);
299 }
301 std::function<void(int, std::optional<size_t>, int, int)> callback) {
302 interaction_context_.on_door_pair_navigation = std::move(callback);
304 }
305
306 private:
311
316
317 // Unified interaction context and coordinator for entity handling
320
321 // Unified mode state machine - replaces scattered boolean flags
323
324 // Helper to calculate object bounds
325 std::pair<int, int> CalculateObjectBounds(const zelda3::RoomObject& object);
326
327 // Refactored input handlers
328 void HandleLeftClick(const ImVec2& canvas_mouse_pos);
329 void UpdateCollisionPainting(const ImVec2& canvas_mouse_pos);
330 void UpdateWaterFillPainting(const ImVec2& canvas_mouse_pos);
331 void HandleObjectSelectionStart(const ImVec2& canvas_mouse_pos);
332 void HandleEmptySpaceClick(const ImVec2& canvas_mouse_pos);
333 void HandleMouseRelease();
334 bool HandleKeyboardNudge();
335
337 std::vector<zelda3::Sprite> sprites;
338 std::vector<zelda3::PotItem> items;
343
344 bool HasData() const { return !sprites.empty() || !items.empty(); }
345 void Clear() {
346 sprites.clear();
347 items.clear();
348 origin_pixel_x = 0;
349 origin_pixel_y = 0;
350 origin_tile_x = 0;
351 origin_tile_y = 0;
352 }
353 };
354
355 void CopySelectedEntitiesToClipboard(bool clipboard_origin_set);
356 std::vector<SelectedEntity> PasteEntityClipboardAt(int target_pixel_x,
357 int target_pixel_y);
358
359 // Preview object state (used by ModeState but kept here for ghost bitmap)
361
362 // Ghost preview bitmap (persists across frames for placement preview)
365
366 // Unified selection system - replaces legacy selection state
368
369 // Callbacks - stored only in interaction_context_ (no duplication)
370 std::function<void(const zelda3::RoomObject&)> object_placed_callback_;
371
372 // Entity selection state (doors, sprites, items)
373 // Note: entity selection is owned by InteractionCoordinator/handlers.
374};
375
376} // namespace editor
377} // namespace yaze
378
379#endif // YAZE_APP_EDITOR_DUNGEON_DUNGEON_OBJECT_INTERACTION_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:28
Handles object selection, placement, and interaction within the dungeon canvas.
void SetSelectedObjects(const std::vector< size_t > &indices)
DungeonCanvasTransform GetCanvasTransform() const
std::pair< int, int > CalculateObjectBounds(const zelda3::RoomObject &object)
bool IsWithinCanvasBounds(int canvas_x, int canvas_y, int margin=32) const
void SetCacheInvalidationCallback(std::function< void()> callback)
void HandleObjectSelectionStart(const ImVec2 &canvas_mouse_pos)
std::pair< int, int > RoomToCanvasCoordinates(int room_x, int room_y) const
void SetCurrentPaletteGroup(const gfx::PaletteGroup &group)
void SetContext(const InteractionContext &ctx)
Set the unified interaction context.
void SetDoorPairNavigationCallback(std::function< void(int, std::optional< size_t >, int, int)> callback)
std::vector< SelectedEntity > PasteEntityClipboardAt(int target_pixel_x, int target_pixel_y)
void CopySelectedEntitiesToClipboard(bool clipboard_origin_set)
void SetItemPlacementMode(bool enabled, uint8_t item_id=0)
void DrawHoverHighlight(const std::vector< zelda3::RoomObject > &objects)
std::function< void(const zelda3::RoomObject &) object_placed_callback_)
void SetSpritePlacementMode(bool enabled, uint8_t sprite_id=0)
void SetEditorSystem(zelda3::DungeonEditorSystem *system)
bool SetObjectLayer(size_t index, zelda3::RoomObject::LayerType layer)
void SetObjectPlacedCallback(std::function< void(const zelda3::RoomObject &)> callback)
void HandleLeftClick(const ImVec2 &canvas_mouse_pos)
void SetCurrentRoom(DungeonRoomStore *rooms, int room_id)
std::vector< size_t > GetSelectedObjectIndices() const
void SetSelectionChangeCallback(std::function< void()> callback)
void UpdateWaterFillPainting(const ImVec2 &canvas_mouse_pos)
InteractionCoordinator & entity_coordinator()
Get the interaction coordinator for entity handling.
bool CanAssignSelectedObjectsToLayer(int target_layer) const
void SetMutationCallback(std::function< void()> callback)
void SetEntityChangedCallback(std::function< void()> callback)
void SelectEntity(EntityType type, size_t index)
const InteractionCoordinator & entity_coordinator() const
void SetDoorPlacementMode(bool enabled, zelda3::DoorType type=zelda3::DoorType::NormalDoor)
std::pair< int, int > CanvasToRoomCoordinates(int canvas_x, int canvas_y) const
void HandleEmptySpaceClick(const ImVec2 &canvas_mouse_pos)
void SetPreviewObject(const zelda3::RoomObject &object, bool loaded)
void UpdateCollisionPainting(const ImVec2 &canvas_mouse_pos)
const InteractionModeManager & mode_manager() const
Coordinates interaction mode switching and dispatches to handlers.
void SetContext(InteractionContext *ctx)
Set the shared interaction context.
Manages interaction mode state and transitions.
void CancelCurrentMode()
Cancel current mode and return to Select.
InteractionMode GetMode() const
Get current interaction mode.
ModeState & GetModeState()
Get mutable reference to mode state.
Manages object selection state and operations for the dungeon editor.
void SetSelectionChangedCallback(std::function< void()> callback)
Set callback to be invoked when selection changes.
bool IsMaskModeActive() const
Check if mask selection mode is active.
bool IsRectangleSelectionActive() const
Check if a rectangle selection is in progress.
int GetLayerFilter() const
Get the current active layer filter.
bool IsObjectSelected(size_t index) const
Check if an object is selected.
std::vector< size_t > GetSelectedIndices() const
Get all selected object indices.
bool AreLayersMerged() const
Check if layers are currently merged.
size_t GetSelectionCount() const
Get the number of selected objects.
void SelectObject(size_t index, SelectionMode mode=SelectionMode::Single)
Select a single object by index.
void ClearSelection()
Clear all selections.
const char * GetLayerFilterName() const
Get the name of the current layer filter for display.
void SetLayersMerged(bool merged)
Set whether layers are currently merged in the room.
void SetLayerFilter(int layer)
Set the active layer filter for selection.
bool IsLayerFilterActive() const
Check if layer filtering is active.
bool HasSelection() const
Check if any objects are selected.
bool HasClipboardData() const
Check if clipboard has data.
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:64
auto global_scale() const
Definition canvas.h:397
auto zero_point() const
Definition canvas.h:348
auto scrolling() const
Definition canvas.h:350
MutationDomain
Domain/type of mutation for undo + invalidation routing.
EntityType
Type of entity that can be selected in the dungeon editor.
DoorType
Door types from ALTTP.
Definition door_types.h:33
@ NormalDoor
Normal door (upper layer)
Shared context for all interaction handlers.
std::function< void(int target_room_id, std::optional< size_t > target_door_index, int target_tile_x, int target_tile_y)> on_door_pair_navigation
std::function< void()> on_invalidate_cache
std::function< void()> on_entity_changed
std::optional< zelda3::DoorType > preview_door_type
std::optional< uint8_t > preview_item_id
std::optional< uint8_t > preview_sprite_id
Represents a selected entity in the dungeon editor.
Represents a group of palettes.