Compare commits

...

4 Commits

Author SHA1 Message Date
Serhii Snitsaruk 3cf90f9387
BlackboardPlan: Don't show mapping in root plans 2024-05-15 13:13:27 +02:00
Serhii Snitsaruk c6b1a40627
BlackboardPlan: Update inspector upon mapping editing finished 2024-05-15 12:52:50 +02:00
Serhii Snitsaruk d36f8f1122
Fix variables missing from BTState blackboard
Non-overridden variables could be missing at runtime in the BTState blackboard due to a bug this commit fixes.
2024-05-15 11:43:31 +02:00
Serhii Snitsaruk a572613001
BlackboardPlan: Utilize mapping in LimboHSM
Also changes how parent plan providing is implemented (used for editor hints).
2024-05-15 11:38:53 +02:00
10 changed files with 61 additions and 19 deletions

View File

@ -11,6 +11,8 @@
#include "blackboard_plan.h" #include "blackboard_plan.h"
#include "../util/limbo_utility.h"
bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) { bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
String name_str = p_name; String name_str = p_name;
@ -34,6 +36,7 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
} else { } else {
parent_scope_mapping[mapped_var_name] = value; parent_scope_mapping[mapped_var_name] = value;
} }
notify_property_list_changed();
return true; return true;
} }
@ -69,7 +72,7 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
// * Editor // * Editor
if (var_map.has(p_name)) { if (var_map.has(p_name)) {
if (has_mapping(p_name)) { if (has_mapping(p_name)) {
r_ret = "Mapped to $" + parent_scope_mapping[p_name]; r_ret = "Mapped to " + LimboUtility::get_singleton()->decorate_var(parent_scope_mapping[p_name]);
} else { } else {
r_ret = var_map[p_name].get_value(); r_ret = var_map[p_name].get_value();
} }
@ -178,8 +181,8 @@ void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
notify_property_list_changed(); notify_property_list_changed();
} }
void BlackboardPlan::set_parent_scope_plan(const Ref<BlackboardPlan> &p_plan) { void BlackboardPlan::set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider) {
parent_scope_plan = p_plan; parent_scope_plan_provider = p_parent_scope_plan_provider;
notify_property_list_changed(); notify_property_list_changed();
} }
@ -422,8 +425,8 @@ void BlackboardPlan::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_base_plan", "blackboard_plan"), &BlackboardPlan::set_base_plan); ClassDB::bind_method(D_METHOD("set_base_plan", "blackboard_plan"), &BlackboardPlan::set_base_plan);
ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan); ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan);
ClassDB::bind_method(D_METHOD("set_parent_scope_plan", "blackboard_plan"), &BlackboardPlan::set_parent_scope_plan); ClassDB::bind_method(D_METHOD("set_parent_scope_plan_provider", "callable"), &BlackboardPlan::set_parent_scope_plan_provider);
ClassDB::bind_method(D_METHOD("get_parent_scope_plan"), &BlackboardPlan::get_parent_scope_plan); ClassDB::bind_method(D_METHOD("get_parent_scope_plan_provider"), &BlackboardPlan::get_parent_scope_plan_provider);
ClassDB::bind_method(D_METHOD("is_mapping_enabled"), &BlackboardPlan::is_mapping_enabled); ClassDB::bind_method(D_METHOD("is_mapping_enabled"), &BlackboardPlan::is_mapping_enabled);
ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived); ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived);
ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan); ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan);

View File

