Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
VisualScriptEditorPanel_Core.cpp
Go to the documentation of this file.
1/**
2 * @file VisualScriptEditorPanel_Core.cpp
3 * @brief Core lifecycle methods for VisualScriptEditorPanel (Phase 24).
4 * @author Olympe Engine
5 * @date 2026-03-09
6 *
7 * @details This file contains the lifecycle methods extracted from VisualScriptEditorPanel.cpp:
8 * - Constructor initialization
9 * - Destructor cleanup
10 * - Initialize() with ImNodes context, UI helpers, and preset loading
11 * - Shutdown() with resource cleanup and registry management
12 *
13 * C++14 compliant — no std::optional, structured bindings, std::filesystem.
14 */
15
17#include "DebugController.h"
19#include "ConditionRegistry.h"
20#include "OperatorRegistry.h"
21#include "BBVariableRegistry.h"
22#include "MathOpOperand.h"
23#include "../system/system_utils.h"
24#include "../system/system_consts.h"
25#include "../NodeGraphCore/GlobalTemplateBlackboard.h"
26
27#include "../third_party/imgui/imgui.h"
28#include "../third_party/imnodes/imnodes.h"
29#include "../json_helper.h"
30#include "../TaskSystem/TaskGraphLoader.h"
31
32#include <fstream>
33#include <iostream>
34#include <algorithm>
35#include <cmath>
36#include <cstring>
37#include <sstream>
38#include <iomanip>
39#include <cstdlib>
40#include <unordered_set>
41
42namespace Olympe {
43
44// ============================================================================
45// Constructor
46// ============================================================================
47/**
48 * @brief VisualScriptEditorPanel Constructor
49 *
50 * Initializes the save-as filename buffer with a default "untitled_graph" name.
51 * This is called when a new editor panel tab is created for editing a blueprint graph.
52 *
53 * @note The ImNodes editor context and UI helper panels are NOT created here.
54 * They are initialized in Initialize() to ensure proper resource management
55 * and context isolation per panel instance.
56 */
58{
59 std::memset(m_saveAsFilename, 0, sizeof(m_saveAsFilename));
60 strcpy_s(m_saveAsFilename, sizeof(m_saveAsFilename), "untitled_graph");
61}
62
63// ============================================================================
64// Destructor
65// ============================================================================
66/**
67 * @brief VisualScriptEditorPanel Destructor
68 *
69 * Cleanup is deferred to Shutdown() to ensure proper sequencing of resource
70 * deallocation in the context of a tabbed editor interface.
71 *
72 * @note Do NOT manually delete m_imnodesContext or UI helper panels here.
73 * Always call Shutdown() first to free resources in correct order.
74 * @see Shutdown()
75 */
77{
78}
79
80// ============================================================================
81// Initialize
82// ============================================================================
83/**
84 * @brief Initialize the editor panel with ImNodes context and UI helpers
85 *
86 * Called when a blueprint is loaded into the editor (e.g., when a tab is opened).
87 * Sets up:
88 * - A dedicated ImNodes editor context for independent canvas state per panel
89 * - Dynamic data pin manager for condition/operand-driven pin generation
90 * - Node branch renderer for visual flow display
91 * - Node conditions panel for condition editing UI
92 * - Math operation panel for arithmetic node properties
93 * - Blackboard access panels (Get/Set operations)
94 * - Variable property panel for variable node editing
95 * - Condition preset library UI
96 * - Entity blackboard for local/global variable management (entity ID 0 = editor context)
97 *
98 * Phase 24 Enhancement (Condition Preset Embedding):
99 * - Presets are now stored IN the blueprint JSON (v4 schema) instead of external files
100 * - Each graph is self-contained; no need for separate preset files
101 * - Presets are loaded from m_template.Presets during Initialize()
102 * - If graph has presets, they populate m_presetRegistry; otherwise registry remains empty
103 * - Logging reports: count of loaded presets per graph
104 *
105 * Callback Setup:
106 * - OnDynamicPinsNeedRegeneration: Triggers when user confirms condition edits in modal
107 * - Fetches FRESH condition data from m_conditionsPanel (not stale eNode data)
108 * - Regenerates dynamic pins with updated operand information
109 * - Syncs m_template for serialization
110 *
111 * @see Shutdown()
112 * @see ConditionPresetRegistry::LoadFromPresetList()
113 * @see DynamicDataPinManager::RegeneratePinsFromConditions()
114 */
116{
117 // Create a dedicated ImNodes editor context for this panel instance.
118 // This ensures that node positions and canvas panning are tracked
119 // independently for each open tab (switching tabs preserves layout).
120 m_imnodesContext = ImNodes::EditorContextCreate();
121
122 // Phase 37 — Minimap support: Create ImNodes canvas editor adapter
123 // Abstracts minimap rendering for VisualScript canvas
124 m_canvasEditor = std::unique_ptr<ImNodesCanvasEditor>(
125 new ImNodesCanvasEditor(
126 "VisualScript", // name
127 ImVec2(0.0f, 0.0f), // canvasScreenPos (will be updated in RenderCanvas)
128 ImVec2(0.0f, 0.0f), // canvasSize (will be updated in RenderCanvas)
129 m_imnodesContext // imnodes context
130 ));
131 if (m_canvasEditor)
132 {
133 m_canvasEditor->SetMinimapVisible(m_minimapVisible);
134 m_canvasEditor->SetMinimapSize(m_minimapSize);
135 m_canvasEditor->SetMinimapPosition(m_minimapPosition);
136 }
137
138 // Phase 24 — Condition Preset UI: create helpers bound to m_presetRegistry.
139 m_pinManager = std::unique_ptr<DynamicDataPinManager>(
140 new DynamicDataPinManager(m_presetRegistry));
141 m_branchRenderer = std::unique_ptr<NodeBranchRenderer>(
142 new NodeBranchRenderer(m_presetRegistry, *m_pinManager));
143 m_conditionsPanel = std::unique_ptr<NodeConditionsPanel>(
144 new NodeConditionsPanel(m_presetRegistry));
145 m_mathOpPanel = std::unique_ptr<MathOpPropertyPanel>(
146 new MathOpPropertyPanel(m_presetRegistry, *m_pinManager));
147 m_getBBPanel = std::unique_ptr<GetBBValuePropertyPanel>(
148 new GetBBValuePropertyPanel());
149 m_setBBPanel = std::unique_ptr<SetBBValuePropertyPanel>(
150 new SetBBValuePropertyPanel());
151 m_variablePanel = std::unique_ptr<VariablePropertyPanel>(
152 new VariablePropertyPanel());
153 m_libraryPanel = std::unique_ptr<ConditionPresetLibraryPanel>(
154 new ConditionPresetLibraryPanel(m_presetRegistry));
155
156 // Phase 26 — SubGraph File Picker Modal
157 m_subGraphModal = std::unique_ptr<SubGraphFilePickerModal>(
158 new SubGraphFilePickerModal());
159
160 // Phase 24 Global Blackboard Integration: Create EntityBlackboard for managing
161 // both local and global variables in the editor context (entity ID 0)
162 m_entityBlackboard = std::unique_ptr<EntityBlackboard>(
163 new EntityBlackboard(0)); // 0 = editor context entity
164
165 // Wire the pin-regeneration callback so the Edit-Conditions modal can
166 // trigger a canvas update when the user confirms changes.
167 m_conditionsPanel->OnDynamicPinsNeedRegeneration = [this]()
168 {
169 if (m_selectedNodeID < 0)
170 return;
171 for (size_t ni = 0; ni < m_editorNodes.size(); ++ni)
172 {
173 VSEditorNode& eNode = m_editorNodes[ni];
174 if (eNode.nodeID != m_selectedNodeID)
175 continue;
176
177 // Phase 24: Get FRESH condition data from panel (not stale data from eNode)
178 // This ensures that edits via RenderConditionList dropdown are picked up
179 std::vector<NodeConditionRef> freshConditionRefs = m_conditionsPanel->GetConditionRefs();
180 std::vector<ConditionRef> freshOperandRefs = m_conditionsPanel->GetConditionOperandRefs();
181
182 // Sync fresh data to eNode
183 eNode.def.conditionRefs = freshConditionRefs;
184 eNode.def.conditionOperandRefs = freshOperandRefs;
185
186 // Regenerate pins with FRESH operand data
187 m_pinManager->RegeneratePinsFromConditions(freshConditionRefs, freshOperandRefs);
188 eNode.def.dynamicPins = m_pinManager->GetAllPins();
189
190 // Keep m_template in sync for serialization.
191 for (size_t ti = 0; ti < m_template.Nodes.size(); ++ti)
192 {
193 if (m_template.Nodes[ti].NodeID == m_selectedNodeID)
194 {
195 m_template.Nodes[ti].conditionRefs = eNode.def.conditionRefs;
196 m_template.Nodes[ti].conditionOperandRefs = eNode.def.conditionOperandRefs;
197 m_template.Nodes[ti].dynamicPins = eNode.def.dynamicPins;
198 break;
199 }
200 }
201 m_conditionsPanel->SetDynamicPins(eNode.def.dynamicPins);
202 m_dirty = true;
203 break;
204 }
205 };
206
207 // Phase 24 — Load presets from the graph (now embedded in blueprint JSON)
208 // instead of from an external file. This makes each blueprint self-contained.
209 // If the graph has presets, populate the registry; otherwise leave empty.
210 if (!m_template.Presets.empty())
211 {
213 SYSTEM_LOG << "[VSEditor] Initialize: loaded " << m_template.Presets.size()
214 << " presets from graph '" << m_template.Name << "'\n";
215 }
216 else
217 {
218 SYSTEM_LOG << "[VSEditor] Initialize: graph '" << m_template.Name
219 << "' has no embedded presets\n";
220 }
221
222 // Phase 33 — Initialize Selection Effect Renderer with default Olympe Blue style
223 // Provides unified selection UX across all canvas types
225 SYSTEM_LOG << "[VSEditor] Selection effect renderer initialized (Olympe Blue style)\n";
226}
227
228// ============================================================================
229// Shutdown
230// ============================================================================
231/**
232 * @brief Shutdown the editor panel and release all resources
233 *
234 * Called when a blueprint editor tab is closed or the application exits.
235 * Performs cleanup in the correct order:
236 * - Frees the ImNodes editor context (if allocated)
237 * - Clears editor node list (m_editorNodes)
238 * - Clears editor link list (m_editorLinks)
239 * - Clears positioned node cache (m_positionedNodes)
240 * - Releases all UI helper panels in Phase 24 order:
241 * * NodeConditionsPanel (used by OnDynamicPinsNeedRegeneration callback)
242 * * MathOpPropertyPanel (may reference m_presetRegistry)
243 * * GetBBValuePropertyPanel
244 * * SetBBValuePropertyPanel
245 * * VariablePropertyPanel
246 * * ConditionPresetLibraryPanel (may reference m_presetRegistry)
247 * * NodeBranchRenderer (may reference m_pinManager)
248 * * DynamicDataPinManager (lowest-level utility)
249 * - Resets condition panel node ID to sentinel value (-1)
250 *
251 * Phase 24 Notes:
252 * - DO NOT manually clear m_presetRegistry here; it is cleared by the destructor
253 * - UI helper reset() calls ensure no dangling callbacks or resource leaks
254 * - After Shutdown(), the panel can be re-initialized for a new graph
255 *
256 * @note Always call Shutdown() before destroying the panel instance.
257 * @see Initialize()
258 * @see ~VisualScriptEditorPanel()
259 */
261{
263 {
264 ImNodes::EditorContextFree(m_imnodesContext);
265 m_imnodesContext = nullptr;
266 }
267
268 // Phase 37 — Release minimap canvas editor
269 m_canvasEditor.reset();
270
271 m_editorNodes.clear();
272 m_editorLinks.clear();
273 m_positionedNodes.clear();
274
275 // Phase 24 — release helpers before registry is destroyed.
276 m_conditionsPanel.reset();
277 m_mathOpPanel.reset();
278 m_getBBPanel.reset();
279 m_setBBPanel.reset();
280 m_variablePanel.reset();
281 m_libraryPanel.reset();
282 m_branchRenderer.reset();
283 m_pinManager.reset();
284 m_subGraphModal.reset();
286}
287
288} // namespace Olympe
UI-side registry of available atomic tasks with display metadata.
Wrapper around the graph blackboard entries for dropdown editors.
Registry of available condition types for Branch/While node dropdowns.
Runtime debug controller for ATS Visual Scripting (Phase 5).
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Defines MathOpOperand — operand references for MathOp nodes.
Hardcoded lists of math and comparison operators for dropdown editors.
ImNodes-based graph editor for ATS Visual Script graphs (Phase 5).
void LoadFromPresetList(const std::vector< ConditionPreset > &presets)
Loads presets from a vector of ConditionPreset objects (clears existing data first).
void ApplyStyle_OlympeBlue()
Style standard "Olympe Blue" - Cyan vif avec glow modéré
std::vector< TaskNodeDefinition > Nodes
All graph nodes.
std::string Name
Friendly name of this template (e.g. "PatrolBehaviour")
std::vector< ConditionPreset > Presets
Presets are now stored in the graph JSON, not in external files.
std::unique_ptr< DynamicDataPinManager > m_pinManager
Dynamic pin manager shared across all Branch nodes in this panel.
char m_saveAsFilename[256]
Buffer for the user-entered filename (without extension)
std::vector< VSEditorLink > m_editorLinks
Editor links (exec + data)
std::unique_ptr< VariablePropertyPanel > m_variablePanel
Properties-panel sub-widget for the selected Variable node (data pure).
VisualScriptEditorPanel()
VisualScriptEditorPanel Constructor.
TaskGraphTemplate m_template
The template currently being edited.
void Shutdown()
Shutdown the editor panel and release all resources.
std::unique_ptr< MathOpPropertyPanel > m_mathOpPanel
Properties-panel sub-widget for the selected MathOp node.
void Initialize()
Initialize the editor panel with ImNodes context and UI helpers.
std::unique_ptr< EntityBlackboard > m_entityBlackboard
Per-entity blackboard instance (combines local + global variables) Created in Initialize() and manage...
int m_condPanelNodeID
ID of the node currently loaded into m_conditionsPanel (-1 = none).
std::unique_ptr< NodeConditionsPanel > m_conditionsPanel
Properties-panel sub-widget for the selected Branch node.
std::unique_ptr< NodeBranchRenderer > m_branchRenderer
Specialized renderer for Branch nodes (4-section layout with conditions).
std::unique_ptr< SubGraphFilePickerModal > m_subGraphModal
Phase 26 — SubGraph File Picker Modal.
std::unique_ptr< GetBBValuePropertyPanel > m_getBBPanel
Properties-panel sub-widget for the selected GetBBValue node.
std::unique_ptr< SetBBValuePropertyPanel > m_setBBPanel
Properties-panel sub-widget for the selected SetBBValue node.
std::unordered_set< int > m_positionedNodes
Nodes for which ImNodes has been given a position.
SelectionEffectRenderer m_selectionRenderer
Renders glow effect for selected nodes (cyan halo + thickened border).
std::unique_ptr< ImNodesCanvasEditor > m_canvasEditor
Canvas editor adapter for minimap support (Phase 37) Abstracts imnodes minimap rendering through ICan...
int m_minimapPosition
Minimap position (0=TopLeft, 1=TopRight, 2=BottomLeft, 3=BottomRight)
float m_minimapSize
Minimap size ratio (0.05-0.5 of canvas)
std::vector< VSEditorNode > m_editorNodes
Editor nodes (mirrors m_template.Nodes + position/selection state)
bool m_minimapVisible
Minimap visibility flag for VisualScript canvas.
int m_selectedNodeID
Currently selected node (for properties panel)
~VisualScriptEditorPanel()
VisualScriptEditorPanel Destructor.
ConditionPresetRegistry m_presetRegistry
Global registry of ConditionPreset objects.
std::unique_ptr< ConditionPresetLibraryPanel > m_libraryPanel
Global condition preset library panel (UI for creating/editing/deleting presets).
< Provides AssetID and INVALID_ASSET_ID
#define SYSTEM_LOG