Skip to content

Commit 0ff93fa

Browse files
authored
Merge pull request #85 from limbonaut/plan-improvements
`BlackboardPlan` fixes
2 parents 7160804 + 3918272 commit 0ff93fa

11 files changed

+63
-18
lines changed

blackboard/blackboard_plan.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,12 @@ bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_p
121121
}
122122

123123
void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
124-
base = p_base;
124+
if (p_base == this) {
125+
WARN_PRINT_ED("BlackboardPlan: Using same resource for derived blackboard plan is not supported.");
126+
base.unref();
127+
} else {
128+
base = p_base;
129+
}
125130
sync_with_base_plan();
126131
notify_property_list_changed();
127132
}

bt/behavior_tree.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void BehaviorTree::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
4848
blackboard_plan->connect(LW_NAME(changed), callable_mp(this, &BehaviorTree::_plan_changed));
4949
}
5050

51-
emit_changed();
51+
_plan_changed();
5252
}
5353

5454
void BehaviorTree::set_root_task(const Ref<BTTask> &p_value) {
@@ -79,6 +79,7 @@ Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_bl
7979
}
8080

8181
void BehaviorTree::_plan_changed() {
82+
emit_signal(LW_NAME(plan_changed));
8283
emit_changed();
8384
}
8485

@@ -96,6 +97,8 @@ void BehaviorTree::_bind_methods() {
9697
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
9798
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_blackboard_plan", "get_blackboard_plan");
9899
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_task", PROPERTY_HINT_RESOURCE_TYPE, "BTTask", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_root_task", "get_root_task");
100+
101+
ADD_SIGNAL(MethodInfo("plan_changed"));
99102
}
100103

101104
BehaviorTree::BehaviorTree() {

bt/bt_player.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,21 @@ void BTPlayer::_load_tree() {
6363
void BTPlayer::_update_blackboard_plan() {
6464
if (blackboard_plan.is_null()) {
6565
blackboard_plan = Ref<BlackboardPlan>(memnew(BlackboardPlan));
66+
} else if (!RESOURCE_IS_BUILT_IN(blackboard_plan)) {
67+
WARN_PRINT_ED("BTPlayer: Using external resource for derived blackboard plan is not supported. Converted to built-in resource.");
68+
blackboard_plan = blackboard_plan->duplicate();
6669
}
70+
6771
blackboard_plan->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr);
6872
}
6973

7074
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
7175
if (Engine::get_singleton()->is_editor_hint()) {
72-
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
73-
behavior_tree->disconnect(LW_NAME(changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
76+
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
77+
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
7478
}
7579
if (p_tree.is_valid()) {
76-
p_tree->connect(LW_NAME(changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
80+
p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
7781
}
7882
behavior_tree = p_tree;
7983
_update_blackboard_plan();
@@ -212,8 +216,8 @@ void BTPlayer::_notification(int p_notification) {
212216
#endif // DEBUG_ENABLED
213217

214218
if (Engine::get_singleton()->is_editor_hint()) {
215-
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
216-
behavior_tree->disconnect(LW_NAME(changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
219+
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
220+
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan));
217221
}
218222
}
219223

@@ -244,7 +248,7 @@ void BTPlayer::_bind_methods() {
244248
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
245249
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
246250
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
247-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_blackboard_plan", "get_blackboard_plan");
251+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_blackboard_plan", "get_blackboard_plan");
248252

249253
BIND_ENUM_CONSTANT(IDLE);
250254
BIND_ENUM_CONSTANT(PHYSICS);

bt/bt_state.cpp

+14-8
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,28 @@
2525

2626
void BTState::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
2727
if (Engine::get_singleton()->is_editor_hint()) {
28-
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan))) {
29-
behavior_tree->disconnect(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan));
28+
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan))) {
29+
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
3030
}
3131
if (p_tree.is_valid()) {
32-
p_tree->connect(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan));
32+
p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
3333
}
34+
behavior_tree = p_tree;
3435
_update_blackboard_plan();
36+
} else {
37+
behavior_tree = p_tree;
3538
}
36-
behavior_tree = p_tree;
3739
}
3840