@ -39,9 +39,9 @@ private:
// Mapping between variables in this plan and their parent scope names. // Mapping between variables in this plan and their parent scope names.
// Used for linking variables to their parent scope counterparts upon Blackboard creation/population. // Used for linking variables to their parent scope counterparts upon Blackboard creation/population.
HashMap<StringName, StringName> parent_scope_mapping; HashMap<StringName, StringName> parent_scope_mapping;
// BlackboardPlan that will be used in parent scope Blackboard creation at runtime. // Fetcher function for the parent scope plan. Funtion should return a Ref<BlackboardPlan>.
// Used to provide hints in the inspector. When set, mapping is enabled in the inspector. // Used in the inspector. When set, mapping feature becomes available.
Ref<BlackboardPlan> parent_scope_plan; Callable parent_scope_plan_provider;
// If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population). // If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population).
bool prefetch_nodepath_vars = true; bool prefetch_nodepath_vars = true;
@ -59,9 +59,10 @@ public:
void set_base_plan(const Ref<BlackboardPlan> &p_base); void set_base_plan(const Ref<BlackboardPlan> &p_base);
Ref<BlackboardPlan> get_base_plan() const { return base; } Ref<BlackboardPlan> get_base_plan() const { return base; }
void set_parent_scope_plan(const Ref<BlackboardPlan> &p_plan); void set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider);
Ref<BlackboardPlan> get_parent_scope_plan() const { return parent_scope_plan; } Callable get_parent_scope_plan_provider() const { return parent_scope_plan_provider; }
bool is_mapping_enabled() const { return parent_scope_plan.is_valid(); }
bool is_mapping_enabled() const { return parent_scope_plan_provider.is_valid() && (parent_scope_plan_provider.call() != Ref<BlackboardPlan>()); }
bool has_mapping(const StringName &p_name) const; bool has_mapping(const StringName &p_name) const;
void set_prefetch_nodepath_vars(bool p_enable); void set_prefetch_nodepath_vars(bool p_enable);

View File

