From dd978b636c2ea409b7b5e013930a0662c4aec9bd Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Tue, 26 Sep 2023 15:05:37 +0200 Subject: [PATCH 1/3] Add class doc for BTProbabilitySelector --- doc_classes/BTProbabilitySelector.xml | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 doc_classes/BTProbabilitySelector.xml diff --git a/doc_classes/BTProbabilitySelector.xml b/doc_classes/BTProbabilitySelector.xml new file mode 100644 index 0000000..3eb00c9 --- /dev/null +++ b/doc_classes/BTProbabilitySelector.xml @@ -0,0 +1,59 @@ + + + + BT composite that chooses a child task to execute based on attached probabilities. + + + BTProbabilitySelector chooses a child task to execute based on attached probabilities. It is typically used for decision-making purposes. Probability distribution is calculated based on weights assigned to each child task. + Returns [code]SUCCESS[/code] when a child task returns [code]SUCCESS[/code]. + Returns [code]RUNNING[/code] when a child task returns [code]RUNNING[/code]. + The behavior of BTProbabilitySelector when a child task results in [code]FAILURE[/code] depends on the value of the [member abort_on_failure] property: + - If [member abort_on_failure] is [code]false[/code], when a child task results in [code]FAILURE[/code], BTProbabilitySelector will normalize the probability distribution over the remaiming children and choose a new child task to be executed. If all child tasks fail, the composite will return [code]FAILURE[/code]. + - If [member abort_on_failure] is [code]true[/code], when a child task results in [code]FAILURE[/code], BTProbabilitySelector will not choose another child task to be executed and will immediately return [code]FAILURE[/code]. + + + + + + + + + Returns the child task's selection probability. + + + + + + Returns the total weight of all child tasks. + + + + + + + Returns the child task's weight within the weighted probability selection algorithm. + + + + + + + + Sets the child task's weight calculated based on the desired probability. + + + + + + + + Sets the child task's weight for the weighted probability selection algorithm. + + + + + + If [code]true[/code], BTProbabilitySelector will not choose another child to execute and will return [code]FAILURE[/code] when a child task results in [code]FAILURE[/code]. + + + From b5a44c08073d8d02c5a416dc1d8532971eba611f Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Tue, 26 Sep 2023 16:06:28 +0200 Subject: [PATCH 2/3] Fix BTProbabilitySelector showing probability for comments --- bt/tasks/composites/bt_probability_selector.cpp | 12 ++++++++++++ bt/tasks/composites/bt_probability_selector.h | 7 ++++++- doc_classes/BTProbabilitySelector.xml | 7 +++++++ editor/task_tree.cpp | 4 ++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bt/tasks/composites/bt_probability_selector.cpp b/bt/tasks/composites/bt_probability_selector.cpp index 575633b..096c5b9 100644 --- a/bt/tasks/composites/bt_probability_selector.cpp +++ b/bt/tasks/composites/bt_probability_selector.cpp @@ -16,15 +16,20 @@ #include "core/error/error_macros.h" double BTProbabilitySelector::get_weight(int p_index) const { + ERR_FAIL_INDEX_V(p_index, get_child_count(), 0.0); + ERR_FAIL_COND_V(get_child(p_index)->is_class_ptr(BTComment::get_class_ptr_static()), 0.0); return _get_weight(p_index); } void BTProbabilitySelector::set_weight(int p_index, double p_weight) { + ERR_FAIL_INDEX(p_index, get_child_count()); + ERR_FAIL_COND(get_child(p_index)->is_class_ptr(BTComment::get_class_ptr_static())); _set_weight(p_index, p_weight); } double BTProbabilitySelector::get_probability(int p_index) const { ERR_FAIL_INDEX_V(p_index, get_child_count(), 0.0); + ERR_FAIL_COND_V(get_child(p_index)->is_class_ptr(BTComment::get_class_ptr_static()), 0.0); double total = _get_total_weight(); return total == 0.0 ? 0.0 : _get_weight(p_index) / total; } @@ -33,6 +38,7 @@ void BTProbabilitySelector::set_probability(int p_index, double p_probability) { ERR_FAIL_INDEX(p_index, get_child_count()); ERR_FAIL_COND(p_probability < 0.0); ERR_FAIL_COND(p_probability >= 1.0); + ERR_FAIL_COND(get_child(p_index)->is_class_ptr(BTComment::get_class_ptr_static())); double others_total = _get_total_weight() - _get_weight(p_index); double others_probability = 1.0 - p_probability; @@ -44,6 +50,11 @@ void BTProbabilitySelector::set_probability(int p_index, double p_probability) { } } +bool BTProbabilitySelector::has_probability(int p_index) const { + ERR_FAIL_INDEX_V(p_index, get_child_count(), false); + return !get_child(p_index)->is_class_ptr(BTComment::get_class_ptr_static()); +} + void BTProbabilitySelector::set_abort_on_failure(bool p_abort_on_failure) { abort_on_failure = p_abort_on_failure; emit_changed(); @@ -115,6 +126,7 @@ void BTProbabilitySelector::_bind_methods() { ClassDB::bind_method(D_METHOD("get_total_weight"), &BTProbabilitySelector::get_total_weight); ClassDB::bind_method(D_METHOD("get_probability", "p_index"), &BTProbabilitySelector::get_probability); ClassDB::bind_method(D_METHOD("set_probability", "p_index", "p_probability"), &BTProbabilitySelector::set_probability); + ClassDB::bind_method(D_METHOD("has_probability", "p_index"), &BTProbabilitySelector::has_probability); ClassDB::bind_method(D_METHOD("get_abort_on_failure"), &BTProbabilitySelector::get_abort_on_failure); ClassDB::bind_method(D_METHOD("set_abort_on_failure", "p_value"), &BTProbabilitySelector::set_abort_on_failure); diff --git a/bt/tasks/composites/bt_probability_selector.h b/bt/tasks/composites/bt_probability_selector.h index 4e893ff..12b1c25 100644 --- a/bt/tasks/composites/bt_probability_selector.h +++ b/bt/tasks/composites/bt_probability_selector.h @@ -12,6 +12,7 @@ #ifndef BT_PROBABILITY_SELECTOR_H #define BT_PROBABILITY_SELECTOR_H +#include "modules/limboai/bt/tasks/bt_comment.h" #include "modules/limboai/bt/tasks/bt_composite.h" #include "core/core_string_names.h" @@ -37,7 +38,9 @@ private: _FORCE_INLINE_ double _get_total_weight() const { double total = 0.0; for (int i = 0; i < get_child_count(); i++) { - total += _get_weight(i); + if (!get_child(i)->is_class_ptr(BTComment::get_class_ptr_static())) { + total += _get_weight(i); + } } return total; } @@ -57,6 +60,8 @@ public: double get_probability(int p_index) const; void set_probability(int p_index, double p_probability); + bool has_probability(int p_index) const; + void set_abort_on_failure(bool p_abort_on_failure); bool get_abort_on_failure() const; }; diff --git a/doc_classes/BTProbabilitySelector.xml b/doc_classes/BTProbabilitySelector.xml index 3eb00c9..2cb45d1 100644 --- a/doc_classes/BTProbabilitySelector.xml +++ b/doc_classes/BTProbabilitySelector.xml @@ -34,6 +34,13 @@ Returns the child task's weight within the weighted probability selection algorithm. + + + + + Returns whether the child task at index [param p_index] participates within the weighted probability selection algorithm and has a probability assigned to it. Returns [code]false[/code] for [BTComment] tasks. + + diff --git a/editor/task_tree.cpp b/editor/task_tree.cpp index 9480705..f5ed104 100644 --- a/editor/task_tree.cpp +++ b/editor/task_tree.cpp @@ -38,7 +38,7 @@ void TaskTree::_update_item(TreeItem *p_item) { if (p_item->get_parent()) { Ref sel = p_item->get_parent()->get_metadata(0); - if (sel.is_valid()) { + if (sel.is_valid() && sel->has_probability(p_item->get_index())) { p_item->set_custom_draw(0, this, SNAME("_draw_probability")); p_item->set_cell_mode(0, TreeItem::CELL_MODE_CUSTOM); } @@ -236,7 +236,7 @@ double TaskTree::get_selected_probability_percent() const { bool TaskTree::selected_has_probability() const { bool result = false; Ref selected = get_selected(); - if (selected.is_valid()) { + if (selected.is_valid() && !selected->is_class_ptr(BTComment::get_class_ptr_static())) { Ref probability_selector = selected->get_parent(); result = probability_selector.is_valid(); } From 953d98f89c11e8e1307aa0864338c79bf4e8fc33 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Tue, 26 Sep 2023 16:12:10 +0200 Subject: [PATCH 3/3] Add probability icon --- editor/limbo_ai_editor_plugin.cpp | 3 ++- editor/limbo_ai_editor_plugin.h | 1 + icons/LimboPercent.svg | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 icons/LimboPercent.svg diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index dc92550..4fbd08f 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -271,7 +271,7 @@ void LimboAIEditor::_on_tree_rmb(const Vector2 &p_menu_pos) { ERR_FAIL_COND_MSG(task.is_null(), "LimboAIEditor: get_selected() returned null"); if (task_tree->selected_has_probability()) { - menu->add_item(TTR("Edit Probability"), ACTION_EDIT_PROBABILITY); + menu->add_icon_item(theme_cache.percent_icon, TTR("Edit Probability"), ACTION_EDIT_PROBABILITY); } menu->add_icon_shortcut(theme_cache.rename_task_icon, ED_GET_SHORTCUT("limbo_ai/rename_task"), ACTION_RENAME); menu->add_icon_item(theme_cache.edit_script_icon, TTR("Edit Script"), ACTION_EDIT_SCRIPT); @@ -799,6 +799,7 @@ void LimboAIEditor::_update_theme_item_cache() { theme_cache.move_task_up_icon = get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")); theme_cache.open_debugger_icon = get_theme_icon(SNAME("Debug"), SNAME("EditorIcons")); theme_cache.open_doc_icon = get_theme_icon(SNAME("Help"), SNAME("EditorIcons")); + theme_cache.percent_icon = get_theme_icon(SNAME("LimboPercent"), SNAME("EditorIcons")); theme_cache.remove_task_icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")); theme_cache.rename_task_icon = get_theme_icon(SNAME("Rename"), SNAME("EditorIcons")); } diff --git a/editor/limbo_ai_editor_plugin.h b/editor/limbo_ai_editor_plugin.h index 1734584..92d4450 100644 --- a/editor/limbo_ai_editor_plugin.h +++ b/editor/limbo_ai_editor_plugin.h @@ -66,6 +66,7 @@ private: Ref move_task_up_icon; Ref open_debugger_icon; Ref open_doc_icon; + Ref percent_icon; Ref remove_task_icon; Ref rename_task_icon; } theme_cache; diff --git a/icons/LimboPercent.svg b/icons/LimboPercent.svg new file mode 100644 index 0000000..8f60917 --- /dev/null +++ b/icons/LimboPercent.svg @@ -0,0 +1 @@ + \ No newline at end of file