Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
ExecutionTestPanel.cpp
Go to the documentation of this file.
1/**
2 * @file ExecutionTestPanel.cpp
3 * @brief Implementation of execution test panel.
4 * @author Olympe Engine
5 * @date 2026-03-24
6 */
7
9#include "../third_party/imgui/imgui.h"
10#include "../system/system_utils.h"
11#include <sstream>
12#include <iomanip>
13
14namespace Olympe {
15
17 : m_visible(true), m_lastTestRun(false), m_selectedEventIndex(-1),
18 m_showTraceLog(true), m_showErrors(true), m_autoScroll(true)
19{
20}
21
25
36
38{
39 SYSTEM_LOG << "[ExecutionTestPanel] Shutdown\n";
40}
41
43{
44 if (!m_visible)
45 return;
46
47 ImGui::SetNextWindowSize(ImVec2(900, 600), ImGuiCond_FirstUseEver);
48
49 if (!ImGui::Begin("Execution Test", &m_visible, ImGuiWindowFlags_None))
50 {
51 ImGui::End();
52 return;
53 }
54
55 // Test controls
57
58 ImGui::Separator();
59
60 // Tabs for different views
61 if (ImGui::BeginTabBar("ExecutionTestTabs", ImGuiTabBarFlags_None))
62 {
63 if (ImGui::BeginTabItem("Trace Log"))
64 {
66 ImGui::EndTabItem();
67 }
68
69 if (ImGui::BeginTabItem("Errors"))
70 {
72 ImGui::EndTabItem();
73 }
74
75 if (ImGui::BeginTabItem("Summary"))
76 {
78 ImGui::EndTabItem();
79 }
80
81 ImGui::EndTabBar();
82 }
83
84 ImGui::End();
85}
86
88{
90 m_lastTestErrors.clear();
91
92 // Run simulation
94
95 m_lastTestRun = true;
96
97 // Log results
98 SYSTEM_LOG << "[ExecutionTest] Test completed: " << m_lastTestErrors.size() << " issues found\n";
100
101 return m_lastTestErrors;
102}
103
105{
106 // Copy the provided tracer for display
108 m_lastTestRun = true;
109 m_lastTestErrors.clear(); // No validation errors for native execution
110
111 SYSTEM_LOG << "[ExecutionTestPanel] Displaying trace with " << m_lastTracer.GetEvents().size() << " events\n";
112}
113
115{
116 return m_lastTracer.GetTraceLog();
117}
118
120{
122}
123
125{
126 ImGui::Text("Execution Test Controls");
127
128 if (ImGui::Button("Test Execution", ImVec2(120, 0)))
129 {
130 // TODO: Get the active template and run test
131 SYSTEM_LOG << "[ExecutionTestPanel] Test execution button clicked\n";
132 }
133
134 ImGui::SameLine();
135 ImGui::Text(m_lastTestRun ? "✓ Last test run" : "● No test run yet");
136
137 ImGui::Separator();
138 ImGui::Text("Test Options");
139
140 ImGui::Checkbox("Validate Conditions##opt1", &m_testOptions.validateConditions);
141 ImGui::Checkbox("Validate Data Flow##opt2", &m_testOptions.validateDataFlow);
142 ImGui::Checkbox("Validate Branch Paths##opt3", &m_testOptions.validateBranchPaths);
143
144 ImGui::SliderInt("Max Steps", &m_testOptions.maxStepsPerFrame, 100, 10000);
145 ImGui::SliderInt("Max Depth", &m_testOptions.maxSubGraphDepth, 1, 20);
146
147 ImGui::Checkbox("Auto-scroll", &m_autoScroll);
148}
149
151{
152 ImGui::Text("Execution Trace (%zu events)", m_lastTracer.GetEvents().size());
153
154 ImGui::Separator();
155
156 // Trace log table
157 if (ImGui::BeginTable("TraceTable", 6, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders))
158 {
159 ImGui::TableSetupColumn("Step", ImGuiTableColumnFlags_WidthFixed, 40.0f);
160 ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 80.0f);
161 ImGui::TableSetupColumn("Node ID", ImGuiTableColumnFlags_WidthFixed, 60.0f);
162 ImGui::TableSetupColumn("Node Name", ImGuiTableColumnFlags_WidthFixed, 120.0f);
163 ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
164 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed, 80.0f);
165
166 ImGui::TableHeadersRow();
167
168 const auto& events = m_lastTracer.GetEvents();
169 size_t eventCount = events.size();
170
172 clipper.Begin((int)eventCount);
173
174 while (clipper.Step())
175 {
176 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; ++i)
177 {
178 RenderExecutionEventRow(events[i], i);
179 }
180 }
181 clipper.End();
182
183 ImGui::EndTable();
184 }
185}
186
188{
189 ImGui::TableNextRow();
190
191 // Step number
192 ImGui::TableSetColumnIndex(0);
193 ImGui::Text("%d", event.stepNumber);
194
195 // Event type
196 ImGui::TableSetColumnIndex(1);
197 const char* typeStr = "Unknown";
198 ImVec4 typeColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
199
200 switch (event.type)
201 {
203 typeStr = "Enter";
204 typeColor = ImVec4(0.4f, 0.7f, 1.0f, 1.0f);
205 break;
207 typeStr = "Exit";
208 typeColor = ImVec4(0.4f, 0.9f, 0.4f, 1.0f);
209 break;
211 typeStr = "Cond";
212 typeColor = ImVec4(1.0f, 0.8f, 0.3f, 1.0f);
213 break;
215 typeStr = "Branch";
216 typeColor = ImVec4(0.9f, 0.6f, 0.2f, 1.0f);
217 break;
219 typeStr = "ERROR";
220 typeColor = ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
221 break;
223 typeStr = "Blocked";
224 typeColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f);
225 break;
227 typeStr = "Data";
228 typeColor = ImVec4(0.7f, 0.7f, 0.9f, 1.0f);
229 break;
231 typeStr = "Done";
232 typeColor = ImVec4(0.4f, 0.9f, 0.4f, 1.0f);
233 break;
234 default:
235 break;
236 }
237
238 ImGui::TextColored(typeColor, "%s", typeStr);
239
240 // Node ID
241 ImGui::TableSetColumnIndex(2);
242 if (event.nodeId >= 0)
243 ImGui::Text("%d", event.nodeId);
244 else
245 ImGui::Text("-");
246
247 // Node name
248 ImGui::TableSetColumnIndex(3);
249 ImGui::Text("%s", event.nodeName.c_str());
250
251 // Message
252 ImGui::TableSetColumnIndex(4);
253 ImGui::Text("%s", event.message.c_str());
254
255 // Condition result (if applicable)
256 ImGui::TableSetColumnIndex(5);
258 {
259 if (event.conditionResult)
260 {
261 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "TRUE");
262 }
263 else
264 {
265 ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "FALSE");
266 }
267 }
268}
269
271{
272 ImGui::Text("Validation Errors (%zu found)", m_lastTestErrors.size());
273
274 ImGui::Separator();
275
276 if (m_lastTestErrors.empty())
277 {
278 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "✓ No errors found!");
279 }
280 else
281 {
282 if (ImGui::BeginTable("ErrorTable", 5, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders))
283 {
284 ImGui::TableSetupColumn("Severity", ImGuiTableColumnFlags_WidthFixed, 80.0f);
285 ImGui::TableSetupColumn("Node ID", ImGuiTableColumnFlags_WidthFixed, 70.0f);
286 ImGui::TableSetupColumn("Node Name", ImGuiTableColumnFlags_WidthFixed, 150.0f);
287 ImGui::TableSetupColumn("Category", ImGuiTableColumnFlags_WidthFixed, 100.0f);
288 ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
289
290 ImGui::TableHeadersRow();
291
292 for (size_t i = 0; i < m_lastTestErrors.size(); ++i)
293 {
295
296 ImGui::TableNextRow();
297
298 // Severity
299 ImGui::TableSetColumnIndex(0);
300 const char* sevStr = BlueprintValidator::SeverityToString(error.severity);
302 ImGui::TextColored(sevColor, "%s", sevStr);
303
304 // Node ID
305 ImGui::TableSetColumnIndex(1);
306 if (error.nodeId >= 0)
307 ImGui::Text("%d", error.nodeId);
308 else
309 ImGui::Text("Graph");
310
311 // Node name
312 ImGui::TableSetColumnIndex(2);
313 ImGui::Text("%s", error.nodeName.c_str());
314
315 // Category
316 ImGui::TableSetColumnIndex(3);
317 ImGui::Text("%s", error.category.c_str());
318
319 // Message
320 ImGui::TableSetColumnIndex(4);
321 ImGui::Text("%s", error.message.c_str());
322 }
323
324 ImGui::EndTable();
325 }
326 }
327}
328
330{
331 ImGui::TextWrapped(m_lastTracer.GetExecutionSummary().c_str());
332
333 ImGui::Separator();
334
335 if (ImGui::CollapsingHeader("Full Trace Log", ImGuiTreeNodeFlags_DefaultOpen))
336 {
337 ImGui::TextWrapped(m_lastTracer.GetTraceLog().c_str());
338 }
339}
340
341} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Panel for executing and testing blueprint graphs with simulation.
static ImVec4 SeverityToColor(ErrorSeverity severity)
static const char * SeverityToString(ErrorSeverity severity)
void DisplayTrace(const GraphExecutionTracer &tracer)
Display a pre-computed trace (for BehaviorTree or native executors).
GraphExecutionSimulator m_simulator
void RenderExecutionEventRow(const ExecutionEvent &event, size_t rowIndex)
std::string GetExecutionLog() const
Returns the execution log as a formatted string.
std::string GetTestSummary() const
Returns a summary of the last test run.
GraphExecutionTracer m_lastTracer
void Render()
Renders the test execution panel window.
std::vector< ValidationError > RunExecutionTest(const TaskGraphTemplate &tmpl)
Runs execution test on the specified template.
std::vector< ValidationError > m_lastTestErrors
std::vector< ValidationError > SimulateExecution(const TaskGraphTemplate &tmpl, const SimulationOptions &options, GraphExecutionTracer &outTracer)
Simulates execution of a graph template.
Records execution trace during graph simulation.
const std::vector< ExecutionEvent > & GetEvents() const
Returns all recorded events.
std::string GetTraceLog() const
Returns a formatted trace log as a multi-line string.
void Reset()
Clears all recorded events and resets state.
std::string GetExecutionSummary() const
Returns a summary of the execution (steps, errors, etc.).
Immutable, shareable task graph asset.
< Provides AssetID and INVALID_ASSET_ID
@ ExecutionBlocked
Execution was blocked (dead-end path, etc.)
@ BranchTaken
A branch condition was true.
@ NodeEntered
Execution entered a node.
@ DataPinResolved
A data pin was resolved.
@ ConditionEvaluated
A condition was evaluated.
@ ErrorOccurred
An error happened during execution.
@ ExecutionCompleted
Graph execution completed.
@ NodeExited
Execution exited a node.
A single event recorded during graph execution trace.
bool validateConditions
Check condition syntax.
int32_t maxStepsPerFrame
Maximum steps to prevent infinite loops.
bool validateDataFlow
Check data connections.
bool validateBranchPaths
Verify all branches lead somewhere.
int32_t maxSubGraphDepth
Maximum nesting depth for subgraphs.
#define SYSTEM_LOG