@ -32,10 +32,10 @@ void BTState::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan)); p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan));
} }
behavior_tree = p_tree; behavior_tree = p_tree;
_update_blackboard_plan();
} else { } else {
behavior_tree = p_tree; behavior_tree = p_tree;
} }
_update_blackboard_plan();
} }
void BTState::_update_blackboard_plan() { void BTState::_update_blackboard_plan() {

View File

@ -35,7 +35,7 @@ void BTNewScope::_set_parent_scope_plan_from_bt() {
ERR_FAIL_NULL(get_blackboard_plan()); ERR_FAIL_NULL(get_blackboard_plan());
Ref<BehaviorTree> bt = get_root()->editor_get_behavior_tree(); Ref<BehaviorTree> bt = get_root()->editor_get_behavior_tree();
ERR_FAIL_NULL(bt); ERR_FAIL_NULL(bt);
get_blackboard_plan()->set_parent_scope_plan(bt->get_blackboard_plan()); get_blackboard_plan()->set_parent_scope_plan_provider(callable_mp(bt.ptr(), &BehaviorTree::get_blackboard_plan));
} }
#endif // TOOLS_ENABLED #endif // TOOLS_ENABLED

View File

@ -54,15 +54,22 @@ void EditorPropertyVariableName::_show_variables_popup() {
variables_popup->popup(rect); variables_popup->popup(rect);
} }
void EditorPropertyVariableName::_name_changed(const String &p_new_name) { void EditorPropertyVariableName::_name_changed(const String &p_new_name, bool p_changing) {
emit_changed(get_edited_property(), p_new_name); emit_changed(get_edited_property(), p_new_name, StringName(), p_changing);
_update_status(); _update_status();
} }
void EditorPropertyVariableName::_name_submitted() {
_name_changed(name_edit->get_text(), false);
if (name_edit->has_focus()) {
name_edit->release_focus();
}
}
void EditorPropertyVariableName::_variable_selected(int p_id) { void EditorPropertyVariableName::_variable_selected(int p_id) {
String var_name = plan->get_var_by_index(p_id).first; String var_name = plan->get_var_by_index(p_id).first;
name_edit->set_text(var_name); name_edit->set_text(var_name);
_name_changed(var_name); _name_submitted();
} }
void EditorPropertyVariableName::_update_status() { void EditorPropertyVariableName::_update_status() {
@ -143,7 +150,9 @@ void EditorPropertyVariableName::setup(const Ref<BlackboardPlan> &p_plan, bool p
void EditorPropertyVariableName::_notification(int p_what) { void EditorPropertyVariableName::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_READY: { case NOTIFICATION_READY: {
name_edit->connect(LW_NAME(text_changed), callable_mp(this, &EditorPropertyVariableName::_name_changed)); name_edit->connect(LW_NAME(text_changed), callable_mp(this, &EditorPropertyVariableName::_name_changed).bind(true));
name_edit->connect(LW_NAME(text_submitted), callable_mp(this, &EditorPropertyVariableName::_name_submitted).unbind(1));
name_edit->connect(LW_NAME(focus_exited), callable_mp(this, &EditorPropertyVariableName::_name_submitted));
variables_popup->connect(LW_NAME(id_pressed), callable_mp(this, &EditorPropertyVariableName::_variable_selected)); variables_popup->connect(LW_NAME(id_pressed), callable_mp(this, &EditorPropertyVariableName::_variable_selected));
drop_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_show_variables_popup)); drop_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_show_variables_popup));
status_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_status_pressed)); status_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_status_pressed));
@ -241,7 +250,12 @@ bool EditorInspectorPluginVariableName::_parse_property(Object *p_object, const
expected_hint = variable.get_hint(); expected_hint = variable.get_hint();
expected_hint_string = variable.get_hint_string(); expected_hint_string = variable.get_hint_string();
} }
plan = plan->get_parent_scope_plan(); if (plan->get_parent_scope_plan_provider().is_valid()) {
Ref<BlackboardPlan> parent_plan = plan->get_parent_scope_plan_provider().call();
if (parent_plan.is_valid()) {
plan = parent_plan;
}
}
ERR_FAIL_NULL_V(plan, false); ERR_FAIL_NULL_V(plan, false);
} else { } else {
plan = plan_getter.call(); plan = plan_getter.call();

View File

@ -55,7 +55,8 @@ private:
PopupMenu *variables_popup; PopupMenu *variables_popup;
void _show_variables_popup(); void _show_variables_popup();
void _name_changed(const String &p_new_name); void _name_changed(const String &p_new_name, bool p_changing);
void _name_submitted();
void _variable_selected(int p_id); void _variable_selected(int p_id);
void _update_status(); void _update_status();

View File

@ -22,12 +22,31 @@
void LimboState::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) { void LimboState::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
blackboard_plan = p_plan; blackboard_plan = p_plan;
if (Engine::get_singleton()->is_editor_hint() && blackboard_plan.is_valid()) {
blackboard_plan->set_parent_scope_plan_provider(callable_mp(this, &LimboState::_get_parent_scope_plan));
}
_update_blackboard_plan(); _update_blackboard_plan();
} }
void LimboState::_update_blackboard_plan() { void LimboState::_update_blackboard_plan() {
} }
Ref<BlackboardPlan> LimboState::_get_parent_scope_plan() const {
BlackboardPlan *parent_plan = nullptr;
const LimboState *state = this;
while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) {
state = Object::cast_to<LimboState>(state->get_parent());
ERR_FAIL_NULL_V(state, parent_plan);
if (state->blackboard_plan.is_valid()) {
parent_plan = state->blackboard_plan.ptr();
break;
}
}
return parent_plan;
}
LimboState *LimboState::get_root() const { LimboState *LimboState::get_root() const {
const Node *state = this; const Node *state = this;
while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) { while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) {

View File

@ -38,6 +38,8 @@ private:
HashMap<StringName, Callable> handlers; HashMap<StringName, Callable> handlers;
Callable guard_callable; Callable guard_callable;
Ref<BlackboardPlan> _get_parent_scope_plan() const;
protected: protected:
friend LimboHSM; friend LimboHSM;

View File

@ -85,6 +85,7 @@ LimboStringNames::LimboStringNames() {
exited = SN("exited"); exited = SN("exited");
favorite_tasks_changed = SN("favorite_tasks_changed"); favorite_tasks_changed = SN("favorite_tasks_changed");
Favorites = SN("Favorites"); Favorites = SN("Favorites");
focus_exited = SN("focus_exited");
font = SN("font"); font = SN("font");
font_color = SN("font_color"); font_color = SN("font_color");
font_size = SN("font_size"); font_size = SN("font_size");

View File

@ -101,6 +101,7 @@ public:
StringName exited; StringName exited;
StringName favorite_tasks_changed; StringName favorite_tasks_changed;
StringName Favorites; StringName Favorites;
StringName focus_exited;
StringName font_color; StringName font_color;
StringName font_size; StringName font_size;
StringName font; StringName font;