limboai/util/limbo_utility.cpp

357 lines
11 KiB
C++
Raw Normal View History

/**
* limbo_utility.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.
* =============================================================================
*/
2022-08-28 10:54:34 +00:00
#include "limbo_utility.h"
2023-07-20 16:35:36 +00:00
#ifdef LIMBOAI_MODULE
2023-08-15 15:49:13 +00:00
#include "modules/limboai/bt/tasks/bt_task.h"
2023-07-20 16:35:36 +00:00
#include "core/error/error_macros.h"
2023-10-28 11:09:03 +00:00
#include "core/object/script_language.h"
#include "core/variant/variant.h"
#include "scene/resources/texture.h"
2022-08-28 10:54:34 +00:00
2023-04-26 12:45:03 +00:00
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
#endif // TOOLS_ENABLED
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
#include "bt/tasks/bt_task.h"
#include <godot_cpp/core/error_macros.hpp>
#endif
2022-09-21 21:56:04 +00:00
LimboUtility *LimboUtility::singleton = nullptr;
LimboUtility *LimboUtility::get_singleton() {
return singleton;
}
2022-11-01 13:03:20 +00:00
String LimboUtility::decorate_var(String p_variable) const {
2022-09-21 21:56:04 +00:00
String var = p_variable.trim_prefix("$").trim_prefix("\"").trim_suffix("\"");
2023-07-28 22:35:47 +00:00
if (var.find(" ") == -1 && !var.is_empty()) {
2022-09-21 21:56:04 +00:00
return vformat("$%s", var);
} else {
return vformat("$\"%s\"", var);
2022-08-28 10:54:34 +00:00
}
}
2022-11-01 13:03:20 +00:00
String LimboUtility::get_status_name(int p_status) const {
switch (p_status) {
case BTTask::FRESH:
return "FRESH";
case BTTask::RUNNING:
return "RUNNING";
case BTTask::FAILURE:
return "FAILURE";
case BTTask::SUCCESS:
return "SUCCESS";
default:
return "";
}
}
Ref<Texture2D> LimboUtility::get_task_icon(String p_class_or_script_path) const {
2023-04-26 12:45:03 +00:00
#ifdef TOOLS_ENABLED
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();
ERR_FAIL_COND_V(theme.is_null(), nullptr);
if (p_class_or_script_path.begins_with("res:")) {
2023-07-20 18:10:02 +00:00
Ref<Script> s = ResourceLoader::load(p_class_or_script_path, "Script");
if (s.is_null()) {
return theme->get_icon(SNAME("FileBroken"), SNAME("EditorIcons"));
}
EditorData &ed = EditorNode::get_editor_data();
Ref<Texture2D> script_icon = ed.get_script_icon(s);
if (script_icon.is_valid()) {
return script_icon;
}
StringName base_type = s->get_instance_base_type();
if (theme->has_icon(base_type, SNAME("EditorIcons"))) {
return theme->get_icon(base_type, SNAME("EditorIcons"));
}
}
2023-08-09 13:38:24 +00:00
if (theme->has_icon(p_class_or_script_path, SNAME("EditorIcons"))) {
return theme->get_icon(p_class_or_script_path, SNAME("EditorIcons"));
2023-08-09 13:38:24 +00:00
}
// Use an icon of one of the base classes: look up max 3 parents.
StringName class_name = p_class_or_script_path;
for (int i = 0; i < 3; i++) {
class_name = ClassDB::get_parent_class(class_name);
if (theme->has_icon(class_name, SNAME("EditorIcons"))) {
return theme->get_icon(class_name, SNAME("EditorIcons"));
2023-08-09 13:38:24 +00:00
}
}
// Return generic resource icon as a fallback.
return theme->get_icon(SNAME("Resource"), SNAME("EditorIcons"));
2023-04-26 12:45:03 +00:00
#endif // TOOLS_ENABLED
2023-08-09 13:38:24 +00:00
// * Class icons are not available at runtime as they are part of the editor theme.
2023-04-26 12:45:03 +00:00
return nullptr;
}
String LimboUtility::get_check_operator_string(CheckType p_check_type) const {
2023-08-10 11:04:53 +00:00
switch (p_check_type) {
case LimboUtility::CheckType::CHECK_EQUAL: {
return "==";
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN: {
return "<";
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN_OR_EQUAL: {
return "<=";
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN: {
return ">";
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN_OR_EQUAL: {
return ">=";
} break;
case LimboUtility::CheckType::CHECK_NOT_EQUAL: {
return "!=";
} break;
default: {
return "?";
} break;
}
}
bool LimboUtility::perform_check(CheckType p_check_type, const Variant &left_value, const Variant &right_value) {
Variant ret;
#ifdef LIMBOAI_MODULE
switch (p_check_type) {
case LimboUtility::CheckType::CHECK_EQUAL: {
ret = Variant::evaluate(Variant::OP_EQUAL, left_value, right_value);
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN: {
ret = Variant::evaluate(Variant::OP_LESS, left_value, right_value);
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN_OR_EQUAL: {
ret = Variant::evaluate(Variant::OP_LESS_EQUAL, left_value, right_value);
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN: {
ret = Variant::evaluate(Variant::OP_GREATER, left_value, right_value);
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN_OR_EQUAL: {
ret = Variant::evaluate(Variant::OP_GREATER_EQUAL, left_value, right_value);
} break;
case LimboUtility::CheckType::CHECK_NOT_EQUAL: {
ret = Variant::evaluate(Variant::OP_NOT_EQUAL, left_value, right_value);
} break;
default: {
ret = false;
} break;
}
#endif
#ifdef LIMBOAI_GDEXTENSION
bool valid;
2023-08-10 11:04:53 +00:00
switch (p_check_type) {
case LimboUtility::CheckType::CHECK_EQUAL: {
Variant::evaluate(Variant::OP_LESS, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN: {
Variant::evaluate(Variant::OP_LESS, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
case LimboUtility::CheckType::CHECK_LESS_THAN_OR_EQUAL: {
Variant::evaluate(Variant::OP_LESS_EQUAL, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN: {
Variant::evaluate(Variant::OP_GREATER, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
case LimboUtility::CheckType::CHECK_GREATER_THAN_OR_EQUAL: {
Variant::evaluate(Variant::OP_GREATER_EQUAL, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
case LimboUtility::CheckType::CHECK_NOT_EQUAL: {
Variant::evaluate(Variant::OP_NOT_EQUAL, left_value, right_value, ret, valid);
2023-08-10 11:04:53 +00:00
} break;
default: {
return false;
} break;
}
#endif
return ret;
2023-08-10 11:04:53 +00:00
}
String LimboUtility::get_operation_string(Operation p_operation) const {
switch (p_operation) {
case OPERATION_NONE: {
return "";
} break;
case OPERATION_ADDITION: {
return "+";
} break;
case OPERATION_SUBTRACTION: {
return "-";
} break;
case OPERATION_MULTIPLICATION: {
return "*";
} break;
case OPERATION_DIVISION: {
return "/";
} break;
case OPERATION_MODULO: {
return "%";
} break;
case OPERATION_POWER: {
return "**";
} break;
case OPERATION_BIT_SHIFT_LEFT: {
return "<<";
} break;
case OPERATION_BIT_SHIFT_RIGHT: {
return ">>";
} break;
case OPERATION_BIT_AND: {
return "&";
} break;
case OPERATION_BIT_OR: {
return "|";
} break;
case OPERATION_BIT_XOR: {
return "^";
} break;
}
2023-11-19 15:26:00 +00:00
return "";
}
Variant LimboUtility::perform_operation(Operation p_operation, const Variant &left_value, const Variant &right_value) {
Variant ret;
#ifdef LIMBOAI_MODULE
switch (p_operation) {
case OPERATION_NONE: {
ret = right_value;
} break;
case OPERATION_ADDITION: {
ret = Variant::evaluate(Variant::OP_ADD, left_value, right_value);
} break;
case OPERATION_SUBTRACTION: {
ret = Variant::evaluate(Variant::OP_SUBTRACT, left_value, right_value);
} break;
case OPERATION_MULTIPLICATION: {
ret = Variant::evaluate(Variant::OP_MULTIPLY, left_value, right_value);
} break;
case OPERATION_DIVISION: {
ret = Variant::evaluate(Variant::OP_DIVIDE, left_value, right_value);
} break;
case OPERATION_MODULO: {
ret = Variant::evaluate(Variant::OP_MODULE, left_value, right_value);
} break;
case OPERATION_POWER: {
ret = Variant::evaluate(Variant::OP_POWER, left_value, right_value);
} break;
case OPERATION_BIT_SHIFT_LEFT: {
ret = Variant::evaluate(Variant::OP_SHIFT_LEFT, left_value, right_value);
} break;
case OPERATION_BIT_SHIFT_RIGHT: {
ret = Variant::evaluate(Variant::OP_SHIFT_RIGHT, left_value, right_value);
} break;
case OPERATION_BIT_AND: {
ret = Variant::evaluate(Variant::OP_BIT_AND, left_value, right_value);
} break;
case OPERATION_BIT_OR: {
ret = Variant::evaluate(Variant::OP_BIT_OR, left_value, right_value);
} break;
case OPERATION_BIT_XOR: {
ret = Variant::evaluate(Variant::OP_BIT_XOR, left_value, right_value);
} break;
}
#endif // LIMBOAI_MODULE
#ifdef LIMBOAI_GDEXTENSION
bool valid;
switch (p_operation) {
case OPERATION_NONE: {
ret = right_value;
} break;
case OPERATION_ADDITION: {
Variant::evaluate(Variant::OP_ADD, left_value, right_value, ret, valid);
} break;
case OPERATION_SUBTRACTION: {
Variant::evaluate(Variant::OP_SUBTRACT, left_value, right_value, ret, valid);
} break;
case OPERATION_MULTIPLICATION: {
Variant::evaluate(Variant::OP_MULTIPLY, left_value, right_value, ret, valid);
} break;
case OPERATION_DIVISION: {
Variant::evaluate(Variant::OP_DIVIDE, left_value, right_value, ret, valid);
} break;
case OPERATION_MODULO: {
Variant::evaluate(Variant::OP_MODULE, left_value, right_value, ret, valid);
} break;
// TODO: Uncomment when https://github.com/godotengine/godot-cpp/issues/1348 is fixed.
// case OPERATION_POWER: {
// Variant::evaluate(Variant::OP_POWER, left_value, right_value, ret, valid);
// } break;
case OPERATION_BIT_SHIFT_LEFT: {
Variant::evaluate(Variant::OP_SHIFT_LEFT, left_value, right_value, ret, valid);
} break;
case OPERATION_BIT_SHIFT_RIGHT: {
Variant::evaluate(Variant::OP_SHIFT_RIGHT, left_value, right_value, ret, valid);
} break;
case OPERATION_BIT_AND: {
Variant::evaluate(Variant::OP_BIT_AND, left_value, right_value, ret, valid);
} break;
case OPERATION_BIT_OR: {
Variant::evaluate(Variant::OP_BIT_OR, left_value, right_value, ret, valid);
} break;
case OPERATION_BIT_XOR: {
Variant::evaluate(Variant::OP_BIT_XOR, left_value, right_value, ret, valid);
} break;
}
#endif // LIMBOAI_GDEXTENSION
2023-11-19 15:26:00 +00:00
return Variant();
}
2022-08-28 10:54:34 +00:00
void LimboUtility::_bind_methods() {
2022-09-21 21:56:04 +00:00
ClassDB::bind_method(D_METHOD("decorate_var", "p_variable"), &LimboUtility::decorate_var);
2022-11-01 13:03:20 +00:00
ClassDB::bind_method(D_METHOD("get_status_name", "p_status"), &LimboUtility::get_status_name);
2023-07-20 20:15:30 +00:00
ClassDB::bind_method(D_METHOD("get_task_icon", "p_class_or_script_path"), &LimboUtility::get_task_icon);
2023-08-10 11:04:53 +00:00
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);
BIND_ENUM_CONSTANT(OPERATION_NONE);
BIND_ENUM_CONSTANT(OPERATION_ADDITION);
BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION);
BIND_ENUM_CONSTANT(OPERATION_MULTIPLICATION);
BIND_ENUM_CONSTANT(OPERATION_DIVISION);
BIND_ENUM_CONSTANT(OPERATION_MODULO);
BIND_ENUM_CONSTANT(OPERATION_POWER);
BIND_ENUM_CONSTANT(OPERATION_BIT_SHIFT_LEFT);
BIND_ENUM_CONSTANT(OPERATION_BIT_SHIFT_RIGHT);
BIND_ENUM_CONSTANT(OPERATION_BIT_AND);
BIND_ENUM_CONSTANT(OPERATION_BIT_OR);
BIND_ENUM_CONSTANT(OPERATION_BIT_XOR);
2022-09-21 21:56:04 +00:00
}
LimboUtility::LimboUtility() {
singleton = this;
}
LimboUtility::~LimboUtility() {
singleton = nullptr;
2022-08-28 10:54:34 +00:00
}