Port BehaviorTreeView

This commit is contained in:
Serhii Snitsaruk 2024-01-07 06:51:34 +01:00
parent f5b1b52f67
commit 3d86a76db9
7 changed files with 98 additions and 18 deletions

View File

@ -13,10 +13,11 @@
#include "behavior_tree_view.h" #include "behavior_tree_view.h"
#include "../../bt/tasks/bt_task.h"
#include "../../util/limbo_utility.h"
#include "behavior_tree_data.h" #include "behavior_tree_data.h"
#include "modules/limboai/bt/tasks/bt_task.h"
#include "modules/limboai/util/limbo_utility.h"
#ifdef LIMBOAI_MODULE
#include "core/math/color.h" #include "core/math/color.h"
#include "core/math/math_defs.h" #include "core/math/math_defs.h"
#include "core/object/callable_method_pointer.h" #include "core/object/callable_method_pointer.h"
@ -24,6 +25,7 @@
#include "editor/editor_scale.h" #include "editor/editor_scale.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "scene/resources/style_box.h" #include "scene/resources/style_box.h"
#endif // LIMBOAI_MODULE
void BehaviorTreeView::_draw_running_status(Object *p_obj, Rect2 p_rect) { void BehaviorTreeView::_draw_running_status(Object *p_obj, Rect2 p_rect) {
p_rect = p_rect.grow_side(SIDE_LEFT, p_rect.get_position().x); p_rect = p_rect.grow_side(SIDE_LEFT, p_rect.get_position().x);
@ -95,18 +97,18 @@ void BehaviorTreeView::update_tree(const BehaviorTreeData &p_data) {
item->set_icon_max_width(0, 16 * EDSCALE); // Force user icon size. item->set_icon_max_width(0, 16 * EDSCALE); // Force user icon size.
if (task_data.status == BTTask::SUCCESS) { if (task_data.status == BTTask::SUCCESS) {
item->set_custom_draw(0, this, SNAME("_draw_success_status")); item->set_custom_draw(0, this, LSNAME(_draw_success_status));
item->set_icon(1, theme_cache.icon_success); item->set_icon(1, theme_cache.icon_success);
} else if (task_data.status == BTTask::FAILURE) { } else if (task_data.status == BTTask::FAILURE) {
item->set_custom_draw(0, this, SNAME("_draw_failure_status")); item->set_custom_draw(0, this, LSNAME(_draw_failure_status));
item->set_icon(1, theme_cache.icon_failure); item->set_icon(1, theme_cache.icon_failure);
} else if (task_data.status == BTTask::RUNNING) { } else if (task_data.status == BTTask::RUNNING) {
item->set_custom_draw(0, this, SNAME("_draw_running_status")); item->set_custom_draw(0, this, LSNAME(_draw_running_status));
item->set_icon(1, theme_cache.icon_running); item->set_icon(1, theme_cache.icon_running);
} }
if (task_data.id == selected_id) { if (task_data.id == selected_id) {
tree->set_selected(item); tree->set_selected(item, 0);
} }
if (collapsed_ids.has(task_data.id)) { if (collapsed_ids.has(task_data.id)) {
@ -125,14 +127,12 @@ void BehaviorTreeView::clear() {
collapsed_ids.clear(); collapsed_ids.clear();
} }
void BehaviorTreeView::_update_theme_item_cache() { void BehaviorTreeView::_do_update_theme_item_cache() {
Control::_update_theme_item_cache(); theme_cache.icon_running = get_theme_icon(LSNAME(LimboExtraClock), LSNAME(EditorIcons));
theme_cache.icon_success = get_theme_icon(LSNAME(BTAlwaysSucceed), LSNAME(EditorIcons));
theme_cache.icon_failure = get_theme_icon(LSNAME(BTAlwaysFail), LSNAME(EditorIcons));
theme_cache.icon_running = get_theme_icon(SNAME("LimboExtraClock"), SNAME("EditorIcons")); theme_cache.font_custom_name = get_theme_font(LSNAME(bold), LSNAME(EditorFonts));
theme_cache.icon_success = get_theme_icon(SNAME("BTAlwaysSucceed"), SNAME("EditorIcons"));
theme_cache.icon_failure = get_theme_icon(SNAME("BTAlwaysFail"), SNAME("EditorIcons"));
theme_cache.font_custom_name = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
Color running_border = Color::html("#fea900"); Color running_border = Color::html("#fea900");
Color running_fill = Color(running_border, 0.1); Color running_fill = Color(running_border, 0.1);
@ -165,6 +165,17 @@ void BehaviorTreeView::_update_theme_item_cache() {
tree->set_column_custom_minimum_width(2, (50.0 + extra_spacing) * EDSCALE); tree->set_column_custom_minimum_width(2, (50.0 + extra_spacing) * EDSCALE);
} }
void BehaviorTreeView::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_POSTINITIALIZE:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_do_update_theme_item_cache();
} break;
}
}
void BehaviorTreeView::_bind_methods() { void BehaviorTreeView::_bind_methods() {
ClassDB::bind_method(D_METHOD("_draw_running_status"), &BehaviorTreeView::_draw_running_status); ClassDB::bind_method(D_METHOD("_draw_running_status"), &BehaviorTreeView::_draw_running_status);
ClassDB::bind_method(D_METHOD("_draw_success_status"), &BehaviorTreeView::_draw_success_status); ClassDB::bind_method(D_METHOD("_draw_success_status"), &BehaviorTreeView::_draw_success_status);
@ -181,7 +192,7 @@ BehaviorTreeView::BehaviorTreeView() {
tree->set_column_expand(2, false); tree->set_column_expand(2, false);
tree->set_anchor(SIDE_RIGHT, ANCHOR_END); tree->set_anchor(SIDE_RIGHT, ANCHOR_END);
tree->set_anchor(SIDE_BOTTOM, ANCHOR_END); tree->set_anchor(SIDE_BOTTOM, ANCHOR_END);
tree->connect(SNAME("item_collapsed"), callable_mp(this, &BehaviorTreeView::_item_collapsed)); tree->connect(LSNAME(item_collapsed), callable_mp(this, &BehaviorTreeView::_item_collapsed));
} }
#endif // TOOLS_ENABLED #endif // TOOLS_ENABLED

View File

@ -16,12 +16,19 @@
#include "behavior_tree_data.h" #include "behavior_tree_data.h"
#include "core/object/class_db.h" #ifdef LIMBOAI_MODULE
#include "core/object/object.h"
#include "scene/gui/control.h" #include "scene/gui/control.h"
#include "scene/gui/tree.h" #include "scene/gui/tree.h"
#include "scene/resources/style_box_flat.h" #include "scene/resources/style_box_flat.h"
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/font.hpp>
#include <godot_cpp/classes/style_box_flat.hpp>
#include <godot_cpp/classes/tree.hpp>
#endif
class BehaviorTreeView : public Control { class BehaviorTreeView : public Control {
GDCLASS(BehaviorTreeView, Control); GDCLASS(BehaviorTreeView, Control);
@ -49,7 +56,9 @@ private:
void _item_collapsed(Object *p_obj); void _item_collapsed(Object *p_obj);
protected: protected:
virtual void _update_theme_item_cache() override; void _do_update_theme_item_cache();
void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();

27
util/limbo_def.cpp Normal file
View File

@ -0,0 +1,27 @@
/**
* limbo_def.cpp
* =============================================================================
* Copyright 2021-2023 Serhii Snitsaruk
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
* =============================================================================
*/
#include "limbo_def.h"
#include "godot_cpp/classes/editor_interface.hpp"
#ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/classes/editor_settings.hpp>
using namespace godot;
Variant _EDITOR_GET(const String &p_setting) {
Ref<EditorSettings> es = EditorInterface::get_singleton()->get_editor_settings();
ERR_FAIL_COND_V(es.is_null() || !es->has_setting(p_setting), Variant());
return es->get(p_setting);
}
#endif

View File

@ -26,7 +26,11 @@
#ifdef LIMBOAI_GDEXTENSION #ifdef LIMBOAI_GDEXTENSION
#include <godot_cpp/variant/string.hpp>
#include <godot_cpp/variant/utility_functions.hpp> #include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/variant/variant.hpp>
using namespace godot;
#define IS_CLASS(m_obj, m_class) (m_obj->get_class_static() == m_class::get_class_static()) #define IS_CLASS(m_obj, m_class) (m_obj->get_class_static() == m_class::get_class_static())
#define RAND_RANGE(m_from, m_to) (UtilityFunctions::randf_range(m_from, m_to)) #define RAND_RANGE(m_from, m_to) (UtilityFunctions::randf_range(m_from, m_to))
@ -37,4 +41,9 @@
#define VCALL(m_name) (call(LSNAME(m_name))) #define VCALL(m_name) (call(LSNAME(m_name)))
#define VCALL_ARGS(m_name, ...) (call(LSNAME(m_name), __VA_ARGS__)) #define VCALL_ARGS(m_name, ...) (call(LSNAME(m_name), __VA_ARGS__))
#define EDITOR_GET(m_var) _EDITOR_GET(m_var)
Variant _EDITOR_GET(const String &p_setting);
#define EDSCALE ((int)EDITOR_GET("interface/editor/display_scale"))
#endif // LIMBOAI_GDEXTENSION #endif // LIMBOAI_GDEXTENSION

View File

@ -41,6 +41,16 @@ LimboStringNames::LimboStringNames() {
_weight_ = SN("_weight_"); _weight_ = SN("_weight_");
error_value = SN("error_value"); error_value = SN("error_value");
behavior_tree = SN("behavior_tree"); behavior_tree = SN("behavior_tree");
_draw_success_status = SN("_draw_success_status");
_draw_failure_status = SN("_draw_failure_status");
_draw_running_status = SN("_draw_running_status");
LimboExtraClock = SN("LimboExtraClock");
EditorIcons = SN("EditorIcons");
BTAlwaysSucceed = SN("BTAlwaysSucceed");
BTAlwaysFail = SN("BTAlwaysFail");
bold = SN("bold");
EditorFonts = SN("EditorFonts");
item_collapsed = SN("item_collapsed");
EVENT_FINISHED = "finished"; EVENT_FINISHED = "finished";
repeat_forever.parse_utf8("Repeat ∞"); repeat_forever.parse_utf8("Repeat ∞");

View File

@ -19,7 +19,9 @@
#endif // LIMBOAI_MODULE #endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION #ifdef LIMBOAI_GDEXTENSION
#include "godot_cpp/variant/string.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
@ -58,6 +60,16 @@ public:
StringName _weight_; StringName _weight_;
StringName error_value; StringName error_value;
StringName behavior_tree; StringName behavior_tree;
StringName _draw_success_status;
StringName _draw_failure_status;
StringName _draw_running_status;
StringName LimboExtraClock;
StringName EditorIcons;
StringName BTAlwaysSucceed;
StringName BTAlwaysFail;
StringName bold;
StringName EditorFonts;
StringName item_collapsed;
String EVENT_FINISHED; String EVENT_FINISHED;
String repeat_forever; String repeat_forever;

View File

@ -29,6 +29,8 @@
#ifdef LIMBOAI_GDEXTENSION #ifdef LIMBOAI_GDEXTENSION
#include "bt/tasks/bt_task.h" #include "bt/tasks/bt_task.h"
#include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/classes/theme.hpp>
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
#endif #endif
@ -63,7 +65,7 @@ String LimboUtility::get_status_name(int p_status) const {
} }
Ref<Texture2D> LimboUtility::get_task_icon(String p_class_or_script_path) const { Ref<Texture2D> LimboUtility::get_task_icon(String p_class_or_script_path) const {
#ifdef TOOLS_ENABLED #if defined(TOOLS_ENABLED) && defined(LIMBOAI_MODULE)
ERR_FAIL_COND_V_MSG(p_class_or_script_path.is_empty(), Variant(), "BTTask: script path or class cannot be empty."); ERR_FAIL_COND_V_MSG(p_class_or_script_path.is_empty(), Variant(), "BTTask: script path or class cannot be empty.");
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme(); Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();