Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
ICanvasEditor.h
Go to the documentation of this file.
1/**
2 * @file ICanvasEditor.h
3 * @brief Standardized Canvas Editor interface for unified architecture
4 * @details Abstraction layer for pan/zoom/grid management across VisualScript and PrefabCanvas
5 *
6 * @design
7 * - Unifies coordinate systems (Screen, Canvas, Editor, Grid spaces)
8 * - Abstracts pan/zoom control (some implementations expose zoom, others don't)
9 * - Provides grid rendering integration
10 * - Separates lifecycle (BeginRender/EndRender) from node/link domain logic
11 *
12 * @usage
13 * // In any editor's render loop:
14 * m_canvasEditor->BeginRender();
15 * {
16 * // Render domain-specific content (nodes, links, etc.)
17 * RenderMyNodes();
18 * }
19 * m_canvasEditor->EndRender();
20 *
21 * @compatibility C++14
22 */
23
24#pragma once
25
26#include "../../third_party/imgui/imgui.h"
27#include "CanvasGridRenderer.h"
28#include <vector>
29#include <tuple>
30
31namespace Olympe
32{
33 /**
34 * @class ICanvasEditor
35 * @brief Abstract interface for canvas editors with unified pan/zoom/grid management
36 *
37 * Implementations:
38 * - ImNodesCanvasEditor: Wraps ImNodes::BeginNodeEditor/EndNodeEditor
39 * - CustomCanvasEditor: Manual pan/zoom implementation with zoom support
40 *
41 * Key contract:
42 * 1. BeginRender() must be called once per frame at start of canvas rendering
43 * 2. EndRender() must be called once per frame at end of canvas rendering
44 * 3. All coordinate transformations maintain consistency across pan/zoom states
45 * 4. Pan/zoom state is persistent across frames (for smooth interaction)
46 */
48 {
49 public:
50 virtual ~ICanvasEditor() = default;
51
52 // ====================================================================
53 // Lifecycle Management
54 // ====================================================================
55
56 /**
57 * @brief Begin rendering cycle for this canvas
58 * @details Must be called at the start of each frame's canvas rendering
59 * - Initializes draw state
60 * - Updates pan/zoom from input
61 * - Prepares coordinate systems
62 *
63 * Implementations:
64 * - ImNodesCanvasEditor: Calls ImNodes::BeginNodeEditor()
65 * - CustomCanvasEditor: Updates m_canvasOffset and m_canvasZoom from input
66 */
67 virtual void BeginRender() = 0;
68
69 /**
70 * @brief End rendering cycle for this canvas
71 * @details Must be called at the end of each frame's canvas rendering
72 * - Finalizes draw state
73 * - Captures post-render input events (hover detection, selection, etc.)
74 *
75 * Implementations:
76 * - ImNodesCanvasEditor: Calls ImNodes::EndNodeEditor()
77 * - CustomCanvasEditor: Performs hover/selection detection, context menu logic
78 */
79 virtual void EndRender() = 0;
80
81 // ====================================================================
82 // Coordinate Transformation Systems
83 // ====================================================================
84
85 /**
86 * @brief Transform screen space coordinates to canvas space
87 * @param screenPos Coordinates in screen space (pixels from top-left of window)
88 * @return Coordinates in canvas space (logical coordinates after pan/zoom)
89 *
90 * Canvas space = screen space transformed by:
91 * - Subtract canvas origin (where canvas starts on screen)
92 * - Subtract pan offset (where user panned to)
93 * - Divide by zoom level (scale to logical units)
94 *
95 * Formula: canvas = (screen - canvasOrigin - pan) / zoom
96 */
97 virtual ImVec2 ScreenToCanvas(const ImVec2& screenPos) const = 0;
98
99 /**
100 * @brief Transform canvas space coordinates to screen space
101 * @param canvasPos Coordinates in canvas space (logical coordinates)
102 * @return Coordinates in screen space (pixels on screen)
103 *
104 * Inverse of ScreenToCanvas:
105 * screen = canvasPos * zoom + pan + canvasOrigin
106 */
107 virtual ImVec2 CanvasToScreen(const ImVec2& canvasPos) const = 0;
108
109 /**
110 * @brief Transform editor space to grid space
111 * @param editorPos Coordinates in editor space
112 * @return Coordinates in grid space (pan-independent)
113 *
114 * Grid space removes the pan offset, allowing positions to be stored
115 * pan-independently. Useful for serialization.
116 *
117 * For imnodes: grid space = SetNodeGridSpacePos (pan-independent storage)
118 * For custom: grid space = editorPos - pan offset
119 */
120 virtual ImVec2 EditorToGrid(const ImVec2& editorPos) const = 0;
121
122 /**
123 * @brief Transform grid space to editor space
124 * @param gridPos Coordinates in grid space
125 * @return Coordinates in editor space
126 *
127 * Inverse of EditorToGrid, adds back the pan offset.
128 */
129 virtual ImVec2 GridToEditor(const ImVec2& gridPos) const = 0;
130
131 // ====================================================================
132 // Pan Management
133 // ====================================================================
134
135 /**
136 * @brief Get current pan offset
137 * @return Offset vector representing where canvas origin is panned to
138 * @note For imnodes: reads EditorContextGetPanning()
139 * @note For custom: returns m_canvasOffset
140 */
141 virtual ImVec2 GetPan() const = 0;
142
143 /**
144 * @brief Set pan offset directly
145 * @param offset New pan offset
146 * @details Used for programmatic pan (keyboard shortcut, reset view, etc.)
147 *
148 * @note For imnodes: calls EditorContextResetPanning()
149 * @note For custom: updates m_canvasOffset directly
150 */
151 virtual void SetPan(const ImVec2& offset) = 0;
152
153 /**
154 * @brief Pan by delta amount
155 * @param delta Relative pan movement
156 * @note Convenience method: SetPan(GetPan() + delta)
157 */
158 virtual void PanBy(const ImVec2& delta) = 0;
159
160 /**
161 * @brief Reset pan to origin (0, 0)
162 * @note Convenience method: SetPan(ImVec2(0, 0))
163 */
164 virtual void ResetPan() = 0;
165
166 // ====================================================================
167 // Zoom Management
168 // ====================================================================
169
170 /**
171 * @brief Get current zoom level
172 * @return Zoom scale (1.0 = 100%, 2.0 = 200%, 0.5 = 50%)
173 * @note For imnodes: always returns 1.0f (no zoom support)
174 * @note For custom: returns m_canvasZoom (0.1f to 3.0f)
175 */
176 virtual float GetZoom() const = 0;
177
178 /**
179 * @brief Set zoom level directly
180 * @param scale New zoom scale
181 * @param zoomCenter Optional center point for zoom (in screen space)
182 * @details If zoomCenter provided, zoom maintains visual position of that point
183 *
184 * @note For imnodes: this is a no-op (returns without change)
185 * @note For custom: updates m_canvasZoom with zoom-center adjustment
186 */
187 virtual void SetZoom(float scale, const ImVec2* zoomCenter = nullptr) = 0;
188
189 /**
190 * @brief Zoom by multiplier
191 * @param factor Zoom multiplier (1.1 = 10% zoom in, 0.9 = 10% zoom out)
192 * @param zoomCenter Optional center point for zoom
193 * @note Convenience: SetZoom(GetZoom() * factor, zoomCenter)
194 */
195 virtual void ZoomBy(float factor, const ImVec2* zoomCenter = nullptr) = 0;
196
197 /**
198 * @brief Get zoom limits (min, max)
199 * @return {minZoom, maxZoom}
200 * @note For imnodes: {1.0f, 1.0f} (no zoom support)
201 * @note For custom: {0.1f, 3.0f}
202 */
203 virtual ImVec2 GetZoomLimits() const = 0;
204
205 /**
206 * @brief Reset zoom to 1.0x
207 * @note Convenience: SetZoom(1.0f)
208 */
209 virtual void ResetZoom() = 0;
210
211 /**
212 * @brief Reset both pan and zoom to defaults
213 * @note Convenience: ResetPan(); ResetZoom();
214 */
215 virtual void ResetView() = 0;
216
217 // ====================================================================
218 // Grid Management
219 // ====================================================================
220
221 /**
222 * @brief Get current grid configuration
223 * @return GridConfig struct with all grid parameters
224 * @note Reflects current zoom state in scaledSpacing
225 */
227
228 /**
229 * @brief Render grid using current configuration
230 * @param preset Style preset to use
231 * @details Delegates to CanvasGridRenderer::RenderGrid()
232 */
234
235 /**
236 * @brief Enable/disable grid rendering
237 * @param enabled True to show grid, false to hide
238 */
239 virtual void SetGridVisible(bool enabled) = 0;
240
241 /**
242 * @brief Check if grid is visible
243 * @return True if grid will be rendered
244 */
245 virtual bool IsGridVisible() const = 0;
246
247 // ====================================================================
248 // Canvas Properties
249 // ====================================================================
250
251 /**
252 * @brief Get canvas position on screen
253 * @return Top-left corner of canvas in screen space (pixels)
254 */
255 virtual ImVec2 GetCanvasScreenPos() const = 0;
256
257 /**
258 * @brief Get canvas size in screen space
259 * @return Width and height of canvas rendering area (pixels)
260 */
261 virtual ImVec2 GetCanvasSize() const = 0;
262
263 /**
264 * @brief Set canvas screen position (call each frame to update)
265 * @param screenPos Top-left corner position in screen space
266 * @details Required for minimap coordinate calculations each frame
267 */
268 virtual void SetCanvasScreenPos(const ImVec2& screenPos) = 0;
269
270 /**
271 * @brief Set canvas size (call each frame to update)
272 * @param size Width and height in screen space
273 * @details Required for minimap rendering calculations each frame
274 */
275 virtual void SetCanvasSize(const ImVec2& size) = 0;
276
277 /**
278 * @brief Get canvas visible area as AABB in canvas space
279 * @return {minCorner, maxCorner} in canvas logical coordinates
280 * @details Useful for culling: which nodes are visible on screen?
281 */
283
284 /**
285 * @brief Check if point in screen space is within canvas bounds
286 * @param screenPos Position in screen space
287 * @return True if point is inside canvas area
288 */
289 virtual bool IsPointInCanvas(const ImVec2& screenPos) const = 0;
290
291 // ====================================================================
292 // Context Information
293 // ====================================================================
294
295 /**
296 * @brief Check if canvas is being hovered by mouse
297 * @return True if mouse is over canvas and canvas has focus
298 */
299 virtual bool IsCanvasHovered() const = 0;
300
301 /**
302 * @brief Get the name/identifier of this canvas
303 * @return String identifier for debugging and logging
304 */
305 virtual const char* GetCanvasName() const = 0;
306
307 // ====================================================================
308 // Minimap Management
309 // ====================================================================
310
311 /**
312 * @brief Render minimap overlay
313 * @details Renders minimap showing current viewport relative to full graph
314 *
315 * Implementations:
316 * - ImNodesCanvasEditor: Calls ImNodes::MiniMap()
317 * - CustomCanvasEditor: No-op (minimap not yet supported for custom canvas)
318 *
319 * Note: Must be called BEFORE EndRender() for imnodes
320 */
321 virtual void RenderMinimap() = 0;
322
323 /**
324 * @brief Enable/disable minimap rendering
325 * @param enabled True to show minimap, false to hide
326 */
327 virtual void SetMinimapVisible(bool enabled) = 0;
328
329 /**
330 * @brief Check if minimap is visible
331 * @return True if minimap will be rendered
332 */
333 virtual bool IsMinimapVisible() const = 0;
334
335 /**
336 * @brief Set minimap size scale
337 * @param scale Size multiplier (0.1f = 10%, 0.3f = 30% of canvas)
338 */
339 virtual void SetMinimapSize(float scale) = 0;
340
341 /**
342 * @brief Get minimap size scale
343 * @return Current size multiplier
344 */
345 virtual float GetMinimapSize() const = 0;
346
347 /**
348 * @brief Set minimap position
349 * @param position Position enum value (TopLeft, TopRight, BottomLeft, BottomRight)
350 */
351 virtual void SetMinimapPosition(int position) = 0;
352
353 /**
354 * @brief Get minimap position
355 * @return Current position enum value
356 */
357 virtual int GetMinimapPosition() const = 0;
358
359 /**
360 * @brief Update minimap with current graph node data
361 * @param nodes Vector of (nodeId, posX, posY, width, height) tuples representing graph nodes
362 * @param graphMinX Graph bounds left edge
363 * @param graphMaxX Graph bounds right edge
364 * @param graphMinY Graph bounds top edge
365 * @param graphMaxY Graph bounds bottom edge
366 * @details Required for custom minimap rendering (CustomCanvasEditor)
367 * ImNodes minimap ignores this (uses internal ImNodes node positions)
368 */
369 virtual void UpdateMinimapNodes(
370 const std::vector<std::tuple<int, float, float, float, float>>& nodes,
371 float graphMinX, float graphMaxX, float graphMinY, float graphMaxY) = 0;
372
373 /**
374 * @brief Update minimap with current viewport bounds
375 * @param viewMinX Visible area left edge
376 * @param viewMaxX Visible area right edge
377 * @param viewMinY Visible area top edge
378 * @param viewMaxY Visible area bottom edge
379 * @param graphMinX Graph bounds left edge
380 * @param graphMaxX Graph bounds right edge
381 * @param graphMinY Graph bounds top edge
382 * @param graphMaxY Graph bounds bottom edge
383 * @details Required for custom minimap rendering (CustomCanvasEditor)
384 * Normalizes viewport bounds relative to graph bounds for minimap display
385 */
387 float viewMinX, float viewMaxX, float viewMinY, float viewMaxY,
388 float graphMinX, float graphMaxX, float graphMinY, float graphMaxY) = 0;
389 };
390
391} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
GridStylePreset
Pre-configured grid styles matching professional editors.
Abstract interface for canvas editors with unified pan/zoom/grid management.
virtual void ResetView()=0
Reset both pan and zoom to defaults.
virtual bool IsMinimapVisible() const =0
Check if minimap is visible.
virtual void SetCanvasScreenPos(const ImVec2 &screenPos)=0
Set canvas screen position (call each frame to update)
virtual void ResetZoom()=0
Reset zoom to 1.0x.
virtual void SetPan(const ImVec2 &offset)=0
Set pan offset directly.
virtual ImVec2 ScreenToCanvas(const ImVec2 &screenPos) const =0
Transform screen space coordinates to canvas space.
virtual void RenderMinimap()=0
Render minimap overlay.
virtual void SetMinimapVisible(bool enabled)=0
Enable/disable minimap rendering.
virtual ImVec2 CanvasToScreen(const ImVec2 &canvasPos) const =0
Transform canvas space coordinates to screen space.
virtual void ZoomBy(float factor, const ImVec2 *zoomCenter=nullptr)=0
Zoom by multiplier.
virtual ImVec2 GetPan() const =0
Get current pan offset.
virtual ImVec2 EditorToGrid(const ImVec2 &editorPos) const =0
Transform editor space to grid space.
virtual void BeginRender()=0
Begin rendering cycle for this canvas.
virtual void SetMinimapSize(float scale)=0
Set minimap size scale.
virtual bool IsCanvasHovered() const =0
Check if canvas is being hovered by mouse.
virtual void ResetPan()=0
Reset pan to origin (0, 0)
virtual ImVec2 GetZoomLimits() const =0
Get zoom limits (min, max)
virtual void SetZoom(float scale, const ImVec2 *zoomCenter=nullptr)=0
Set zoom level directly.
virtual void EndRender()=0
End rendering cycle for this canvas.
virtual ImVec2 GridToEditor(const ImVec2 &gridPos) const =0
Transform grid space to editor space.
virtual void UpdateMinimapNodes(const std::vector< std::tuple< int, float, float, float, float > > &nodes, float graphMinX, float graphMaxX, float graphMinY, float graphMaxY)=0
Update minimap with current graph node data.
virtual float GetZoom() const =0
Get current zoom level.
virtual CanvasGridRenderer::GridConfig GetGridConfig() const =0
Get current grid configuration.
virtual void RenderGrid(CanvasGridRenderer::GridStylePreset preset)=0
Render grid using current configuration.
virtual int GetMinimapPosition() const =0
Get minimap position.
virtual void UpdateMinimapViewport(float viewMinX, float viewMaxX, float viewMinY, float viewMaxY, float graphMinX, float graphMaxX, float graphMinY, float graphMaxY)=0
Update minimap with current viewport bounds.
virtual ImVec2 GetCanvasSize() const =0
Get canvas size in screen space.
virtual ~ICanvasEditor()=default
virtual void SetCanvasSize(const ImVec2 &size)=0
Set canvas size (call each frame to update)
virtual ImVec2 GetCanvasScreenPos() const =0
Get canvas position on screen.
virtual bool IsGridVisible() const =0
Check if grid is visible.
virtual const char * GetCanvasName() const =0
Get the name/identifier of this canvas.
virtual void SetMinimapPosition(int position)=0
Set minimap position.
virtual void GetCanvasVisibleBounds(ImVec2 &outMin, ImVec2 &outMax) const =0
Get canvas visible area as AABB in canvas space.
virtual float GetMinimapSize() const =0
Get minimap size scale.
virtual void PanBy(const ImVec2 &delta)=0
Pan by delta amount.
virtual bool IsPointInCanvas(const ImVec2 &screenPos) const =0
Check if point in screen space is within canvas bounds.
virtual void SetGridVisible(bool enabled)=0
Enable/disable grid rendering.
< Provides AssetID and INVALID_ASSET_ID
Configuration parameters for grid rendering.