Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
blueprinteditor.h
Go to the documentation of this file.
1/*
2 * Olympe Blueprint Editor - Backend (Business Logic)
3 *
4 * Singleton backend for the Blueprint Editor managing:
5 * - Editor state and lifecycle
6 * - Asset management and current blueprint data
7 * - Business logic and data models
8 * - NO UI/GUI code (separated into BlueprintEditorGUI)
9 *
10 * ╔════════════════════════════════════════════════════════════════════════════╗
11 * ║ DOCUMENTATION INDEX ║
12 * ╚════════════════════════════════════════════════════════════════════════════╝
13 *
14 * Complete documentation available in Docs/ directory:
15 *
16 * 📚 PRIMARY GUIDES:
17 * • Docs/Blueprint_Editor_User_Guide_v4.md
18 * -> Step-by-step workflows, CRUD operations, debugging (20 min read)
19 *
20 * • Docs/Blueprint_Editor_Advanced_Systems.md
21 * -> SubGraphs, Profiler, Templates, Validation (45 min read)
22 *
23 * • Docs/Blueprint_Editor_Visual_Diagrams.md
24 * -> Interactive Mermaid flowcharts (15 min read)
25 *
26 * • Docs/README_Documentation_Index.md
27 * -> Master index with learning paths and topic search
28 *
29 * ⚠️ DEPRECATED (DO NOT USE):
30 * • Docs/Blueprint Editor Features.md
31 * -> Legacy BT v2 documentation (replaced by v4 guides above)
32 *
33 * ╔════════════════════════════════════════════════════════════════════════════╗
34 * ║ CURRENT SYSTEM (v4) ║
35 * ╚════════════════════════════════════════════════════════════════════════════╝
36 *
37 * EDITOR: VisualScriptEditorPanel (Phase 5)
38 * FILE FORMAT: .ats or .json with schema_version: 4
39 * GRAPH TYPE: "VisualScript" (ATS Visual Script)
40 * LOADER: TaskGraphLoader::ParseSchemaV4() (primary path)
41 * EXECUTOR: VSGraphExecutor::ExecuteFrame()
42 *
43 * NODE TYPES: EntryPoint, Branch, Sequence, While, AtomicTask,
44 * GetBBValue, SetBBValue, MathOp, SubGraph, DoOnce, Delay
45 *
46 * CONNECTIONS: ExecConnections (flow control) + DataConnections (typed data)
47 *
48 * ╔════════════════════════════════════════════════════════════════════════════╗
49 * ║ ADVANCED FEATURES ║
50 * ╚════════════════════════════════════════════════════════════════════════════╝
51 *
52 * SUBGRAPHS (Phase 8):
53 * • Modular graph composition (depth-limited to 4)
54 * • Cycle detection via SubGraphCallStack
55 * • Schema v5 format (rootGraph + subgraphs dictionary)
56 * • Tab-based navigation in editor
57 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "SubGraph System"
58 *
59 * PERFORMANCE PROFILER (Phase 5):
60 * • Per-node execution metrics (avg/max/total time)
61 * • Frame timeline (last 60 frames)
62 * • Hotspot table sorted by average time
63 * • CSV export for external analysis
64 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "Performance Profiler"
65 *
66 * DEBUG SYSTEM (Phase 5):
67 * • Breakpoints (F9 toggle, runtime check)
68 * • Step controls (F5 Continue, F10 Step Over, F11 Step Into)
69 * • Call stack inspection
70 * • Live Blackboard variable watch
71 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "Debug System"
72 *
73 * BLACKBOARD SYSTEM (Phase 2.1):
74 * • Variable types: Int, Float, Bool, String, Vector3
75 * • Scoping: local: (per-entity) / global: (world-shared)
76 * • GetBBValue / SetBBValue nodes for read/write
77 * -> Docs: Docs/Blueprint_Editor_User_Guide_v4.md -> Section 6
78 *
79 * TEMPLATE MANAGER (Phase 5):
80 * • Save graphs as reusable templates
81 * • Template catalog with categorization (AI, Character, Enemy)
82 * • Apply templates to current graph
83 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "Template Manager"
84 *
85 * VALIDATION SYSTEM:
86 * • Real-time error detection (cycles, type mismatches, missing properties)
87 * • Severity levels: Critical, Error, Warning, Info
88 * • Click errors to navigate to affected nodes
89 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "Validation System"
90 *
91 * COMMAND SYSTEM (Undo/Redo):
92 * • Full undo/redo support (Ctrl+Z / Ctrl+Y)
93 * • Command pattern with CreateNode, DeleteNode, CreateLink
94 * • Composite commands for batch operations
95 * -> Docs: Docs/Blueprint_Editor_Advanced_Systems.md -> "Command System"
96 *
97 * ╔════════════════════════════════════════════════════════════════════════════╗
98 * ║ QUICK START ║
99 * ╚════════════════════════════════════════════════════════════════════════════╝
100 *
101 * 1. View -> VS Graph Editor -> New Graph
102 * 2. Right-click -> Flow Control -> EntryPoint
103 * 3. Right-click -> Flow Control -> Branch
104 * 4. Drag from "Out" pin to "In" pin
105 * 5. Select Branch node -> Properties -> Set "ConditionKey" = "local:HasEnemy"
106 * 6. View -> Blackboard -> Add Variable: "HasEnemy" (Bool, default: false)
107 * 7. Right-click -> Tasks -> AtomicTask
108 * 8. Ctrl+S to save as "my_ai.ats"
109 *
110 * -> Full tutorial: Docs/Blueprint_Editor_User_Guide_v4.md -> Section 10
111 */
112
113#pragma once
114
115#include "EntityBlueprint.h"
117#include "../../Source/third_party/nlohmann/json.hpp"
118#include <string>
119#include <memory>
120#include <vector>
121#include <map>
122
123namespace Olympe
124{
125 // Forward declaration
126 class BlueprintEditorGUI;
127
128 // Forward declare Blueprint namespace types
129 namespace Blueprint
130 {
131 class CommandStack;
132 }
133
134 // Use nlohmann json
136
137 // Asset metadata structure for backend
139 {
140 std::string filepath; // Full path to asset file
141 std::string name; // Asset name (from JSON or filename)
142 std::string type; // Asset type (EntityBlueprint, BehaviorTree, etc.)
143 std::string description; // Asset description
144 bool isDirectory; // True if this is a directory
145 int componentCount; // For EntityBlueprint
146 int nodeCount; // For BehaviorTree
147 std::vector<std::string> components; // Component types
148 std::vector<std::string> nodes; // Node types
149 bool isValid; // False if JSON is malformed
150 std::string errorMessage; // Error message if not valid
151
153 };
154
155 // Asset tree node structure for backend
157 {
158 std::string name; // Display name (filename without path)
159 std::string fullPath; // Complete file path
160 std::string type; // Asset type
162 std::vector<std::shared_ptr<AssetNode>> children;
163
164 AssetNode(const std::string& n, const std::string& path, bool isDir)
165 : name(n), fullPath(path), isDirectory(isDir) {}
166 };
167
168 /**
169 * BlueprintEditor Singleton Backend
170 * Manages all business logic, state, and data for the Blueprint Editor
171 * Completely separated from UI rendering (handled by BlueprintEditorGUI)
172 */
174 {
175 public:
176 // Singleton access
177 static BlueprintEditor& Instance();
178 static BlueprintEditor& Get() { return Instance(); }
179
180 // Lifecycle methods
181 void Initialize();
182 void Shutdown();
183 void Update(float deltaTime); // Called by GameEngine when active
184
185 // Editor mode initialization
186 void InitializeRuntimeEditor(); // Initialize in Runtime mode (read-only)
187 void InitializeStandaloneEditor(); // Initialize in Standalone mode (full CRUD)
188
189 // Editor state
190 bool IsActive() const { return m_IsActive; }
193
194 // Blueprint operations
195 void NewBlueprint(const std::string& name, const std::string& description = "");
196 bool LoadBlueprint(const std::string& filepath);
197 bool SaveBlueprint();
198 bool SaveBlueprintAs(const std::string& filepath);
199
200 // Blueprint access (const for read-only, non-const for editing)
203
204 // State queries
205 bool HasBlueprint() const { return !m_CurrentBlueprint.name.empty(); }
206 bool HasUnsavedChanges() const { return m_HasUnsavedChanges; }
207 const std::string& GetCurrentFilepath() const { return m_CurrentFilepath; }
208
209 // State modification
212
213 // Asset management
214 std::string GetAssetRootPath() const { return m_AssetRootPath; }
215 void SetAssetRootPath(const std::string& path);
216
217 // Asset scanning and retrieval
218 void RefreshAssets(); // Rescan asset directories (Blueprints + Gamedata)
219 std::shared_ptr<AssetNode> GetAssetTree() const { return m_AssetTreeRoot; }
220
221 // Pre-load all ATS graphs found under Blueprints/ and Gamedata/ into
222 // TaskGraphLoader. Called automatically by InitializeStandaloneEditor().
223 void PreloadATSGraphs();
224
225 // Asset queries
226 std::vector<AssetMetadata> GetAllAssets() const;
227 std::vector<AssetMetadata> GetAssetsByType(const std::string& type) const;
228 std::vector<AssetMetadata> SearchAssets(const std::string& query) const;
229
230 // Asset metadata
231 AssetMetadata GetAssetMetadata(const std::string& filepath);
232 bool IsAssetValid(const std::string& filepath) const;
233
234 // Asset metadata cache invalidation
235 void InvalidateAssetMetadataCache(); // Clear all cached metadata
236
237 // Asset type detection
238 std::string DetectAssetType(const std::string& filepath);
239
240 // Error handling
241 std::string GetLastError() const { return m_LastError; }
242 bool HasError() const { return !m_LastError.empty(); }
243 void ClearError() { m_LastError.clear(); }
244
245 // ===== B) Runtime Entity Management =====
246 // World bridge: notification hooks for entity lifecycle
247 void NotifyEntityCreated(uint64_t entityId);
248 void NotifyEntityDestroyed(uint64_t entityId);
249
250 // Runtime entity queries
251 const std::vector<uint64_t>& GetRuntimeEntities() const { return m_RuntimeEntities; }
252 size_t GetRuntimeEntityCount() const { return m_RuntimeEntities.size(); }
253
254 // ===== C) Entity Selection for Panel Synchronization =====
255 void SetSelectedEntity(uint64_t entityId);
257 bool HasSelectedEntity() const { return m_SelectedEntity != 0; } // 0 = INVALID_ENTITY_ID
258
259 // ===== Asset Selection for Panel Synchronization =====
260 void SelectAsset(const std::string& assetPath);
261 std::string GetSelectedAssetPath() const { return m_SelectedAssetPath; }
262 bool HasSelectedAsset() const { return !m_SelectedAssetPath.empty(); }
263
264 // ===== Graph Loading in Node Graph Editor =====
265 // Opens a BehaviorTree or HFSM asset in the Node Graph Editor
266 void OpenGraphInEditor(const std::string& assetPath);
267
268 // ===== Phase 5: Template Management =====
269 // Save current blueprint as template
270 bool SaveCurrentAsTemplate(const std::string& name, const std::string& description, const std::string& category);
271
272 // Apply template to current blueprint
273 bool ApplyTemplate(const std::string& templateId);
274
275 // Delete a template
276 bool DeleteTemplate(const std::string& templateId);
277
278 // Reload templates from disk
279 void ReloadTemplates();
280
281 // ===== Phase 6: Undo/Redo System =====
282 void Undo();
283 void Redo();
284 bool CanUndo() const;
285 bool CanRedo() const;
286 std::string GetLastCommandDescription() const;
287 std::string GetNextRedoDescription() const;
288
289 // Command stack access for history panel
291
292 // ===== Plugin System =====
293 void InitializePlugins();
294 void RegisterPlugin(std::unique_ptr<class BlueprintEditorPlugin> plugin);
295 class BlueprintEditorPlugin* GetPlugin(const std::string& type);
297
298 // ===== Migration System =====
300 std::vector<std::string> ScanBlueprintFiles(const std::string& directory);
303
304 // ===== Configuration System =====
305 bool LoadConfig(const std::string& configPath = "blueprint_editor_config.json");
306 bool SaveConfig(const std::string& configPath = "blueprint_editor_config.json");
307 const json& GetConfig() const { return m_Config; }
309
310 private:
311 // Private constructor/destructor for singleton
314
315 // Disable copy and assignment
318
319 // Asset management helpers
320 std::shared_ptr<AssetNode> ScanDirectory(const std::string& path);
321 void ParseAssetMetadata(const std::string& filepath, AssetMetadata& metadata);
322 void ParseEntityBlueprint(const json& j, AssetMetadata& metadata);
323 void ParseBehaviorTree(const json& j, AssetMetadata& metadata);
324 void ParseHFSM(const json& j, AssetMetadata& metadata);
325 void CollectAllAssets(const std::shared_ptr<AssetNode>& node, std::vector<AssetMetadata>& assets) const;
326
327 private:
328 // Editor state
331
332 // Blueprint data
334 std::string m_CurrentFilepath;
335
336 // Asset paths and tree
337 std::string m_AssetRootPath; // Blueprints directory (default: "Blueprints")
338 std::string m_GamedataRootPath; // Gamedata directory (default: "Gamedata")
339 std::shared_ptr<AssetNode> m_AssetTreeRoot;
340
341 // Error handling
342 std::string m_LastError;
343
344 // ===== B) Runtime Entity Tracking =====
345 std::vector<uint64_t> m_RuntimeEntities; // List of all runtime entities from World
346
347 // ===== C) Entity Selection =====
348 uint64_t m_SelectedEntity; // Currently selected entity (0 = none)
349
350 // ===== Asset Selection =====
351 std::string m_SelectedAssetPath; // Currently selected asset file path
352
353 // ===== Asset Metadata Cache (Performance Optimization) =====
354 // Cache to avoid reloading and reparsing JSON for the same asset every frame
355 std::map<std::string, AssetMetadata> m_AssetMetadataCache; // filepath -> metadata
356 std::string m_LastCachedAssetPath; // Track previous selection for cache invalidation
357
358 // ===== Phase 6: Command System =====
359 Blueprint::CommandStack* m_CommandStack; // Undo/redo command stack
360
361 // ===== Plugin System =====
362 std::map<std::string, std::unique_ptr<class BlueprintEditorPlugin>> m_Plugins;
363
364 // ===== Migration System =====
366 std::vector<std::string> m_BlueprintsToMigrate;
367
368 // ===== Configuration System =====
369 json m_Config; // Editor configuration (loaded from JSON)
370 };
371}
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
BlueprintEditorPlugin - Base interface for blueprint type plugins Each plugin handles a specific blue...
BlueprintEditor Singleton Backend Manages all business logic, state, and data for the Blueprint Edito...
std::vector< AssetMetadata > SearchAssets(const std::string &query) const
const std::string & GetCurrentFilepath() const
size_t GetRuntimeEntityCount() const
BlueprintEditor(const BlueprintEditor &)=delete
void RegisterPlugin(std::unique_ptr< class BlueprintEditorPlugin > plugin)
const json & GetConfig() const
std::shared_ptr< AssetNode > GetAssetTree() const
std::string GetSelectedAssetPath() const
void SetActive(bool active)
void ParseEntityBlueprint(const json &j, AssetMetadata &metadata)
std::vector< std::string > ScanBlueprintFiles(const std::string &directory)
static BlueprintEditor & Instance()
const std::vector< uint64_t > & GetRuntimeEntities() const
std::map< std::string, std::unique_ptr< class BlueprintEditorPlugin > > m_Plugins
bool LoadBlueprint(const std::string &filepath)
void SetShowMigrationDialog(bool show)
std::string DetectAssetType(const std::string &filepath)
std::shared_ptr< AssetNode > ScanDirectory(const std::string &path)
std::vector< AssetMetadata > GetAssetsByType(const std::string &type) const
Blueprint::CommandStack * m_CommandStack
std::vector< uint64_t > m_RuntimeEntities
void NewBlueprint(const std::string &name, const std::string &description="")
void NotifyEntityDestroyed(uint64_t entityId)
std::string GetNextRedoDescription() const
void SetAssetRootPath(const std::string &path)
std::string GetLastError() const
std::string GetLastCommandDescription() const
Blueprint::EntityBlueprint & GetCurrentBlueprintMutable()
const Blueprint::EntityBlueprint & GetCurrentBlueprint() const
void NotifyEntityCreated(uint64_t entityId)
void ParseHFSM(const json &j, AssetMetadata &metadata)
bool DeleteTemplate(const std::string &templateId)
AssetMetadata GetAssetMetadata(const std::string &filepath)
std::vector< std::string > m_BlueprintsToMigrate
bool IsAssetValid(const std::string &filepath) const
bool LoadConfig(const std::string &configPath="blueprint_editor_config.json")
void SelectAsset(const std::string &assetPath)
void SetSelectedEntity(uint64_t entityId)
uint64_t GetSelectedEntity() const
bool SaveConfig(const std::string &configPath="blueprint_editor_config.json")
Blueprint::CommandStack * GetCommandStack()
bool SaveBlueprintAs(const std::string &filepath)
class BlueprintEditorPlugin * GetPlugin(const std::string &type)
void OpenGraphInEditor(const std::string &assetPath)
bool ApplyTemplate(const std::string &templateId)
std::shared_ptr< AssetNode > m_AssetTreeRoot
void ParseAssetMetadata(const std::string &filepath, AssetMetadata &metadata)
bool SaveCurrentAsTemplate(const std::string &name, const std::string &description, const std::string &category)
class BlueprintEditorPlugin * DetectPlugin(const json &blueprint)
std::vector< AssetMetadata > GetAllAssets() const
void CollectAllAssets(const std::shared_ptr< AssetNode > &node, std::vector< AssetMetadata > &assets) const
void ParseBehaviorTree(const json &j, AssetMetadata &metadata)
std::string GetAssetRootPath() const
static BlueprintEditor & Get()
BlueprintEditor & operator=(const BlueprintEditor &)=delete
Blueprint::EntityBlueprint m_CurrentBlueprint
void Update(float deltaTime)
std::map< std::string, AssetMetadata > m_AssetMetadataCache
CommandStack - Manages undo/redo command history Maintains two stacks for undo and redo operations.
< Provides AssetID and INVALID_ASSET_ID
nlohmann::json json
@ Blueprint
.ats files (SubGraph/VisualScript)
nlohmann::json json
std::vector< std::string > components
std::vector< std::string > nodes
AssetNode(const std::string &n, const std::string &path, bool isDir)
std::vector< std::shared_ptr< AssetNode > > children