Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
BTEditorCommand.cpp
Go to the documentation of this file.
1/**
2 * @file BTEditorCommand.cpp
3 * @brief Implementation of command pattern for behavior tree editor
4 */
5
6#include "BTEditorCommand.h"
7#include <iostream>
8#include <algorithm>
9
10namespace Olympe
11{
12 // =============================================================================
13 // BTCommandStack Implementation
14 // =============================================================================
15
16 void BTCommandStack::Execute(std::unique_ptr<BTEditorCommand> cmd)
17 {
18 if (!cmd)
19 return;
20
21 cmd->Execute();
22
23 m_undoStack.push_back(std::move(cmd));
24
25 // Clear redo stack after new action
26 m_redoStack.clear();
27
28 // Limit stack size
29 if (m_undoStack.size() > kMaxStackSize)
30 {
31 m_undoStack.erase(m_undoStack.begin());
32 }
33 }
34
36 {
37 if (!CanUndo())
38 return;
39
40 auto cmd = std::move(m_undoStack.back());
41 m_undoStack.pop_back();
42
43 cmd->Undo();
44
45 m_redoStack.push_back(std::move(cmd));
46 }
47
49 {
50 if (!CanRedo())
51 return;
52
53 auto cmd = std::move(m_redoStack.back());
54 m_redoStack.pop_back();
55
56 cmd->Execute();
57
58 m_undoStack.push_back(std::move(cmd));
59 }
60
62 {
63 return !m_undoStack.empty();
64 }
65
67 {
68 return !m_redoStack.empty();
69 }
70
72 {
73 if (!CanUndo())
74 return "";
75
76 return m_undoStack.back()->GetDescription();
77 }
78
80 {
81 if (!CanRedo())
82 return "";
83
84 return m_redoStack.back()->GetDescription();
85 }
86
88 {
89 m_undoStack.clear();
90 m_redoStack.clear();
91 }
92
93 // =============================================================================
94 // AddNodeCommand Implementation
95 // =============================================================================
96
98 const std::string& name, const Vector& position)
99 : m_tree(tree)
100 , m_nodeType(type)
101 , m_nodeName(name)
102 , m_position(position)
103 , m_createdNodeId(0)
104 {
105 }
106
108 {
109 if (!m_tree)
110 return;
111
113 std::cout << "[AddNodeCommand] Created node ID=" << m_createdNodeId << std::endl;
114 }
115
117 {
118 if (!m_tree || m_createdNodeId == 0)
119 return;
120
122 std::cout << "[AddNodeCommand] Removed node ID=" << m_createdNodeId << std::endl;
123 }
124
126 {
127 return "Add Node: " + m_nodeName;
128 }
129
130 // =============================================================================
131 // DeleteNodeCommand Implementation
132 // =============================================================================
133
135 : m_tree(tree)
136 , m_nodeId(nodeId)
137 {
138 // Save the node data before deletion
139 if (tree)
140 {
141 const BTNode* node = tree->GetNode(nodeId);
142 if (node)
143 {
144 m_savedNode = *node;
145
146 // Save all connections to/from this node
147 for (const auto& otherNode : tree->nodes)
148 {
149 // Check if otherNode is parent of this node
150 for (size_t i = 0; i < otherNode.childIds.size(); ++i)
151 {
152 if (otherNode.childIds[i] == nodeId)
153 {
156 conn.childId = nodeId;
157 conn.isDecorator = false;
158 conn.childIndex = static_cast<int>(i);
159 m_savedConnections.push_back(conn);
160 }
161 }
162
163 if (otherNode.decoratorChildId == nodeId)
164 {
167 conn.childId = nodeId;
168 conn.isDecorator = true;
169 conn.childIndex = 0;
170 m_savedConnections.push_back(conn);
171 }
172 }
173 }
174 }
175 }
176
178 {
179 if (!m_tree)
180 return;
181
183 std::cout << "[DeleteNodeCommand] Deleted node ID=" << m_nodeId << std::endl;
184 }
185
187 {
188 if (!m_tree)
189 return;
190
191 // Restore the node
192 m_tree->nodes.push_back(m_savedNode);
193
194 // Restore connections
195 for (const auto& conn : m_savedConnections)
196 {
197 BTNode* parent = m_tree->GetNode(conn.parentId);
198 if (parent)
199 {
200 if (conn.isDecorator)
201 {
202 parent->decoratorChildId = conn.childId;
203 }
204 else
205 {
206 // Insert at the saved index if possible
207 if (conn.childIndex >= 0 && static_cast<size_t>(conn.childIndex) <= parent->childIds.size())
208 {
209 parent->childIds.insert(parent->childIds.begin() + conn.childIndex, conn.childId);
210 }
211 else
212 {
213 parent->childIds.push_back(conn.childId);
214 }
215 }
216 }
217 }
218
219 std::cout << "[DeleteNodeCommand] Restored node ID=" << m_nodeId << std::endl;
220 }
221
223 {
224 return "Delete Node ID=" + std::to_string(m_nodeId);
225 }
226
227 // =============================================================================
228 // MoveNodeCommand Implementation
229 // =============================================================================
230
232 const Vector& oldPos, const Vector& newPos)
233 : m_tree(tree)
234 , m_nodeId(nodeId)
235 , m_oldPosition(oldPos)
236 , m_newPosition(newPos)
237 {
238 }
239
241 {
242 // Note: In the current implementation, node positions are not stored in BTNode
243 // This would need to be added to BTNode if we want to save positions
244 std::cout << "[MoveNodeCommand] Moved node ID=" << m_nodeId << std::endl;
245 }
246
248 {
249 std::cout << "[MoveNodeCommand] Restored position for node ID=" << m_nodeId << std::endl;
250 }
251
253 {
254 return "Move Node ID=" + std::to_string(m_nodeId);
255 }
256
257 // =============================================================================
258 // ConnectNodesCommand Implementation
259 // =============================================================================
260
262 : m_tree(tree)
263 , m_parentId(parentId)
264 , m_childId(childId)
265 {
266 }
267
269 {
270 if (!m_tree)
271 return;
272
274 std::cout << "[ConnectNodesCommand] Connected " << m_parentId << " -> " << m_childId << std::endl;
275 }
276
278 {
279 if (!m_tree)
280 return;
281
283 std::cout << "[ConnectNodesCommand] Disconnected " << m_parentId << " -X-> " << m_childId << std::endl;
284 }
285
287 {
288 return "Connect " + std::to_string(m_parentId) + " -> " + std::to_string(m_childId);
289 }
290
291 // =============================================================================
292 // DisconnectNodesCommand Implementation
293 // =============================================================================
294
296 : m_tree(tree)
297 , m_parentId(parentId)
298 , m_childId(childId)
299 {
300 }
301
303 {
304 if (!m_tree)
305 return;
306
308 std::cout << "[DisconnectNodesCommand] Disconnected " << m_parentId << " -X-> " << m_childId << std::endl;
309 }
310
312 {
313 if (!m_tree)
314 return;
315
317 std::cout << "[DisconnectNodesCommand] Reconnected " << m_parentId << " -> " << m_childId << std::endl;
318 }
319
321 {
322 return "Disconnect " + std::to_string(m_parentId) + " -X-> " + std::to_string(m_childId);
323 }
324
325 // =============================================================================
326 // EditParameterCommand Implementation
327 // =============================================================================
328
330 const std::string& paramName, const std::string& oldValue,
331 const std::string& newValue, ParamType type)
332 : m_tree(tree)
333 , m_nodeId(nodeId)
334 , m_paramName(paramName)
335 , m_oldValue(oldValue)
336 , m_newValue(newValue)
337 , m_paramType(type)
338 {
339 }
340
342 {
343 if (!m_tree)
344 return;
345
347 if (!node)
348 return;
349
350 // Apply new value based on parameter type
352 {
354 }
355 else if (m_paramType == ParamType::Int)
356 {
357 node->intParams[m_paramName] = std::stoi(m_newValue);
358 }
359 else if (m_paramType == ParamType::Float)
360 {
361 node->floatParams[m_paramName] = std::stof(m_newValue);
362 }
363
364 std::cout << "[EditParameterCommand] Set " << m_paramName << " = " << m_newValue << std::endl;
365 }
366
368 {
369 if (!m_tree)
370 return;
371
373 if (!node)
374 return;
375
376 // Restore old value
378 {
380 }
381 else if (m_paramType == ParamType::Int)
382 {
383 node->intParams[m_paramName] = std::stoi(m_oldValue);
384 }
385 else if (m_paramType == ParamType::Float)
386 {
387 node->floatParams[m_paramName] = std::stof(m_oldValue);
388 }
389
390 std::cout << "[EditParameterCommand] Restored " << m_paramName << " = " << m_oldValue << std::endl;
391 }
392
394 {
395 return "Edit " + m_paramName;
396 }
397
398} // namespace Olympe
Command pattern implementation for behavior tree editor undo/redo.
BTNodeType
Behavior tree node types.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::string GetDescription() const override
Get a human-readable description of the command.
void Undo() override
Undo the command.
BehaviorTreeAsset * m_tree
AddNodeCommand(BehaviorTreeAsset *tree, BTNodeType type, const std::string &name, const Vector &position)
void Execute() override
Execute the command.
std::vector< std::unique_ptr< BTEditorCommand > > m_redoStack
std::string GetUndoDescription() const
Get description of the next undo command.
bool CanRedo() const
Check if redo is available.
void Execute(std::unique_ptr< BTEditorCommand > cmd)
Execute a command and add it to the undo stack.
void Undo()
Undo the last command.
bool CanUndo() const
Check if undo is available.
std::vector< std::unique_ptr< BTEditorCommand > > m_undoStack
static const size_t kMaxStackSize
std::string GetRedoDescription() const
Get description of the next redo command.
void Clear()
Clear all commands.
void Redo()
Redo the last undone command.
std::string GetDescription() const override
Get a human-readable description of the command.
ConnectNodesCommand(BehaviorTreeAsset *tree, uint32_t parentId, uint32_t childId)
void Execute() override
Execute the command.
void Undo() override
Undo the command.
void Undo() override
Undo the command.
std::vector< Connection > m_savedConnections
void Execute() override
Execute the command.
std::string GetDescription() const override
Get a human-readable description of the command.
DeleteNodeCommand(BehaviorTreeAsset *tree, uint32_t nodeId)
BehaviorTreeAsset * m_tree
void Undo() override
Undo the command.
std::string GetDescription() const override
Get a human-readable description of the command.
void Execute() override
Execute the command.
DisconnectNodesCommand(BehaviorTreeAsset *tree, uint32_t parentId, uint32_t childId)
std::string GetDescription() const override
Get a human-readable description of the command.
EditParameterCommand(BehaviorTreeAsset *tree, uint32_t nodeId, const std::string &paramName, const std::string &oldValue, const std::string &newValue, ParamType type)
void Undo() override
Undo the command.
void Execute() override
Execute the command.
std::string GetDescription() const override
Get a human-readable description of the command.
void Undo() override
Undo the command.
MoveNodeCommand(BehaviorTreeAsset *tree, uint32_t nodeId, const Vector &oldPos, const Vector &newPos)
void Execute() override
Execute the command.
Represents a single node in a behavior tree.
std::vector< uint32_t > childIds
IDs of child nodes.
uint32_t decoratorChildId
std::map< std::string, std::string > stringParams
String parameters.
uint32_t AddNode(BTNodeType type, const std::string &name, const Vector &position)
bool RemoveNode(uint32_t nodeId)
bool ConnectNodes(uint32_t parentId, uint32_t childId)
std::vector< BTNode > nodes
BTNode * GetNode(uint32_t nodeId)
bool DisconnectNodes(uint32_t parentId, uint32_t childId)