Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
VSGraphExecutor.h
Go to the documentation of this file.
1/**
2 * @file VSGraphExecutor.h
3 * @brief Exécuteur de graphes ATS Visual Scripting (flowchart).
4 * @author Olympe Engine
5 * @date 2026-03-08
6 *
7 * @details
8 * VSGraphExecutor implémente la logique d'exécution "par frame" d'un graphe
9 * de type VisualScript (schema v4). Il est appelé par TaskSystem::Process()
10 * pour chaque entité dont le TaskGraphTemplate a GraphType == "VisualScript".
11 *
12 * Modèle d'exécution :
13 * - Chaque frame, l'exécution repart depuis le node actif (CurrentNodeID).
14 * - Pour EntryPoint : avance immédiatement vers le premier successeur exec.
15 * - Pour Branch : évalue la condition via Phase 24 presets, Phase 23 conditions, ou data pins.
16 * - Pour VSSequence : exécute les ChildrenIDs dans l'ordre (SequenceChildIndex).
17 * - Pour AtomicTask : délègue à IAtomicTask::ExecuteWithContext(), gère Running.
18 * - Pour Delay : accumule StateTimer, émet Completed quand >= DelaySeconds.
19 * - Pour DoOnce : vérifie DoOnceFlags[nodeID], bloque si déjà exécuté.
20 * - Pour GetBBValue / SetBBValue : lit/écrit dans LocalBlackboard via BBKey (scope:key).
21 * - Pour SubGraph : charge et délègue à un VSGraphExecutor récursif (depth-limited).
22 * - Pour While : évalue condition, suit Loop ou Completed.
23 * - Pour Switch : évalue valeur BB, route vers le case correspondant.
24 * - Pour MathOp : calcule résultat via DataPinCache, stocke dans output pin.
25 *
26 * Résolution des Data Pins (Phase 24.1 - Stack-based recursive evaluation):
27 * Avant d'exécuter un node, VSGraphExecutor résout toutes ses DataConnections
28 * entrantes en utilisant DataPinEvaluator::EvaluateNodeInputPins().
29 *
30 * Ce système utilise une évaluation récursive en profondeur d'abord pour
31 * évaluer les réseaux de data pins "data pure" (Variable, MathOp, GetBBValue).
32 * Les dépendances sont résolues automatiquement avec détection de cycles et
33 * limite de profondeur pour éviter les débordements de pile.
34 *
35 * Exemple:
36 * SetBBValue.In("Value") ← MathOp.Out("Result") ← Variable.Out("mHealth") + Variable.Out("mFoodPortion")
37 * L'exécution se fera: évaluer MathOp -> évaluer ses deux Variables -> calculer résultat -> SetBBValue
38 *
39 * Phase 24 - Condition Preset Integration (2026-03-17):
40 * - HandleBranch evaluates node->conditionRefs with ConditionPresetEvaluator
41 * - Supports AND/OR operators with short-circuit evaluation
42 * - Falls back to Phase 23-B.4 conditions if no presets are defined
43 * - Falls back to data pin evaluation as final fallback
44 * - Fully backward compatible with existing task graphs
45 *
46 * C++14 compliant.
47 */
48
49#pragma once
50
51#include <cstdint>
52#include <string>
53
54#include "TaskGraphTemplate.h"
55#include "TaskGraphTypes.h"
56#include "../ECS/Components/TaskRunnerComponent.h"
57#include "AtomicTaskContext.h"
58#include "LocalBlackboard.h"
59
60// Phase 23-B.4: Condition evaluation
61#include "ConditionEvaluator.h"
62
63// Phase 24: Condition preset evaluation (runtime integration)
64#include "../Runtime/ConditionPresetEvaluator.h"
65#include "../Runtime/RuntimeEnvironment.h"
66#include "../Editor/ConditionPreset/ConditionPresetRegistry.h"
67
68namespace Olympe {
69
70// Forward declarations
71class World;
72
73/**
74 * @struct SubGraphCallStack
75 * @brief Tracks the SubGraph call chain to detect cycles and enforce depth limits.
76 *
77 * @details
78 * Each SubGraph invocation pushes its file path onto PathStack before executing
79 * and pops it after. This allows O(n) cycle detection (n = depth) and
80 * guarantees that HandleSubGraph never recurses deeper than MAX_SUBGRAPH_DEPTH.
81 */
83 std::vector<std::string> PathStack; ///< Stack of SubGraph file paths currently executing
84 int32_t Depth = 0; ///< Current recursion depth
85
86 bool Contains(const std::string& path) const {
87 for (size_t i = 0; i < PathStack.size(); ++i)
88 {
89 if (PathStack[i] == path) return true;
90 }
91 return false;
92 }
93
94 void Push(const std::string& path) {
95 PathStack.push_back(path);
96 ++Depth;
97 }
98
99 void Pop() {
100 if (!PathStack.empty()) {
101 PathStack.pop_back();
102 --Depth;
103 }
104 }
105};
106
107/**
108 * @class VSGraphExecutor
109 * @brief Exécute un graphe ATS Visual Scripting pour une entité sur un frame.
110 */
112public:
113
114 /**
115 * @brief Point d'entrée principal : exécute le graphe pour une entité.
116 *
117 * @param entity ID de l'entité propriétaire du runner.
118 * @param runner Composant runtime mutable de l'entité (CurrentNodeID, BB, etc.).
119 * @param tmpl Template immutable du graphe.
120 * @param localBB Blackboard local de l'entité (initialisé depuis tmpl->Blackboard).
121 * @param worldPtr Pointeur vers World (peut être nullptr en tests).
122 * @param dt Delta-time du frame courant.
123 */
124 static void ExecuteFrame(EntityID entity,
126 const TaskGraphTemplate& tmpl,
129 float dt);
130
131private:
132
133 // -----------------------------------------------------------------------
134 // Node handlers (un par TaskNodeType VS)
135 // -----------------------------------------------------------------------
136
137 /// Résout les data pins entrantes d'un node et peuple runner.DataPinCache.
138 static void ResolveDataPins(int32_t nodeID,
140 const TaskGraphTemplate& tmpl,
142
143 /// Retourne l'ID du node cible sur un exec pin nommé `pinName` depuis `sourceNodeID`.
144 /// Retourne NODE_INDEX_NONE si aucune connexion trouvée.
146 const std::string& pinName,
147 const TaskGraphTemplate& tmpl);
148
149 /// Lit une valeur BB depuis localBB avec support du scope "local:" et "global:".
150 static TaskValue ReadBBValue(const std::string& scopedKey,
152
153 /// Écrit une valeur BB dans localBB avec support du scope "local:".
154 static void WriteBBValue(const std::string& scopedKey,
155 const TaskValue& value,
157
158 // Node-type handlers — retournent l'ID du prochain node à exécuter
159 // (NODE_INDEX_NONE = fin de frame, garde currentNodeID inchangé pour frame suivant)
160
162
163 static int32_t HandleBranch(int32_t nodeID,
165 const TaskGraphTemplate& tmpl,
167
168 static int32_t HandleSwitch(int32_t nodeID,
170 const TaskGraphTemplate& tmpl,
172
173 static int32_t HandleVSSequence(int32_t nodeID,
175 const TaskGraphTemplate& tmpl);
176
177 static int32_t HandleWhile(int32_t nodeID,
179 const TaskGraphTemplate& tmpl,
181
182 static int32_t HandleDoOnce(int32_t nodeID,
184 const TaskGraphTemplate& tmpl);
185
186 static int32_t HandleDelay(int32_t nodeID,
188 const TaskGraphTemplate& tmpl,
189 float dt);
190
191 static int32_t HandleGetBBValue(int32_t nodeID,
193 const TaskGraphTemplate& tmpl,
195
196 static int32_t HandleSetBBValue(int32_t nodeID,
198 const TaskGraphTemplate& tmpl,
200
201 static int32_t HandleMathOp(int32_t nodeID,
203 const TaskGraphTemplate& tmpl);
204
205 static int32_t HandleAtomicTask(EntityID entity,
206 int32_t nodeID,
208 const TaskGraphTemplate& tmpl,
211 float dt);
212
213 // SubGraph: depth-limited recursive execution with cycle detection.
214 // callStack tracks the currently active SubGraph paths to detect cycles.
215 static int32_t HandleSubGraph(EntityID entity,
216 int32_t nodeID,
218 const TaskGraphTemplate& tmpl,
221 float dt,
223
224 // Limite de récursion pour SubGraph
225 static const int MAX_SUBGRAPH_DEPTH = 4;
226};
227
228} // namespace Olympe
Runtime context passed to IAtomicTask::ExecuteWithContext().
Evaluates structured Condition expressions for Branch/While nodes.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::uint64_t EntityID
Definition ECS_Entity.h:21
Runtime key-value store for task graph variables.
Immutable asset structure shared by all task graph runners.
Core enumerations and TaskValue type-safe variant for the Atomic Task System.
Simple map-based blackboard for task graph runtime state.
Immutable, shareable task graph asset.
C++14-compliant type-safe value container for task parameters.
Exécute un graphe ATS Visual Scripting pour une entité sur un frame.
static int32_t HandleWhile(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
static int32_t FindExecTarget(int32_t sourceNodeID, const std::string &pinName, const TaskGraphTemplate &tmpl)
Retourne l'ID du node cible sur un exec pin nommé pinName depuis sourceNodeID.
static int32_t HandleSubGraph(EntityID entity, int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB, World *worldPtr, float dt, SubGraphCallStack &callStack)
static TaskValue ReadBBValue(const std::string &scopedKey, LocalBlackboard &localBB)
Lit une valeur BB depuis localBB avec support du scope "local:" et "global:".
static int32_t HandleGetBBValue(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
static void ResolveDataPins(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
Résout les data pins entrantes d'un node et peuple runner.DataPinCache.
static const int MAX_SUBGRAPH_DEPTH
Out-of-class definition required in C++14 for ODR-used static const members.
static void WriteBBValue(const std::string &scopedKey, const TaskValue &value, LocalBlackboard &localBB)
Écrit une valeur BB dans localBB avec support du scope "local:".
static int32_t HandleMathOp(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl)
static int32_t HandleSwitch(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
static int32_t HandleVSSequence(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl)
static int32_t HandleEntryPoint(int32_t nodeID, const TaskGraphTemplate &tmpl)
static int32_t HandleSetBBValue(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
static int32_t HandleBranch(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB)
static int32_t HandleDoOnce(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl)
static void ExecuteFrame(EntityID entity, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB, World *worldPtr, float dt)
Point d'entrée principal : exécute le graphe pour une entité.
static int32_t HandleAtomicTask(EntityID entity, int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, LocalBlackboard &localBB, World *worldPtr, float dt)
static int32_t HandleDelay(int32_t nodeID, TaskRunnerComponent &runner, const TaskGraphTemplate &tmpl, float dt)
Core ECS manager and world coordinator.
Definition World.h:210
< Provides AssetID and INVALID_ASSET_ID
Tracks the SubGraph call chain to detect cycles and enforce depth limits.
bool Contains(const std::string &path) const
void Push(const std::string &path)
int32_t Depth
Current recursion depth.
std::vector< std::string > PathStack
Stack of SubGraph file paths currently executing.
Per-entity runtime state for task graph execution.