Add `agent` parameter to `BTPlayer` to propagate upon `BehaviorTree` initialization, and add `scene_root` property to `BTTask`
`scene_root` is useful to resolve exported NodePath properties in `BTTask` instances (and for BBNode parameters).
This commit is contained in:
parent
75e8e68da4
commit
5dff2e537b
|
@ -71,10 +71,10 @@ void BehaviorTree::copy_other(const Ref<BehaviorTree> &p_other) {
|
||||||
root_task = p_other->get_root_task();
|
root_task = p_other->get_root_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard) const {
|
Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) const {
|
||||||
ERR_FAIL_COND_V_MSG(root_task == nullptr, memnew(BTTask), "Trying to instance a behavior tree with no valid root task.");
|
ERR_FAIL_COND_V_MSG(root_task == nullptr, memnew(BTTask), "Trying to instance a behavior tree with no valid root task.");
|
||||||
Ref<BTTask> inst = root_task->clone();
|
Ref<BTTask> inst = root_task->clone();
|
||||||
inst->initialize(p_agent, p_blackboard);
|
inst->initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
|
|
||||||
Ref<BehaviorTree> clone() const;
|
Ref<BehaviorTree> clone() const;
|
||||||
void copy_other(const Ref<BehaviorTree> &p_other);
|
void copy_other(const Ref<BehaviorTree> &p_other);
|
||||||
Ref<BTTask> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard) const;
|
Ref<BTTask> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) const;
|
||||||
|
|
||||||
BehaviorTree();
|
BehaviorTree();
|
||||||
~BehaviorTree();
|
~BehaviorTree();
|
||||||
|
|
|
@ -50,9 +50,13 @@ void BTPlayer::_load_tree() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tree_instance.unref();
|
tree_instance.unref();
|
||||||
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer: Needs a valid behavior tree.");
|
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer: Initialization failed - needs a valid behavior tree.");
|
||||||
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "BTPlayer: Behavior tree has no valid root task.");
|
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "BTPlayer: Initialization failed - behavior tree has no valid root task.");
|
||||||
tree_instance = behavior_tree->instantiate(get_owner(), blackboard);
|
Node *agent_node = GET_NODE(this, agent);
|
||||||
|
ERR_FAIL_NULL_MSG(agent_node, vformat("BTPlayer: Initialization failed - can't get agent by provided path '%s'.", agent));
|
||||||
|
Node *scene_root = get_owner();
|
||||||
|
ERR_FAIL_NULL_MSG(scene_root, "BTPlayer: Initialization failed - can't get scene root (make sure the BTPlayer.owner is set).");
|
||||||
|
tree_instance = behavior_tree->instantiate(agent_node, blackboard, scene_root);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (IS_DEBUGGER_ACTIVE()) {
|
if (IS_DEBUGGER_ACTIVE()) {
|
||||||
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
LimboDebugger::get_singleton()->register_bt_instance(tree_instance, get_path());
|
||||||
|
@ -228,6 +232,8 @@ void BTPlayer::_notification(int p_notification) {
|
||||||
void BTPlayer::_bind_methods() {
|
void BTPlayer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTPlayer::set_behavior_tree);
|
ClassDB::bind_method(D_METHOD("set_behavior_tree", "behavior_tree"), &BTPlayer::set_behavior_tree);
|
||||||
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTPlayer::set_agent);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_agent"), &BTPlayer::get_agent);
|
||||||
ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &BTPlayer::set_update_mode);
|
ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &BTPlayer::set_update_mode);
|
||||||
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
||||||
ClassDB::bind_method(D_METHOD("set_active", "active"), &BTPlayer::set_active);
|
ClassDB::bind_method(D_METHOD("set_active", "active"), &BTPlayer::set_active);
|
||||||
|
@ -245,6 +251,7 @@ void BTPlayer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTPlayer::get_tree_instance);
|
ClassDB::bind_method(D_METHOD("get_tree_instance"), &BTPlayer::get_tree_instance);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "agent"), "set_agent", "get_agent");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
|
||||||
|
@ -266,6 +273,7 @@ void BTPlayer::_bind_methods() {
|
||||||
|
|
||||||
BTPlayer::BTPlayer() {
|
BTPlayer::BTPlayer() {
|
||||||
blackboard = Ref<Blackboard>(memnew(Blackboard));
|
blackboard = Ref<Blackboard>(memnew(Blackboard));
|
||||||
|
agent = LW_NAME(node_pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
BTPlayer::~BTPlayer() {
|
BTPlayer::~BTPlayer() {
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<BehaviorTree> behavior_tree;
|
Ref<BehaviorTree> behavior_tree;
|
||||||
|
NodePath agent;
|
||||||
Ref<BlackboardPlan> blackboard_plan;
|
Ref<BlackboardPlan> blackboard_plan;
|
||||||
UpdateMode update_mode = UpdateMode::PHYSICS;
|
UpdateMode update_mode = UpdateMode::PHYSICS;
|
||||||
bool active = true;
|
bool active = true;
|
||||||
|
@ -57,6 +58,9 @@ public:
|
||||||
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||||
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||||
|
|
||||||
|
void set_agent(const NodePath &p_agent) { agent = p_agent; }
|
||||||
|
NodePath get_agent() const { return agent; }
|
||||||
|
|
||||||
void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan);
|
void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan);
|
||||||
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
|
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ void BTState::_setup() {
|
||||||
LimboState::_setup();
|
LimboState::_setup();
|
||||||
ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned.");
|
ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned.");
|
||||||
// TODO: BBNode relies on agent to be scene owner, so if the user provides anything else, the behavior tree can break.
|
// TODO: BBNode relies on agent to be scene owner, so if the user provides anything else, the behavior tree can break.
|
||||||
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard());
|
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard(), get_owner());
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
if (tree_instance.is_valid() && IS_DEBUGGER_ACTIVE()) {
|
||||||
|
|
|
@ -159,13 +159,15 @@ void BTTask::set_custom_name(const String &p_name) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void BTTask::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
void BTTask::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND(p_agent == nullptr);
|
ERR_FAIL_NULL(p_agent);
|
||||||
ERR_FAIL_COND(p_blackboard == nullptr);
|
ERR_FAIL_NULL(p_blackboard);
|
||||||
|
ERR_FAIL_NULL(p_scene_root);
|
||||||
data.agent = p_agent;
|
data.agent = p_agent;
|
||||||
data.blackboard = p_blackboard;
|
data.blackboard = p_blackboard;
|
||||||
|
data.scene_root = p_scene_root;
|
||||||
for (int i = 0; i < data.children.size(); i++) {
|
for (int i = 0; i < data.children.size(); i++) {
|
||||||
get_child(i)->initialize(p_agent, p_blackboard);
|
get_child(i)->initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
VCALL_OR_NATIVE(_setup);
|
VCALL_OR_NATIVE(_setup);
|
||||||
|
@ -399,6 +401,7 @@ void BTTask::_bind_methods() {
|
||||||
// Properties, setters and getters.
|
// Properties, setters and getters.
|
||||||
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
||||||
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTTask::set_agent);
|
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTTask::set_agent);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_scene_root"), &BTTask::get_scene_root);
|
||||||
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
||||||
ClassDB::bind_method(D_METHOD("_set_children", "children"), &BTTask::_set_children);
|
ClassDB::bind_method(D_METHOD("_set_children", "children"), &BTTask::_set_children);
|
||||||
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
||||||
|
@ -410,6 +413,7 @@ void BTTask::_bind_methods() {
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_agent", "get_agent");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_agent", "get_agent");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_NODE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_scene_root");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", PROPERTY_USAGE_NONE), "", "get_blackboard");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", PROPERTY_USAGE_NONE), "", "get_blackboard");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_status");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_status");
|
||||||
|
|
|
@ -75,6 +75,7 @@ private:
|
||||||
int index = -1;
|
int index = -1;
|
||||||
String custom_name;
|
String custom_name;
|
||||||
Node *agent = nullptr;
|
Node *agent = nullptr;
|
||||||
|
Node *scene_root = nullptr;
|
||||||
Ref<Blackboard> blackboard;
|
Ref<Blackboard> blackboard;
|
||||||
BTTask *parent = nullptr;
|
BTTask *parent = nullptr;
|
||||||
Vector<Ref<BTTask>> children;
|
Vector<Ref<BTTask>> children;
|
||||||
|
@ -116,6 +117,8 @@ public:
|
||||||
_FORCE_INLINE_ Node *get_agent() const { return data.agent; }
|
_FORCE_INLINE_ Node *get_agent() const { return data.agent; }
|
||||||
void set_agent(Node *p_agent) { data.agent = p_agent; }
|
void set_agent(Node *p_agent) { data.agent = p_agent; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Node *get_scene_root() const { return data.scene_root; }
|
||||||
|
|
||||||
void set_display_collapsed(bool p_display_collapsed);
|
void set_display_collapsed(bool p_display_collapsed);
|
||||||
bool is_displayed_collapsed() const;
|
bool is_displayed_collapsed() const;
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ public:
|
||||||
Ref<BTTask> get_root() const;
|
Ref<BTTask> get_root() const;
|
||||||
|
|
||||||
virtual Ref<BTTask> clone() const;
|
virtual Ref<BTTask> clone() const;
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard);
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root);
|
||||||
virtual PackedStringArray get_configuration_warnings(); // ! Native version.
|
virtual PackedStringArray get_configuration_warnings(); // ! Native version.
|
||||||
|
|
||||||
Status execute(double p_delta);
|
Status execute(double p_delta);
|
||||||
|
|
|
@ -20,7 +20,7 @@ void BTNewScope::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND(p_agent == nullptr);
|
ERR_FAIL_COND(p_agent == nullptr);
|
||||||
ERR_FAIL_COND(p_blackboard == nullptr);
|
ERR_FAIL_COND(p_blackboard == nullptr);
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
|
||||||
|
|
||||||
bb->set_parent(p_blackboard);
|
bb->set_parent(p_blackboard);
|
||||||
|
|
||||||
BTDecorator::initialize(p_agent, bb);
|
BTDecorator::initialize(p_agent, bb, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
BT::Status BTNewScope::_tick(double p_delta) {
|
BT::Status BTNewScope::_tick(double p_delta) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ protected:
|
||||||
virtual Status _tick(double p_delta) override;
|
virtual Status _tick(double p_delta) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BT_NEW_SCOPE_H
|
#endif // BT_NEW_SCOPE_H
|
||||||
|
|
|
@ -44,14 +44,14 @@ String BTSubtree::_generate_name() {
|
||||||
return vformat("Subtree %s", s);
|
return vformat("Subtree %s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTSubtree::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
|
void BTSubtree::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
||||||
ERR_FAIL_COND_MSG(!subtree.is_valid(), "Subtree is not assigned.");
|
ERR_FAIL_COND_MSG(!subtree.is_valid(), "Subtree is not assigned.");
|
||||||
ERR_FAIL_COND_MSG(!subtree->get_root_task().is_valid(), "Subtree root task is not valid.");
|
ERR_FAIL_COND_MSG(!subtree->get_root_task().is_valid(), "Subtree root task is not valid.");
|
||||||
ERR_FAIL_COND_MSG(get_child_count() != 0, "Subtree task shouldn't have children during initialization.");
|
ERR_FAIL_COND_MSG(get_child_count() != 0, "Subtree task shouldn't have children during initialization.");
|
||||||
|
|
||||||
add_child(subtree->get_root_task()->clone());
|
add_child(subtree->get_root_task()->clone());
|
||||||
|
|
||||||
BTNewScope::initialize(p_agent, p_blackboard);
|
BTNewScope::initialize(p_agent, p_blackboard, p_scene_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
BT::Status BTSubtree::_tick(double p_delta) {
|
BT::Status BTSubtree::_tick(double p_delta) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void set_subtree(const Ref<BehaviorTree> &p_value);
|
void set_subtree(const Ref<BehaviorTree> &p_value);
|
||||||
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
||||||
|
|
||||||
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;
|
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) override;
|
||||||
virtual PackedStringArray get_configuration_warnings() override;
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
|
|
||||||
BTSubtree() = default;
|
BTSubtree() = default;
|
||||||
|
|
|
@ -51,13 +51,13 @@ TEST_CASE("[SceneTree][LimboAI] BTAwaitAnimation") {
|
||||||
SUBCASE("When AnimationPlayer doesn't exist") {
|
SUBCASE("When AnimationPlayer doesn't exist") {
|
||||||
player_param->set_saved_value(NodePath("./NotFound"));
|
player_param->set_saved_value(NodePath("./NotFound"));
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
awa->initialize(dummy, bb);
|
awa->initialize(dummy, bb, dummy);
|
||||||
CHECK(awa->execute(0.01666) == BTTask::FAILURE);
|
CHECK(awa->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
SUBCASE("When AnimationPlayer exists") {
|
SUBCASE("When AnimationPlayer exists") {
|
||||||
player_param->set_saved_value(player->get_path());
|
player_param->set_saved_value(player->get_path());
|
||||||
awa->initialize(dummy, bb);
|
awa->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When AnimationPlayer is not playing") {
|
SUBCASE("When AnimationPlayer is not playing") {
|
||||||
REQUIRE_FALSE(player->is_playing());
|
REQUIRE_FALSE(player->is_playing());
|
||||||
|
|
|
@ -47,7 +47,7 @@ TEST_CASE("[Modules][LimboAI] BTCallMethod") {
|
||||||
node_param->set_variable("object");
|
node_param->set_variable("object");
|
||||||
cm->set_method("callback");
|
cm->set_method("callback");
|
||||||
|
|
||||||
cm->initialize(dummy, bb);
|
cm->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When method is empty") {
|
SUBCASE("When method is empty") {
|
||||||
cm->set_method("");
|
cm->set_method("");
|
||||||
|
|
|
@ -39,7 +39,7 @@ TEST_CASE("[Modules][LimboAI] BTCheckAgentProperty") {
|
||||||
Ref<BTCheckAgentProperty> cap = memnew(BTCheckAgentProperty);
|
Ref<BTCheckAgentProperty> cap = memnew(BTCheckAgentProperty);
|
||||||
Node *agent = memnew(Node);
|
Node *agent = memnew(Node);
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
cap->initialize(agent, bb);
|
cap->initialize(agent, bb, agent);
|
||||||
StringName agent_name = "SimpleNode";
|
StringName agent_name = "SimpleNode";
|
||||||
agent->set_name(agent_name);
|
agent->set_name(agent_name);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ TEST_CASE("[Modules][LimboAI] BTCheckTrigger") {
|
||||||
Node *dummy = memnew(Node);
|
Node *dummy = memnew(Node);
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
|
|
||||||
ct->initialize(dummy, bb);
|
ct->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("Empty") {
|
SUBCASE("Empty") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
|
|
|
@ -36,7 +36,7 @@ TEST_CASE("[Modules][LimboAI] BTCheckVar") {
|
||||||
Ref<BTCheckVar> cv = memnew(BTCheckVar);
|
Ref<BTCheckVar> cv = memnew(BTCheckVar);
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
Node *dummy = memnew(Node);
|
Node *dummy = memnew(Node);
|
||||||
cv->initialize(dummy, bb);
|
cv->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("Check with empty variable and value") {
|
SUBCASE("Check with empty variable and value") {
|
||||||
cv->set_variable("");
|
cv->set_variable("");
|
||||||
|
|
|
@ -47,7 +47,7 @@ TEST_CASE("[Modules][LimboAI] BTEvaluateExpression") {
|
||||||
node_param->set_variable("object");
|
node_param->set_variable("object");
|
||||||
ee->set_expression_string("callback()");
|
ee->set_expression_string("callback()");
|
||||||
|
|
||||||
ee->initialize(dummy, bb);
|
ee->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When expression string is empty") {
|
SUBCASE("When expression string is empty") {
|
||||||
ee->set_expression_string("");
|
ee->set_expression_string("");
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_CASE("[Modules][LimboAI] BTForEach") {
|
||||||
Ref<BTForEach> fe = memnew(BTForEach);
|
Ref<BTForEach> fe = memnew(BTForEach);
|
||||||
Node *dummy = memnew(Node);
|
Node *dummy = memnew(Node);
|
||||||
Ref<Blackboard> blackboard = memnew(Blackboard);
|
Ref<Blackboard> blackboard = memnew(Blackboard);
|
||||||
fe->initialize(dummy, blackboard);
|
fe->initialize(dummy, blackboard, dummy);
|
||||||
|
|
||||||
Array arr;
|
Array arr;
|
||||||
arr.append("apple");
|
arr.append("apple");
|
||||||
|
|
|
@ -26,7 +26,7 @@ TEST_CASE("[Modules][LimboAI] BTNewScope") {
|
||||||
|
|
||||||
SUBCASE("When empty") {
|
SUBCASE("When empty") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
ns->initialize(dummy, parent_bb);
|
ns->initialize(dummy, parent_bb, dummy);
|
||||||
CHECK(ns->execute(0.01666) == BTTask::FAILURE);
|
CHECK(ns->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ TEST_CASE("[Modules][LimboAI] BTNewScope") {
|
||||||
REQUIRE(parent_bb->has_var("vegetable"));
|
REQUIRE(parent_bb->has_var("vegetable"));
|
||||||
REQUIRE(parent_bb->get_var("vegetable", "wetgoop") == "carrot");
|
REQUIRE(parent_bb->get_var("vegetable", "wetgoop") == "carrot");
|
||||||
|
|
||||||
parent->initialize(dummy, parent_bb);
|
parent->initialize(dummy, parent_bb, dummy);
|
||||||
|
|
||||||
CHECK(ns->get_blackboard() != parent->get_blackboard());
|
CHECK(ns->get_blackboard() != parent->get_blackboard());
|
||||||
CHECK(ns->get_blackboard() == child->get_blackboard());
|
CHECK(ns->get_blackboard() == child->get_blackboard());
|
||||||
|
|
|
@ -48,13 +48,13 @@ TEST_CASE("[SceneTree][LimboAI] BTPauseAnimation") {
|
||||||
SUBCASE("When AnimationPlayer doesn't exist") {
|
SUBCASE("When AnimationPlayer doesn't exist") {
|
||||||
player_param->set_saved_value(NodePath("./NotFound"));
|
player_param->set_saved_value(NodePath("./NotFound"));
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
pa->initialize(dummy, bb);
|
pa->initialize(dummy, bb, dummy);
|
||||||
CHECK(pa->execute(0.01666) == BTTask::FAILURE);
|
CHECK(pa->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
SUBCASE("When AnimationPlayer exists") {
|
SUBCASE("When AnimationPlayer exists") {
|
||||||
player_param->set_saved_value(player->get_path());
|
player_param->set_saved_value(player->get_path());
|
||||||
pa->initialize(dummy, bb);
|
pa->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When AnimationPlayer is not playing") {
|
SUBCASE("When AnimationPlayer is not playing") {
|
||||||
REQUIRE_FALSE(player->is_playing());
|
REQUIRE_FALSE(player->is_playing());
|
||||||
|
|
|
@ -49,13 +49,13 @@ TEST_CASE("[SceneTree][LimboAI] BTPlayAnimation") {
|
||||||
SUBCASE("When AnimationPlayer doesn't exist") {
|
SUBCASE("When AnimationPlayer doesn't exist") {
|
||||||
player_param->set_saved_value(NodePath("./NotFound"));
|
player_param->set_saved_value(NodePath("./NotFound"));
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
pa->initialize(dummy, bb);
|
pa->initialize(dummy, bb, dummy);
|
||||||
CHECK(pa->execute(0.01666) == BTTask::FAILURE);
|
CHECK(pa->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
SUBCASE("When AnimationPlayer exists") {
|
SUBCASE("When AnimationPlayer exists") {
|
||||||
player_param->set_saved_value(player->get_path());
|
player_param->set_saved_value(player->get_path());
|
||||||
pa->initialize(dummy, bb);
|
pa->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When not waiting to finish") {
|
SUBCASE("When not waiting to finish") {
|
||||||
pa->set_await_completion(0.0);
|
pa->set_await_completion(0.0);
|
||||||
|
|
|
@ -28,7 +28,7 @@ TEST_CASE("[Modules][LimboAI] BTSetAgentProperty") {
|
||||||
Ref<BTSetAgentProperty> sap = memnew(BTSetAgentProperty);
|
Ref<BTSetAgentProperty> sap = memnew(BTSetAgentProperty);
|
||||||
Node *agent = memnew(Node);
|
Node *agent = memnew(Node);
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
sap->initialize(agent, bb);
|
sap->initialize(agent, bb, agent);
|
||||||
|
|
||||||
sap->set_property("process_priority"); // * property that will be set by the task
|
sap->set_property("process_priority"); // * property that will be set by the task
|
||||||
Ref<BBVariant> value = memnew(BBVariant);
|
Ref<BBVariant> value = memnew(BBVariant);
|
||||||
|
|
|
@ -29,7 +29,7 @@ TEST_CASE("[Modules][LimboAI] BTSetVar") {
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
Node *dummy = memnew(Node);
|
Node *dummy = memnew(Node);
|
||||||
|
|
||||||
sv->initialize(dummy, bb);
|
sv->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When variable is not set") {
|
SUBCASE("When variable is not set") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
|
|
|
@ -48,13 +48,13 @@ TEST_CASE("[SceneTree][LimboAI] BTStopAnimation") {
|
||||||
SUBCASE("When AnimationPlayer doesn't exist") {
|
SUBCASE("When AnimationPlayer doesn't exist") {
|
||||||
player_param->set_saved_value(NodePath("./NotFound"));
|
player_param->set_saved_value(NodePath("./NotFound"));
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
sa->initialize(dummy, bb);
|
sa->initialize(dummy, bb, dummy);
|
||||||
CHECK(sa->execute(0.01666) == BTTask::FAILURE);
|
CHECK(sa->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
SUBCASE("When AnimationPlayer exists") {
|
SUBCASE("When AnimationPlayer exists") {
|
||||||
player_param->set_saved_value(player->get_path());
|
player_param->set_saved_value(player->get_path());
|
||||||
sa->initialize(dummy, bb);
|
sa->initialize(dummy, bb, dummy);
|
||||||
|
|
||||||
SUBCASE("When AnimationPlayer is not playing") {
|
SUBCASE("When AnimationPlayer is not playing") {
|
||||||
REQUIRE_FALSE(player->is_playing());
|
REQUIRE_FALSE(player->is_playing());
|
||||||
|
|
|
@ -29,7 +29,7 @@ TEST_CASE("[Modules][LimboAI] BTSubtree") {
|
||||||
|
|
||||||
SUBCASE("When empty") {
|
SUBCASE("When empty") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
st->initialize(dummy, bb);
|
st->initialize(dummy, bb, dummy);
|
||||||
CHECK(st->execute(0.01666) == BTTask::FAILURE);
|
CHECK(st->execute(0.01666) == BTTask::FAILURE);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ TEST_CASE("[Modules][LimboAI] BTSubtree") {
|
||||||
st->set_subtree(bt);
|
st->set_subtree(bt);
|
||||||
|
|
||||||
CHECK(st->get_child_count() == 0);
|
CHECK(st->get_child_count() == 0);
|
||||||
st->initialize(dummy, bb);
|
st->initialize(dummy, bb, dummy);
|
||||||
CHECK(st->get_child_count() == 1);
|
CHECK(st->get_child_count() == 1);
|
||||||
CHECK(st->get_child(0) != task);
|
CHECK(st->get_child(0) != task);
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ TEST_CASE("[Modules][LimboAI] BTTask") {
|
||||||
Node *dummy = memnew(Node);
|
Node *dummy = memnew(Node);
|
||||||
Ref<Blackboard> bb = memnew(Blackboard);
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
SUBCASE("With valid parameters") {
|
SUBCASE("With valid parameters") {
|
||||||
task->initialize(dummy, bb);
|
task->initialize(dummy, bb, dummy);
|
||||||
CHECK(task->get_agent() == dummy);
|
CHECK(task->get_agent() == dummy);
|
||||||
CHECK(task->get_blackboard() == bb);
|
CHECK(task->get_blackboard() == bb);
|
||||||
CHECK(child1->get_agent() == dummy);
|
CHECK(child1->get_agent() == dummy);
|
||||||
|
@ -174,12 +174,17 @@ TEST_CASE("[Modules][LimboAI] BTTask") {
|
||||||
}
|
}
|
||||||
SUBCASE("Test if not crashes when agent is null") {
|
SUBCASE("Test if not crashes when agent is null") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
task->initialize(nullptr, bb);
|
task->initialize(nullptr, bb, dummy);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
SUBCASE("Test if not crashes when scene_owner is null") {
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
task->initialize(dummy, bb, nullptr);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
SUBCASE("Test if not crashes when BB is null") {
|
SUBCASE("Test if not crashes when BB is null") {
|
||||||
ERR_PRINT_OFF;
|
ERR_PRINT_OFF;
|
||||||
task->initialize(dummy, nullptr);
|
task->initialize(dummy, nullptr, dummy);
|
||||||
ERR_PRINT_ON;
|
ERR_PRINT_ON;
|
||||||
}
|
}
|
||||||
memdelete(dummy);
|
memdelete(dummy);
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable, Variant()))
|
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable, Variant()))
|
||||||
#define GET_SCRIPT(m_obj) (m_obj->get_script_instance() ? m_obj->get_script_instance()->get_script() : nullptr)
|
#define GET_SCRIPT(m_obj) (m_obj->get_script_instance() ? m_obj->get_script_instance()->get_script() : nullptr)
|
||||||
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_style_override(m_name, m_stylebox))
|
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_style_override(m_name, m_stylebox))
|
||||||
|
#define GET_NODE(m_parent, m_path) m_parent->get_node(m_path)
|
||||||
|
|
||||||
_FORCE_INLINE_ bool OBJECT_HAS_PROPERTY(Object *p_obj, const StringName &p_prop) {
|
_FORCE_INLINE_ bool OBJECT_HAS_PROPERTY(Object *p_obj, const StringName &p_prop) {
|
||||||
bool r_valid;
|
bool r_valid;
|
||||||
|
@ -137,6 +138,7 @@ using namespace godot;
|
||||||
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable))
|
#define PERFORMANCE_ADD_CUSTOM_MONITOR(m_id, m_callable) (Performance::get_singleton()->add_custom_monitor(m_id, m_callable))
|
||||||
#define GET_SCRIPT(m_obj) (m_obj->get_script())
|
#define GET_SCRIPT(m_obj) (m_obj->get_script())
|
||||||
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_stylebox_override(m_name, m_stylebox))
|
#define ADD_STYLEBOX_OVERRIDE(m_control, m_name, m_stylebox) (m_control->add_theme_stylebox_override(m_name, m_stylebox))
|
||||||
|
#define GET_NODE(m_parent, m_path) m_parent->get_node_internal(m_path)
|
||||||
|
|
||||||
_FORCE_INLINE_ bool OBJECT_HAS_PROPERTY(Object *p_obj, const StringName &p_prop) {
|
_FORCE_INLINE_ bool OBJECT_HAS_PROPERTY(Object *p_obj, const StringName &p_prop) {
|
||||||
return Variant(p_obj).has_key(p_prop);
|
return Variant(p_obj).has_key(p_prop);
|
||||||
|
|
|
@ -166,4 +166,6 @@ LimboStringNames::LimboStringNames() {
|
||||||
|
|
||||||
repeat_forever.parse_utf8("Repeat ∞");
|
repeat_forever.parse_utf8("Repeat ∞");
|
||||||
output_var_prefix.parse_utf8("➜");
|
output_var_prefix.parse_utf8("➜");
|
||||||
|
|
||||||
|
node_pp = NodePath("..");
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define LIMBO_STRING_NAMES_H
|
#define LIMBO_STRING_NAMES_H
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
|
#include "core/string/node_path.h"
|
||||||
#include "core/string/string_name.h"
|
#include "core/string/string_name.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
#include "modules/register_module_types.h"
|
#include "modules/register_module_types.h"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
|
|
||||||
#ifdef LIMBOAI_GDEXTENSION
|
#ifdef LIMBOAI_GDEXTENSION
|
||||||
#include "godot_cpp/variant/string.hpp"
|
#include "godot_cpp/variant/string.hpp"
|
||||||
|
#include <godot_cpp/variant/node_path.hpp>
|
||||||
#include <godot_cpp/variant/string_name.hpp>
|
#include <godot_cpp/variant/string_name.hpp>
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
#endif // LIMBOAI_GDEXTENSION
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
@ -181,6 +183,8 @@ public:
|
||||||
|
|
||||||
String repeat_forever;
|
String repeat_forever;
|
||||||
String output_var_prefix;
|
String output_var_prefix;
|
||||||
|
|
||||||
|
NodePath node_pp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LW_NAME(m_arg) LimboStringNames::get_singleton()->m_arg
|
#define LW_NAME(m_arg) LimboStringNames::get_singleton()->m_arg
|
||||||
|
|
Loading…
Reference in New Issue