yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
base_entity_handler.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_DUNGEON_INTERACTION_BASE_ENTITY_HANDLER_H_
2#define YAZE_APP_EDITOR_DUNGEON_INTERACTION_BASE_ENTITY_HANDLER_H_
3
4#include <algorithm>
5#include <optional>
6#include <utility>
7
11#include "imgui/imgui.h"
12
13namespace yaze {
14namespace editor {
15
27 public:
28 virtual ~BaseEntityHandler() = default;
29
36 void SetContext(InteractionContext* ctx) { ctx_ = ctx; }
37
41 InteractionContext* context() const { return ctx_; }
42
43 // ========================================================================
44 // Placement Lifecycle
45 // ========================================================================
46
53 virtual void BeginPlacement() = 0;
54
61 virtual void CancelPlacement() = 0;
62
66 virtual bool IsPlacementActive() const = 0;
67
68 // ========================================================================
69 // Mouse Interaction
70 // ========================================================================
71
79 virtual bool HandleClick(int canvas_x, int canvas_y) = 0;
80
87 virtual void HandleDrag(ImVec2 current_pos, ImVec2 delta) = 0;
88
94 virtual void HandleRelease() = 0;
95 virtual bool HandleMouseWheel(float delta) { return false; }
96
97 // ========================================================================
98 // Rendering
99 // ========================================================================
100
107 virtual void DrawGhostPreview() = 0;
108
114 virtual void DrawSelectionHighlight() = 0;
115
116 // ========================================================================
117 // Hit Testing
118 // ========================================================================
119
127 virtual std::optional<size_t> GetEntityAtPosition(int canvas_x,
128 int canvas_y) const = 0;
129
130 // Per-frame toast render called unconditionally by InteractionCoordinator so
131 // the "Placed" message remains visible even after the user exits placement
132 // mode immediately after a successful click.
134 if (ImGui::GetCurrentContext() == nullptr) return;
136 ImGui::GetColorU32(AgentUI::GetTheme().status_success));
137 }
138
139 protected:
141
142 // ========================================================================
143 // Placement Success Toast (shared by all derived handlers)
144 // ========================================================================
145
146 // Call after a successful entity placement. Extends the toast display by
147 // kToastDuration seconds; rapid placements simply prolong the same toast.
149 if (ImGui::GetCurrentContext() == nullptr) return;
151 static_cast<float>(ImGui::GetTime()) + kToastDuration;
152 }
153
154 // Draw a fading "OK" toast near the canvas origin.
155 // @param msg Short message to display (e.g. "Placed").
156 // @param color Opaque RGBA colour for the text (alpha will be modulated).
157 void DrawSuccessToastOverlay(const char* msg, ImU32 color) const {
158 if (ImGui::GetCurrentContext() == nullptr) return;
159 if (toast_expire_time_ <= 0.0f ||
160 ImGui::GetTime() >= toast_expire_time_) {
161 return;
162 }
163 float remaining =
164 toast_expire_time_ - static_cast<float>(ImGui::GetTime());
165 // Fade out during the last 0.4 s; keep full opacity the rest of the time.
166 float alpha = std::min(1.0f, remaining / 0.4f);
167 // Blend alpha into supplied colour.
168 ImU32 base_rgb = color & 0x00FFFFFFu;
169 ImU32 alpha_ch = static_cast<ImU32>(alpha * 255.0f) << 24;
170 ImU32 toast_color = base_rgb | alpha_ch;
171
172 ImVec2 canvas_pos = GetCanvasZeroPoint();
173 ImDrawList* draw_list = ImGui::GetWindowDrawList();
174 // Render near the top-left canvas corner so it never overlaps tiles.
175 draw_list->AddText(ImVec2(canvas_pos.x + 8.0f, canvas_pos.y + 6.0f),
176 toast_color, msg);
177 }
178
179 // Shared toast expiry timestamp (seconds, from ImGui::GetTime()).
180 float toast_expire_time_ = 0.0f;
181
182 static constexpr float kToastDuration = 1.5f;
183
184 // ========================================================================
185 // Helper Methods (available to all derived handlers)
186 // ========================================================================
187
191 std::pair<int, int> RoomToCanvas(int room_x, int room_y) const {
192 return dungeon_coords::RoomToCanvas(room_x, room_y);
193 }
194
198 std::pair<int, int> CanvasToRoom(int canvas_x, int canvas_y) const {
199 return dungeon_coords::CanvasToRoom(canvas_x, canvas_y);
200 }
201
205 bool IsWithinBounds(int canvas_x, int canvas_y) const {
206 return dungeon_coords::IsWithinBounds(canvas_x, canvas_y);
207 }
208
212 ImVec2 GetCanvasZeroPoint() const {
213 if (!ctx_ || !ctx_->canvas) return ImVec2(0, 0);
214 return ctx_->canvas->zero_point();
215 }
216
220 float GetCanvasScale() const {
221 if (!ctx_ || !ctx_->canvas) return 1.0f;
222 float scale = ctx_->canvas->global_scale();
223 return scale > 0.0f ? scale : 1.0f;
224 }
225
229 bool HasValidContext() const { return ctx_ && ctx_->IsValid(); }
230
235 return ctx_ ? ctx_->GetCurrentRoom() : nullptr;
236 }
237};
238
239} // namespace editor
240} // namespace yaze
241
242#endif // YAZE_APP_EDITOR_DUNGEON_INTERACTION_BASE_ENTITY_HANDLER_H_
Abstract base class for entity interaction handlers.
virtual void HandleRelease()=0
Handle mouse release.
virtual bool IsPlacementActive() const =0
Check if placement mode is active.
virtual void BeginPlacement()=0
Begin placement mode.
InteractionContext * context() const
Get the interaction context.
virtual void HandleDrag(ImVec2 current_pos, ImVec2 delta)=0
Handle mouse drag.
virtual bool HandleClick(int canvas_x, int canvas_y)=0
Handle mouse click at canvas position.
virtual void DrawSelectionHighlight()=0
Draw selection highlight for selected entities.
virtual void DrawGhostPreview()=0
Draw ghost preview during placement.
std::pair< int, int > CanvasToRoom(int canvas_x, int canvas_y) const
Convert canvas pixel coordinates to room tile coordinates.
void DrawSuccessToastOverlay(const char *msg, ImU32 color) const
bool IsWithinBounds(int canvas_x, int canvas_y) const
Check if coordinates are within room bounds.
virtual void CancelPlacement()=0
Cancel current placement.
float GetCanvasScale() const
Get canvas global scale.
zelda3::Room * GetCurrentRoom() const
Get current room (convenience method)
virtual ~BaseEntityHandler()=default
bool HasValidContext() const
Check if context is valid.
virtual bool HandleMouseWheel(float delta)
std::pair< int, int > RoomToCanvas(int room_x, int room_y) const
Convert room tile coordinates to canvas pixel coordinates.
ImVec2 GetCanvasZeroPoint() const
Get canvas zero point (for screen coordinate conversion)
virtual std::optional< size_t > GetEntityAtPosition(int canvas_x, int canvas_y) const =0
Get entity at canvas position.
void SetContext(InteractionContext *ctx)
Set the interaction context.
static constexpr float kToastDuration
auto global_scale() const
Definition canvas.h:491
auto zero_point() const
Definition canvas.h:443
const AgentUITheme & GetTheme()
std::pair< int, int > RoomToCanvas(int room_x, int room_y)
Convert room tile coordinates to canvas pixel coordinates.
bool IsWithinBounds(int canvas_x, int canvas_y, int margin=0)
Check if coordinates are within room bounds.
std::pair< int, int > CanvasToRoom(int canvas_x, int canvas_y)
Convert canvas pixel coordinates to room tile coordinates.
Shared context for all interaction handlers.
bool IsValid() const
Check if context has required dependencies.
zelda3::Room * GetCurrentRoom() const
Get pointer to current room.