From 2795c6dcf2e2c4954555e23705da6c6f998434d0 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Tue, 8 Aug 2023 15:06:01 +0200 Subject: [PATCH] Add BTCheckVar condition task --- bt/conditions/bt_check_var.cpp | 135 +++++++++++++++++++++++++++++++++ bt/conditions/bt_check_var.h | 59 ++++++++++++++ config.py | 1 + icons/BTCheckVar.svg | 1 + register_types.cpp | 2 + 5 files changed, 198 insertions(+) create mode 100644 bt/conditions/bt_check_var.cpp create mode 100644 bt/conditions/bt_check_var.h create mode 100644 icons/BTCheckVar.svg diff --git a/bt/conditions/bt_check_var.cpp b/bt/conditions/bt_check_var.cpp new file mode 100644 index 0000000..dfebc7f --- /dev/null +++ b/bt/conditions/bt_check_var.cpp @@ -0,0 +1,135 @@ +/** + * bt_check_var.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 "bt_check_var.h" + +#include "modules/limboai/util/limbo_utility.h" + +#include "core/variant/callable.h" + +VARIANT_ENUM_CAST(BTCheckVar::CheckType); + +void BTCheckVar::set_variable(String p_variable) { + variable = p_variable; + emit_changed(); +} + +void BTCheckVar::set_check_type(CheckType p_check_type) { + check_type = p_check_type; + emit_changed(); +} + +void BTCheckVar::set_value(Ref p_value) { + value = p_value; + emit_changed(); + if (Engine::get_singleton()->is_editor_hint() && value.is_valid()) { + value->connect(SNAME("changed"), Callable(this, SNAME("emit_changed"))); + } +} + +String BTCheckVar::get_configuration_warning() const { + String warning = BTCondition::get_configuration_warning(); + if (!warning.is_empty()) { + warning += "\n"; + } + if (variable.is_empty()) { + warning += "`variable` should be assigned.\n"; + } + if (!value.is_valid()) { + warning += "`value` should be assigned.\n"; + } + return warning; +} + +String BTCheckVar::_generate_name() const { + if (variable.is_empty()) { + return "CheckVar ???"; + } + + String check_str = "?"; + switch (check_type) { + case CheckType::CHECK_EQUAL: { + check_str = "=="; + } break; + case CheckType::CHECK_LESS_THAN: { + check_str = "<"; + } break; + case CheckType::CHECK_LESS_THAN_OR_EQUAL: { + check_str = "<="; + } break; + case CheckType::CHECK_GREATER_THAN: { + check_str = ">"; + } break; + case CheckType::CHECK_GREATER_THAN_OR_EQUAL: { + check_str = ">="; + } break; + case CheckType::CHECK_NOT_EQUAL: { + check_str = "!="; + } break; + } + + return vformat("Check if %s %s %s", LimboUtility::get_singleton()->decorate_var(variable), check_str, + value.is_valid() ? Variant(value) : Variant("???")); +} + +int BTCheckVar::_tick(double p_delta) { + ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BBCheckVar: `variable` is not set."); + ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BBCheckVar: `value` is not set."); + + ERR_FAIL_COND_V_MSG(!get_blackboard()->has_var(variable), FAILURE, vformat("BBCheckVar: Blackboard variable doesn't exist: \"%s\". Returning FAILURE.", variable)); + + Variant left_value = get_blackboard()->get_var(variable, Variant()); + Variant right_value = value->get_value(get_agent(), get_blackboard()); + + switch (check_type) { + case CheckType::CHECK_EQUAL: { + return Variant::evaluate(Variant::OP_EQUAL, left_value, right_value) ? SUCCESS : FAILURE; + } break; + case CheckType::CHECK_LESS_THAN: { + return Variant::evaluate(Variant::OP_LESS, left_value, right_value) ? SUCCESS : FAILURE; + } break; + case CheckType::CHECK_LESS_THAN_OR_EQUAL: { + return Variant::evaluate(Variant::OP_LESS_EQUAL, left_value, right_value) ? SUCCESS : FAILURE; + } break; + case CheckType::CHECK_GREATER_THAN: { + return Variant::evaluate(Variant::OP_GREATER, left_value, right_value) ? SUCCESS : FAILURE; + } break; + case CheckType::CHECK_GREATER_THAN_OR_EQUAL: { + return Variant::evaluate(Variant::OP_GREATER_EQUAL, left_value, right_value) ? SUCCESS : FAILURE; + } break; + case CheckType::CHECK_NOT_EQUAL: { + return Variant::evaluate(Variant::OP_NOT_EQUAL, left_value, right_value) ? SUCCESS : FAILURE; + } break; + default: { + return FAILURE; + } break; + } +} + +void BTCheckVar::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_variable", "p_variable"), &BTCheckVar::set_variable); + ClassDB::bind_method(D_METHOD("get_variable"), &BTCheckVar::get_variable); + ClassDB::bind_method(D_METHOD("set_check_type", "p_check_type"), &BTCheckVar::set_check_type); + ClassDB::bind_method(D_METHOD("get_check_type"), &BTCheckVar::get_check_type); + ClassDB::bind_method(D_METHOD("set_value", "p_value"), &BTCheckVar::set_value); + ClassDB::bind_method(D_METHOD("get_value"), &BTCheckVar::get_value); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "variable"), "set_variable", "get_variable"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "check_type", PROPERTY_HINT_ENUM, "Equal,Less Than,Less Than Or Equal,Greater Than,Greater Than Or Equal,Not Equal"), "set_check_type", "get_check_type"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "value", PROPERTY_HINT_RESOURCE_TYPE, "BBVariant"), "set_value", "get_value"); + + BIND_ENUM_CONSTANT(CHECK_EQUAL); + BIND_ENUM_CONSTANT(CHECK_LESS_THAN); + BIND_ENUM_CONSTANT(CHECK_LESS_THAN_OR_EQUAL); + BIND_ENUM_CONSTANT(CHECK_GREATER_THAN); + BIND_ENUM_CONSTANT(CHECK_GREATER_THAN_OR_EQUAL); + BIND_ENUM_CONSTANT(CHECK_NOT_EQUAL); +} diff --git a/bt/conditions/bt_check_var.h b/bt/conditions/bt_check_var.h new file mode 100644 index 0000000..a3f4c0e --- /dev/null +++ b/bt/conditions/bt_check_var.h @@ -0,0 +1,59 @@ +/** + * bt_check_var.h + * ============================================================================= + * 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. + * ============================================================================= + */ + +#ifndef BT_CHECK_VAR_H +#define BT_CHECK_VAR_H + +#include "bt_condition.h" + +#include "modules/limboai/blackboard/bb_param/bb_variant.h" + +#include "core/object/class_db.h" +#include "core/object/object.h" + +class BTCheckVar : public BTCondition { + GDCLASS(BTCheckVar, BTCondition); + +public: + enum CheckType : unsigned int { + CHECK_EQUAL, + CHECK_LESS_THAN, + CHECK_LESS_THAN_OR_EQUAL, + CHECK_GREATER_THAN, + CHECK_GREATER_THAN_OR_EQUAL, + CHECK_NOT_EQUAL + }; + +private: + String variable; + CheckType check_type = CheckType::CHECK_EQUAL; + Ref value; + +protected: + static void _bind_methods(); + + virtual String _generate_name() const override; + virtual int _tick(double p_delta) override; + +public: + virtual String get_configuration_warning() const override; + + void set_variable(String p_variable); + String get_variable() const { return variable; } + + void set_check_type(CheckType p_check_type); + CheckType get_check_type() const { return check_type; } + + void set_value(Ref p_value); + Ref get_value() const { return value; } +}; + +#endif // BT_CHECK_VAR_H \ No newline at end of file diff --git a/config.py b/config.py index bbfbd68..7dda1ba 100644 --- a/config.py +++ b/config.py @@ -60,6 +60,7 @@ def get_doc_classes(): "BTAction", "BTAlwaysFail", "BTAlwaysSucceed", + "BTCheckVar", "BTComposite", "BTCondition", "BTConsolePrint", diff --git a/icons/BTCheckVar.svg b/icons/BTCheckVar.svg new file mode 100644 index 0000000..150a4f2 --- /dev/null +++ b/icons/BTCheckVar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/register_types.cpp b/register_types.cpp index 29d77d2..5cec7d5 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -63,6 +63,7 @@ #include "bt/composites/bt_random_sequence.h" #include "bt/composites/bt_selector.h" #include "bt/composites/bt_sequence.h" +#include "bt/conditions/bt_check_var.h" #include "bt/conditions/bt_condition.h" #include "bt/decorators/bt_always_fail.h" #include "bt/decorators/bt_always_succeed.h" @@ -144,6 +145,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(BTWaitTicks); GDREGISTER_CLASS(BTCondition); + GDREGISTER_CLASS(BTCheckVar); GDREGISTER_ABSTRACT_CLASS(BBParam); GDREGISTER_CLASS(BBInt);