3941
void BTState::_update_blackboard_plan() {
4042
if (get_blackboard_plan().is_null()) {
41-
set_blackboard_plan(Ref<BlackboardPlan>(memnew(BlackboardPlan)));
43+
set_blackboard_plan(memnew(BlackboardPlan));
44+
} else if (!RESOURCE_IS_BUILT_IN(get_blackboard_plan())) {
45+
WARN_PRINT_ED("BTState: Using external resource for derived blackboard plan is not supported. Converted to built-in resource.");
46+
set_blackboard_plan(get_blackboard_plan()->duplicate());
47+
} else {
48+
get_blackboard_plan()->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr);
4249
}
43-
get_blackboard_plan()->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr);
4450
}
4551

4652
void BTState::_setup() {
@@ -91,8 +97,8 @@ void BTState::_notification(int p_notification) {
9197
#endif // DEBUG_ENABLED
9298

9399
if (Engine::get_singleton()->is_editor_hint()) {
94-
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan))) {
95-
behavior_tree->disconnect(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan));
100+
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan))) {
101+
behavior_tree->disconnect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
96102
}
97103
}
98104
} break;

doc/source/classes/class_behaviortree.rst

+17
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ Methods
7373

7474
.. rst-class:: classref-descriptions-group
7575

76+
Signals
77+
-------
78+
79+
.. _class_BehaviorTree_signal_plan_changed:
80+
81+
.. rst-class:: classref-signal
82+
83+
**plan_changed** **(** **)**
84+
85+
Emitted when the :ref:`BlackboardPlan<class_BlackboardPlan>` changes.
86+
87+
.. rst-class:: classref-section-separator
88+
89+
----
90+
91+
.. rst-class:: classref-descriptions-group
92+
7693
Property Descriptions
7794
---------------------
7895

doc_classes/BehaviorTree.xml

+7
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,11 @@
5858
User-provided description of the BehaviorTree.
5959
</member>
6060
</members>
61+
<signals>
62+
<signal name="plan_changed">
63+
<description>
64+
Emitted when the [BlackboardPlan] changes.
65+
</description>
66+
</signal>
67+
</signals>
6168
</class>

hsm/limbo_state.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ void LimboState::_bind_methods() {
206206
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "EVENT_FINISHED", PROPERTY_HINT_NONE, "", 0), "", "event_finished");
207207
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_agent", "get_agent");
208208
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", 0), "", "get_blackboard");
209-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT), "set_blackboard_plan", "get_blackboard_plan");
209+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_blackboard_plan", "get_blackboard_plan");
210210

211211
ADD_SIGNAL(MethodInfo("setup"));
212212
ADD_SIGNAL(MethodInfo("entered"));

hsm/limbo_state.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class LimboState : public Node {
6767

6868
public:
6969
void set_blackboard_plan(const Ref<BlackboardPlan> &p_plan);
70-
Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
70+
_FORCE_INLINE_ Ref<BlackboardPlan> get_blackboard_plan() const { return blackboard_plan; }
7171

7272
Ref<Blackboard> get_blackboard() const { return blackboard; }
7373

util/limbo_compat.h

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ Variant VARIANT_DEFAULT(Variant::Type p_type);
234234
#define PROJECT_CONFIG_FILE() GET_PROJECT_SETTINGS_DIR().path_join("limbo_ai.cfg")
235235
#define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1)
236236
#define RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
237+
#define RESOURCE_IS_BUILT_IN(m_res) (m_res->get_path().is_empty() || m_res->get_path().contains("::"))
237238

238239
#ifdef TOOLS_ENABLED
239240

util/limbo_string_names.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ LimboStringNames::LimboStringNames() {
122122
NonFavorite = SN("NonFavorite");
123123
normal = SN("normal");
124124
panel = SN("panel");
125+
plan_changed = SN("plan_changed");
125126
popup_hide = SN("popup_hide");
126127
pressed = SN("pressed");
127128
probability_clicked = SN("probability_clicked");

util/limbo_string_names.h

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class LimboStringNames {
137137
StringName NonFavorite;
138138
StringName normal;
139139
StringName panel;
140+
StringName plan_changed;
140141
StringName popup_hide;
141142
StringName pressed;
142143
StringName probability_clicked;

0 commit comments

Comments
 (0)