#include "behaviour_tree.h" #include "behaviour_nodes/behaviour_composite.h" #include "behaviour_nodes/behaviour_node.h" #include "core/config/engine.h" #include "core/object/class_db.h" #include "core/object/object.h" #include "core/variant/typed_array.h" void BehaviourTree::_bind_methods() { ADD_SIGNAL(MethodInfo("current_behaviour_changed", PropertyInfo(Variant::OBJECT, "new_behaviour", PROPERTY_HINT_NODE_TYPE, "BehaviourNode"))); } void BehaviourTree::process() { do { this->current->execute(); } while (execute_next()); } void BehaviourTree::_notification(int what) { if (Engine::get_singleton()->is_editor_hint()) { return; } switch (what) { default: return; case NOTIFICATION_READY: for (Variant var : get_children()) { if ((this->root = cast_to(var))) { this->current = this->root; break; } } ERR_FAIL_COND_EDMSG(this->root == nullptr, "No valid BehaviourNode in BehaviourTree"); set_process(true); return; case NOTIFICATION_PROCESS: process(); return; } } bool BehaviourTree::execute_next() { BehaviourNode *next{ this->current->get_next() }; if (next == this->current) { return false; } else { ERR_FAIL_COND_V_EDMSG(next == nullptr, false, vformat("%s::get_next returned a nullptr, repeating last node", this->current->get_class())); if (this->current != next->get_parent()) { this->current->exit(); } if (this->current->get_parent() != next) { next->enter(); emit_signal("current_behaviour_changed", next); } this->current = next; return this->current != this->root && (cast_to(this->current) || this->current->get_status() != BehaviourNode::Running); } }