21 child->parent_ =
nullptr;
32 other.parent_ =
nullptr;
36 child->parent_ =
this;
47 child->parent_ =
nullptr;
52 name_ = std::move(other.name_);
64 other.parent_ =
nullptr;
69 child->parent_ =
this;
79 LOG_ERROR(
"Node",
"Attempting to add null child to node '" +
name_ +
"'");
83 if (child.get() ==
this) {
84 LOG_ERROR(
"Node",
"Attempting to add node '" +
name_ +
"' as child of itself");
91 if (ancestor == child.get()) {
92 LOG_ERROR(
"Node",
"Adding child '" + child->name_ +
"' to node '" +
name_ +
"' would create a cycle");
98 child->parent_ =
this;
105 LOG_ERROR(
"Node",
"Child index " + std::to_string(index) +
" out of bounds for node '" +
name_ +
"' (has " +
106 std::to_string(
children_.size()) +
" children)");
118 if (index != SIZE_MAX) {
125 LOG_ERROR(
"Node",
"Child index " + std::to_string(index) +
" out of bounds for node '" +
name_ +
"'");
129 std::unique_ptr<Node> child = std::move(
children_[index]);
134 child->parent_ =
nullptr;
142 if (index != SIZE_MAX) {
155 copy->AddChild(child->DeepCopy());
165 [&name](
const std::unique_ptr<Node> &child) { return child && child->name_ == name; });
166 return it !=
children_.end() ? it->get() :
nullptr;
171 [
id](
const std::unique_ptr<Node> &child) { return child && child->id_ == id; });
172 return it !=
children_.end() ? it->get() :
nullptr;
191 total_width += child->CalculateSubtreeWidth(node_width, horizontal_spacing);
192 total_width += horizontal_spacing;
198 total_width -= horizontal_spacing;
201 return std::max(node_width, total_width);
218 if (!child || !child->IsValid()) {
223 if (child->parent_ !=
this) {
232 std::vector<const Node *> visited;
237 size_t max_depth = 0;
240 max_depth = std::max(max_depth, child->GetDepth());
243 return max_depth + 1;
248 [](
size_t sum,
const std::unique_ptr<Node> &child) {
249 return sum + (child ? child->GetSubtreeNodeCount() : 0);
258 child->Accept(visitor);
268 static_cast<const Node *
>(child.get())->Accept(visitor);
305 std::vector<Node *> result;
309 result.push_back(child.get());
316 std::vector<const Node *> result;
320 result.push_back(child.get());
329 ") - " + std::to_string(
children_.size()) +
" children";
338 child->PrintTree(indent + 1);
345 auto copy = std::make_unique<Node>(
name_,
type_);
364 LOG_TRACE(
"Node",
"Child '" + (child ? child->
name_ :
"null") +
"' added to node '" +
name_ +
"'");
369 LOG_TRACE(
"Node",
"Child '" + (child ? child->
name_ :
"null") +
"' removed from node '" +
name_ +
"'");
375 if (std::find(visited.begin(), visited.end(),
this) != visited.end()) {
379 visited.push_back(
this);
382 bool has_cycle = std::any_of(
children_.begin(),
children_.end(), [&visited](
const std::unique_ptr<Node> &child) {
383 return child && child->HasCyclesHelper(visited);
391 for (
size_t i = 0; i <
children_.size(); ++i) {
417 return std::make_unique<Node>(name, type);
435 root->AddChild(std::move(combat_sequence));
436 root->AddChild(std::move(patrol_sequence));
437 root->AddChild(std::move(idle_action));
#define LOG_ERROR(category, message)
#define LOG_TRACE(category, message)
#define LOG_INFO(category, message)
static std::unique_ptr< Node > CreateConditionNode(const String &name)
static std::unique_ptr< Node > CreateSampleTree()
static std::unique_ptr< Node > CreateNode(const String &name, Node::Type type)
static std::unique_ptr< Node > CreateActionNode(const String &name)
static std::unique_ptr< Node > CreateControlNode(const String &name)
static std::unique_ptr< Node > CreateDecoratorNode(const String &name)
virtual std::unique_ptr< Node > CreateCopy() const
bool HasAttribute(const String &name) const
Node(const String &name, Type type=Type::None)
String GetStatusString() const
Status
Node status for runtime execution tracking.
std::map< String, String > custom_attributes_
virtual void OnChildAdded(Node *child)
void RemoveChild(size_t index)
void PrintTree(int indent=0) const
const std::map< String, String > & GetAllAttributes() const
VisualState
Visual state for UI rendering.
size_t GetSubtreeNodeCount() const
VisualState visual_state_
size_t GetAttributeCount() const
std::vector< std::unique_ptr< Node > > children_
String GetAttribute(const String &name, const String &default_value="") const
Node * GetChild(size_t index) const
bool HasCyclesHelper(std::vector< const Node * > &visited) const
String GetTypeString() const
Type
Node types for behavior tree classification.
virtual void OnChildRemoved(Node *child)
void Accept(std::function< void(Node *)> visitor)
Node * FindChild(const String &name) const
void SetAttribute(const String &name, const String &value)
void RemoveAttribute(const String &name)
std::vector< Node * > GetAllChildren()
std::unique_ptr< Node > DetachChild(size_t index)
size_t FindChildIndex(Node *child) const
Node * FindChildById(size_t id) const
void AddChild(std::unique_ptr< Node > child)
Node & operator=(const Node &other)=delete
int CalculateSubtreeWidth(int node_width, int horizontal_spacing) const
std::unique_ptr< Node > DeepCopy() const
Main types header for EmberCore.
std::string String
Framework-agnostic string type.