Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
TaskSystem.h
Go to the documentation of this file.
1/**
2 * @file TaskSystem.h
3 * @brief ECS system that iterates TaskRunnerComponent entities and drives
4 * ATS Visual Script graph execution each frame.
5 * @author Olympe Engine
6 * @date 2026-02-22 (refactored Phase 4 - 2026-03-08)
7 *
8 * @details
9 * TaskSystem inherits from ECS_System and is registered in the World alongside
10 * all other runtime systems. Each frame, Process() iterates the set of
11 * entities that own a TaskRunnerComponent, retrieves the bound
12 * TaskGraphTemplate via AssetManager, and delegates to ExecuteVSFrame() to
13 * advance Visual Script graph execution.
14 *
15 * ### Execution paths (Phase 4)
16 * - VS graphs (graphType == "VisualScript"): dispatched via ExecuteVSFrame()
17 * which calls VSGraphExecutor::ExecuteFrame(). This is the PRIMARY path.
18 * - Legacy BT-style graphs: ExecuteNode() is retained for direct invocation
19 * by unit tests; Process() no longer calls it (VS is the only path in the
20 * main loop).
21 *
22 * ### AtomicTask lifecycle (Phase 2.C / Phase 4)
23 * ExecuteNode() implements the following lifecycle for AtomicTask nodes:
24 * 1. On first entry to a node, create the IAtomicTask instance via
25 * AtomicTaskRegistry::Create() and store it in runner.activeTask.
26 * 2. Each tick, call runner.activeTask->ExecuteWithContext(ctx, params).
27 * 3. Running => keep activeTask; accumulate StateTimer; return.
28 * 4. Success/Failure => reset activeTask; set LastStatus; reset StateTimer;
29 * advance CurrentNodeID via TransitionToNextNode().
30 * NODE_INDEX_NONE signals that the graph is complete.
31 * 5. If runner.CurrentNodeID is set to NODE_INDEX_NONE while a task is
32 * Running, the next call to ExecuteNode() calls activeTask->Abort() before
33 * releasing the instance.
34 *
35 * C++14 compliant - no C++17/20 features.
36 */
37
38#pragma once
39
40#include "../ECS_Systems.h"
41#include "../ECS/Components/TaskRunnerComponent.h"
42#include "TaskGraphTemplate.h"
43#include "../Core/AssetManager.h"
44#include "LocalBlackboard.h"
45#include "VSGraphExecutor.h"
46
47namespace Olympe {
48
49/**
50 * @brief Signature of the editor publish callback.
51 *
52 * Called by TaskSystem each frame while an AtomicTask node is Running.
53 * The editor registers a function of this type via
54 * TaskSystem::SetEditorPublishCallback() to receive live runtime info
55 * without creating a compile-time dependency on editor code.
56 *
57 * @param entity ID of the entity currently executing the task.
58 * @param nodeIndex Current node ID being executed.
59 * @param bb Non-owning pointer to the LocalBlackboard for this tick.
60 * Only valid for the duration of the callback invocation.
61 */
63
64/**
65 * @class TaskSystem
66 * @brief ECS system responsible for advancing task graph execution each frame.
67 *
68 * @details
69 * Usage:
70 * @code
71 * TaskSystem* taskSystem = world.RegisterSystem<TaskSystem>();
72 * // TaskSystem sets its own requiredSignature in the constructor.
73 * @endcode
74 *
75 * Inheritance: TaskSystem : ECS_System
76 */
77class TaskSystem : public ECS_System
78{
79public:
80
81 // -----------------------------------------------------------------------
82 // Lifecycle
83 // -----------------------------------------------------------------------
84
85 /**
86 * @brief Constructs the system and configures the required component signature.
87 *
88 * @note Signature configuration is left as a TODO until the component
89 * registration API is fully wired up in Phase 1.5.
90 */
91 TaskSystem();
92
93 // -----------------------------------------------------------------------
94 // Editor runtime wiring
95 // -----------------------------------------------------------------------
96
97 /**
98 * @brief Register a callback that receives live task-runner state each
99 * frame while a task is executing.
100 *
101 * Pass nullptr to unregister. The callback is invoked from
102 * ExecuteAtomicTask() after ticking the task when the task is Running.
103 * It is safe to call this from any thread before the first Process().
104 *
105 * @param fn Function matching TaskEditorPublishFn, or nullptr.
106 */
108
109 // -----------------------------------------------------------------------
110 // ECS_System interface
111 // -----------------------------------------------------------------------
112
113 /**
114 * @brief Processes all entities registered with this system for one frame.
115 *
116 * For each entity in m_entities:
117 * 1. Retrieves the TaskRunnerComponent (TODO Phase 1.5: from World).
118 * 2. Looks up the bound TaskGraphTemplate via AssetManager::Get().
119 * 3. Skips the entity if no valid template is found.
120 * 4. Calls ExecuteNode() to advance task graph execution.
121 */
122 virtual void Process() override;
123
124 // -----------------------------------------------------------------------
125 // Core execution (public to allow direct invocation in unit tests)
126 // -----------------------------------------------------------------------
127
128 /**
129 * @brief Advances execution of one node in the task graph for the given entity.
130 *
131 * @details
132 * Implements the AtomicTask lifecycle described in the class documentation.
133 * runner.CurrentNodeID is treated as a NodeID (looked up via
134 * TaskGraphTemplate::GetNode()). NODE_INDEX_NONE (-1) means there is no
135 * active node; any lingering activeTask is Abort()ed and released.
136 *
137 * @param entity The entity being processed.
138 * @param runner Reference to the entity's TaskRunnerComponent.
139 * @param tmpl Non-null pointer to the resolved TaskGraphTemplate.
140 * @param dt Delta-time in seconds for the current frame.
141 */
142 void ExecuteNode(EntityID entity,
144 const TaskGraphTemplate* tmpl,
145 float dt);
146
147 /**
148 * @brief Dispatches VS-graph execution to VSGraphExecutor.
149 * Called from Process() when tmpl->GraphType == "VisualScript".
150 *
151 * @param entity The entity being processed.
152 * @param runner Reference to the entity's TaskRunnerComponent.
153 * @param tmpl Non-null pointer to the resolved TaskGraphTemplate.
154 * @param dt Delta-time in seconds for the current frame.
155 */
156 void ExecuteVSFrame(EntityID entity,
158 const TaskGraphTemplate* tmpl,
159 float dt);
160
161 /**
162 * @brief Aborts the active atomic task on a runner, if any.
163 *
164 * @details
165 * Calls Abort() on runner.activeTask (if non-null), resets the unique_ptr,
166 * and sets runner.LastStatus to TaskRunnerComponent::TaskStatus::Aborted.
167 * Safe to call when runner.activeTask is nullptr (no-op).
168 *
169 * @param runner Reference to the entity's TaskRunnerComponent.
170 */
172
173private:
174
175 // -----------------------------------------------------------------------
176 // Private helpers
177 // -----------------------------------------------------------------------
178
179 /**
180 * @brief Executes one tick of an AtomicTask node.
181 *
182 * Creates runner.activeTask on first call for this node, ticks it, and
183 * handles Running / completion transitions.
184 *
185 * @param entity The entity being processed.
186 * @param runner Reference to the entity's TaskRunnerComponent.
187 * @param node The current AtomicTask node definition.
188 * @param tmpl Non-null pointer to the resolved TaskGraphTemplate (used
189 * to resolve LocalVariable bindings).
190 * @param dt Delta-time in seconds for the current frame.
191 */
192 void ExecuteAtomicTask(EntityID entity,
195 const TaskGraphTemplate* tmpl,
196 float dt);
197
198 /**
199 * @brief Advances runner.CurrentNodeID after a node completes.
200 *
201 * Sets runner.CurrentNodeID to node.NextOnSuccess if @p success is
202 * true, or node.NextOnFailure otherwise. NODE_INDEX_NONE signals that
203 * the graph has finished. Also resets runner.StateTimer to 0.
204 *
205 * @param runner The runner component to update.
206 * @param node The node that just completed.
207 * @param success true if the node succeeded, false if it failed.
208 */
211 bool success);
212
213 /// Callback registered by the editor to receive live runtime info.
215};
216
217} // namespace Olympe
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.
Exécuteur de graphes ATS Visual Scripting (flowchart).
Simple map-based blackboard for task graph runtime state.
Immutable, shareable task graph asset.
ECS system responsible for advancing task graph execution each frame.
Definition TaskSystem.h:78
virtual void Process() override
Processes all entities registered with this system for one frame.
void ExecuteAtomicTask(EntityID entity, TaskRunnerComponent &runner, const TaskNodeDefinition &node, const TaskGraphTemplate *tmpl, float dt)
Executes one tick of an AtomicTask node.
void ExecuteVSFrame(EntityID entity, TaskRunnerComponent &runner, const TaskGraphTemplate *tmpl, float dt)
Dispatches VS-graph execution to VSGraphExecutor.
static void SetEditorPublishCallback(TaskEditorPublishFn fn)
Register a callback that receives live task-runner state each frame while a task is executing.
TaskSystem()
Constructs the system and configures the required component signature.
void AbortActiveTask(TaskRunnerComponent &runner)
Aborts the active atomic task on a runner, if any.
void ExecuteNode(EntityID entity, TaskRunnerComponent &runner, const TaskGraphTemplate *tmpl, float dt)
Advances execution of one node in the task graph for the given entity.
static TaskEditorPublishFn s_EditorPublishFn
Callback registered by the editor to receive live runtime info.
Definition TaskSystem.h:214
void TransitionToNextNode(TaskRunnerComponent &runner, const TaskNodeDefinition &node, bool success)
Advances runner.CurrentNodeID after a node completes.
< Provides AssetID and INVALID_ASSET_ID
void(*)(EntityID entity, int nodeIndex, const LocalBlackboard *bb) TaskEditorPublishFn
Signature of the editor publish callback.
Definition TaskSystem.h:62
Full description of a single node in the task graph.
Per-entity runtime state for task graph execution.