Add BTEvaluateExpression
This commit is contained in:
parent
8176d5c83c
commit
fb958c7c34
|
@ -0,0 +1,159 @@
|
||||||
|
/**
|
||||||
|
* bt_evaluate_expression.cpp
|
||||||
|
* =============================================================================
|
||||||
|
* Copyright 2021-2023 Serhii Snitsaruk
|
||||||
|
* Copyright 2024 Wilson E. Alvarez
|
||||||
|
*
|
||||||
|
* 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_evaluate_expression.h"
|
||||||
|
|
||||||
|
#include "../../../util/limbo_compat.h"
|
||||||
|
#include "../../../util/limbo_utility.h"
|
||||||
|
|
||||||
|
#ifdef LIMBOAI_GDEXTENSION
|
||||||
|
#include "godot_cpp/classes/global_constants.hpp"
|
||||||
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
|
//**** Setters / Getters
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_expression_string(const String &p_expression_string) {
|
||||||
|
expression_string = p_expression_string;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_node_param(Ref<BBNode> p_object) {
|
||||||
|
node_param = p_object;
|
||||||
|
emit_changed();
|
||||||
|
if (Engine::get_singleton()->is_editor_hint() && node_param.is_valid()) {
|
||||||
|
node_param->connect(LW_NAME(changed), Callable(this, LW_NAME(emit_changed)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_input_include_delta(bool p_input_include_delta) {
|
||||||
|
if (input_include_delta != p_input_include_delta) {
|
||||||
|
processed_input_values.resize(input_values.size() + int(p_input_include_delta));
|
||||||
|
}
|
||||||
|
input_include_delta = p_input_include_delta;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_input_names(const PackedStringArray &p_input_names) {
|
||||||
|
input_names = p_input_names;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_input_values(const TypedArray<BBVariant> &p_input_values) {
|
||||||
|
if (input_values.size() != p_input_values.size()) {
|
||||||
|
processed_input_values.resize(p_input_values.size() + int(input_include_delta));
|
||||||
|
}
|
||||||
|
input_values = p_input_values;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::set_result_var(const String &p_result_var) {
|
||||||
|
result_var = p_result_var;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
//**** Task Implementation
|
||||||
|
|
||||||
|
PackedStringArray BTEvaluateExpression::get_configuration_warnings() {
|
||||||
|
PackedStringArray warnings = BTAction::get_configuration_warnings();
|
||||||
|
if (expression_string.is_empty()) {
|
||||||
|
warnings.append("Expression string is not set.");
|
||||||
|
}
|
||||||
|
if (node_param.is_null()) {
|
||||||
|
warnings.append("Node parameter is not set.");
|
||||||
|
} else if (node_param->get_value_source() == BBParam::SAVED_VALUE && node_param->get_saved_value() == Variant()) {
|
||||||
|
warnings.append("Path to node is not set.");
|
||||||
|
} else if (node_param->get_value_source() == BBParam::BLACKBOARD_VAR && node_param->get_variable() == String()) {
|
||||||
|
warnings.append("Node blackboard variable is not set.");
|
||||||
|
}
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTEvaluateExpression::_setup() {
|
||||||
|
parse();
|
||||||
|
ERR_FAIL_COND_MSG(is_parsed != Error::OK, "BTEvaluateExpression: Failed to parse expression: " + expression.get_error_text());
|
||||||
|
}
|
||||||
|
|
||||||
|
Error BTEvaluateExpression::parse() {
|
||||||
|
PackedStringArray processed_input_names;
|
||||||
|
processed_input_names.resize(input_names.size() + int(input_include_delta));
|
||||||
|
String *processed_input_names_ptr = processed_input_names.ptrw();
|
||||||
|
if (input_include_delta) {
|
||||||
|
processed_input_names_ptr[0] = "delta";
|
||||||
|
}
|
||||||
|
for (int i = 0; i < input_names.size(); ++i) {
|
||||||
|
processed_input_names_ptr[i + int(input_include_delta)] = input_names[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
is_parsed = expression.parse(expression_string, processed_input_names);
|
||||||
|
return is_parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
String BTEvaluateExpression::_generate_name() {
|
||||||
|
return vformat("EvaluateExpression %s node: %s %s",
|
||||||
|
!expression_string.is_empty() ? expression_string : "???",
|
||||||
|
node_param.is_valid() && !node_param->to_string().is_empty() ? node_param->to_string() : "???",
|
||||||
|
result_var.is_empty() ? "" : LimboUtility::get_singleton()->decorate_output_var(result_var));
|
||||||
|
}
|
||||||
|
|
||||||
|
BT::Status BTEvaluateExpression::_tick(double p_delta) {
|
||||||
|
ERR_FAIL_COND_V_MSG(expression_string.is_empty(), FAILURE, "BTEvaluateExpression: Expression String is not set.");
|
||||||
|
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTEvaluateExpression: Node parameter is not set.");
|
||||||
|
Object *obj = node_param->get_value(get_agent(), get_blackboard());
|
||||||
|
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTEvaluateExpression: Failed to get object: " + node_param->to_string());
|
||||||
|
ERR_FAIL_COND_V_MSG(is_parsed != Error::OK, FAILURE, "BTEvaluateExpression: Failed to parse expression: " + expression.get_error_text());
|
||||||
|
|
||||||
|
if (input_include_delta) {
|
||||||
|
processed_input_values[0] = p_delta;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < input_values.size(); ++i) {
|
||||||
|
const Ref<BBVariant> &bb_variant = input_values[i];
|
||||||
|
processed_input_values[i + int(input_include_delta)] = bb_variant->get_value(get_agent(), get_blackboard());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant result = expression.execute(processed_input_values, obj, false);
|
||||||
|
ERR_FAIL_COND_V_MSG(expression.has_execute_failed(), FAILURE, "BTEvaluateExpression: Failed to execute: " + expression.get_error_text());
|
||||||
|
|
||||||
|
if (!result_var.is_empty()) {
|
||||||
|
get_blackboard()->set_var(result_var, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//**** Godot
|
||||||
|
|
||||||
|
void BTEvaluateExpression::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("parse"), &BTEvaluateExpression::parse);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_expression_string", "p_method"), &BTEvaluateExpression::set_expression_string);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_expression_string"), &BTEvaluateExpression::get_expression_string);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_node_param", "p_param"), &BTEvaluateExpression::set_node_param);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_node_param"), &BTEvaluateExpression::get_node_param);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_input_names", "p_input_names"), &BTEvaluateExpression::set_input_names);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_input_names"), &BTEvaluateExpression::get_input_names);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_input_values", "p_input_values"), &BTEvaluateExpression::set_input_values);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_input_values"), &BTEvaluateExpression::get_input_values);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_input_include_delta", "p_input_include_delta"), &BTEvaluateExpression::set_input_include_delta);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_input_delta_included"), &BTEvaluateExpression::is_input_delta_included);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_result_var", "p_result_var"), &BTEvaluateExpression::set_result_var);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_result_var"), &BTEvaluateExpression::get_result_var);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "BBNode"), "set_node_param", "get_node_param");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "expression_string"), "set_expression_string", "get_expression_string");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "result_var"), "set_result_var", "get_result_var");
|
||||||
|
ADD_GROUP("Inputs", "input_");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_include_delta"), "set_input_include_delta", "is_input_delta_included");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "input_names", PROPERTY_HINT_ARRAY_TYPE, "String"), "set_input_names", "get_input_names");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "input_values", PROPERTY_HINT_ARRAY_TYPE, RESOURCE_TYPE_HINT("BBVariant")), "set_input_values", "get_input_values");
|
||||||
|
}
|
||||||
|
|
||||||
|
BTEvaluateExpression::BTEvaluateExpression() {
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* bt_evaluate_expression.h
|
||||||
|
* =============================================================================
|
||||||
|
* Copyright 2021-2023 Serhii Snitsaruk
|
||||||
|
* Copyright 2024 Wilson E. Alvarez
|
||||||
|
*
|
||||||
|
* 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_EVALUATE_EXPRESSION_H
|
||||||
|
#define BT_EVALUATE_EXPRESSION_H
|
||||||
|
|
||||||
|
#include "../bt_action.h"
|
||||||
|
|
||||||
|
#ifdef LIMBOAI_MODULE
|
||||||
|
#include "core/math/expression.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LIMBOAI_GDEXTENSION
|
||||||
|
#include <godot_cpp/classes/expression.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../../blackboard/bb_param/bb_node.h"
|
||||||
|
#include "../../../blackboard/bb_param/bb_variant.h"
|
||||||
|
|
||||||
|
class BTEvaluateExpression : public BTAction {
|
||||||
|
GDCLASS(BTEvaluateExpression, BTAction);
|
||||||
|
TASK_CATEGORY(Utility);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expression expression;
|
||||||
|
Error is_parsed = FAILED;
|
||||||
|
Ref<BBNode> node_param;
|
||||||
|
String expression_string;
|
||||||
|
PackedStringArray input_names;
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
bool input_include_delta = false;
|
||||||
|
Array processed_input_values;
|
||||||
|
String result_var;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
virtual String _generate_name() override;
|
||||||
|
virtual void _setup() override;
|
||||||
|
virtual Status _tick(double p_delta) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Error parse();
|
||||||
|
|
||||||
|
void set_expression_string(const String &p_expression_string);
|
||||||
|
String get_expression_string() const { return expression_string; }
|
||||||
|
|
||||||
|
void set_node_param(Ref<BBNode> p_object);
|
||||||
|
Ref<BBNode> get_node_param() const { return node_param; }
|
||||||
|
|
||||||
|
void set_input_names(const PackedStringArray &p_input_names);
|
||||||
|
PackedStringArray get_input_names() const { return input_names; }
|
||||||
|
|
||||||
|
void set_input_values(const TypedArray<BBVariant> &p_input_values);
|
||||||
|
TypedArray<BBVariant> get_input_values() const { return input_values; }
|
||||||
|
|
||||||
|
void set_input_include_delta(bool p_input_include_delta);
|
||||||
|
bool is_input_delta_included() const { return input_include_delta; }
|
||||||
|
|
||||||
|
void set_result_var(const String &p_result_var);
|
||||||
|
String get_result_var() const { return result_var; }
|
||||||
|
|
||||||
|
virtual PackedStringArray get_configuration_warnings() override;
|
||||||
|
|
||||||
|
BTEvaluateExpression();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BT_EVALUATE_EXPRESSION_H
|
|
@ -68,6 +68,7 @@ def get_doc_classes():
|
||||||
"BTAlwaysSucceed",
|
"BTAlwaysSucceed",
|
||||||
"BTAwaitAnimation",
|
"BTAwaitAnimation",
|
||||||
"BTCallMethod",
|
"BTCallMethod",
|
||||||
|
"BTEvaluateExpression",
|
||||||
"BTCheckAgentProperty",
|
"BTCheckAgentProperty",
|
||||||
"BTCheckTrigger",
|
"BTCheckTrigger",
|
||||||
"BTCheckVar",
|
"BTCheckVar",
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<class name="BTEvaluateExpression" inherits="BTAction" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||||
|
<brief_description>
|
||||||
|
BT action that evaluates an [Expression] against a specified [Node] or [Object].
|
||||||
|
</brief_description>
|
||||||
|
<description>
|
||||||
|
BTEvaluateExpression action evaluates an [member expression_string] on the specified [Node] or [Object] instance and returns [code]SUCCESS[/code] when the [Expression] executes successfully.
|
||||||
|
Returns [code]FAILURE[/code] if the action encounters an issue during the [Expression] parsing or execution.
|
||||||
|
</description>
|
||||||
|
<tutorials>
|
||||||
|
</tutorials>
|
||||||
|
<methods>
|
||||||
|
<method name="parse">
|
||||||
|
<return type="int" enum="Error" />
|
||||||
|
<description>
|
||||||
|
Calls [method Expression.parse] considering [member input_include_delta] and [member input_names] and returns its error code.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<members>
|
||||||
|
<member name="expression_string" type="String" setter="set_expression_string" getter="get_expression_string" default="""">
|
||||||
|
The expression string to be parsed and executed.
|
||||||
|
[b]Warning:[/b] Call [method parse] after updating [member expression_string] to update the internal [Expression] as it won't be updated automatically.
|
||||||
|
</member>
|
||||||
|
<member name="input_include_delta" type="bool" setter="set_input_include_delta" getter="is_input_delta_included" default="false">
|
||||||
|
If enabled, the input variable [code]delta[/code] will be added to [member input_names] and [member input_values].
|
||||||
|
[b]Warning:[/b] Call [method parse] after toggling [member input_include_delta] to update the internal [Expression] as it won't be updated automatically.
|
||||||
|
</member>
|
||||||
|
<member name="input_names" type="PackedStringArray" setter="set_input_names" getter="get_input_names" default="PackedStringArray()">
|
||||||
|
List of variable names within [member expression_string] for which the user will provide values for through [member input_values].
|
||||||
|
[b]Warning:[/b] Call [method parse] after updating [member input_names] to update the internal [Expression] as it won't be updated automatically.
|
||||||
|
</member>
|
||||||
|
<member name="input_values" type="BBVariant[]" setter="set_input_values" getter="get_input_values" default="[]">
|
||||||
|
List of values for variables specified in [member input_names]. The values are mapped to the variables by their array index.
|
||||||
|
</member>
|
||||||
|
<member name="node" type="BBNode" setter="set_node_param" getter="get_node_param">
|
||||||
|
Specifies the [Node] or [Object] instance containing the method to be called.
|
||||||
|
</member>
|
||||||
|
<member name="result_var" type="String" setter="set_result_var" getter="get_result_var" default="""">
|
||||||
|
if non-empty, assign the result of the method call to the blackboard variable specified by this property.
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</class>
|
|
@ -90,6 +90,7 @@
|
||||||
#include "bt/tasks/scene/bt_stop_animation.h"
|
#include "bt/tasks/scene/bt_stop_animation.h"
|
||||||
#include "bt/tasks/utility/bt_call_method.h"
|
#include "bt/tasks/utility/bt_call_method.h"
|
||||||
#include "bt/tasks/utility/bt_console_print.h"
|
#include "bt/tasks/utility/bt_console_print.h"
|
||||||
|
#include "bt/tasks/utility/bt_evaluate_expression.h"
|
||||||
#include "bt/tasks/utility/bt_fail.h"
|
#include "bt/tasks/utility/bt_fail.h"
|
||||||
#include "bt/tasks/utility/bt_random_wait.h"
|
#include "bt/tasks/utility/bt_random_wait.h"
|
||||||
#include "bt/tasks/utility/bt_wait.h"
|
#include "bt/tasks/utility/bt_wait.h"
|
||||||
|
@ -182,6 +183,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
||||||
GDREGISTER_CLASS(BTCondition);
|
GDREGISTER_CLASS(BTCondition);
|
||||||
LIMBO_REGISTER_TASK(BTAwaitAnimation);
|
LIMBO_REGISTER_TASK(BTAwaitAnimation);
|
||||||
LIMBO_REGISTER_TASK(BTCallMethod);
|
LIMBO_REGISTER_TASK(BTCallMethod);
|
||||||
|
LIMBO_REGISTER_TASK(BTEvaluateExpression);
|
||||||
LIMBO_REGISTER_TASK(BTConsolePrint);
|
LIMBO_REGISTER_TASK(BTConsolePrint);
|
||||||
LIMBO_REGISTER_TASK(BTFail);
|
LIMBO_REGISTER_TASK(BTFail);
|
||||||
LIMBO_REGISTER_TASK(BTPauseAnimation);
|
LIMBO_REGISTER_TASK(BTPauseAnimation);
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/**
|
||||||
|
* test_evaluate_expression.h
|
||||||
|
* =============================================================================
|
||||||
|
* Copyright 2021-2023 Serhii Snitsaruk
|
||||||
|
* Copyright 2024 Wilson E. Alvarez
|
||||||
|
*
|
||||||
|
* 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 TEST_EVALUATE_EXPRESSION_H
|
||||||
|
#define TEST_EVALUATE_EXPRESSION_H
|
||||||
|
|
||||||
|
#include "limbo_test.h"
|
||||||
|
|
||||||
|
#include "modules/limboai/blackboard/bb_param/bb_node.h"
|
||||||
|
#include "modules/limboai/blackboard/blackboard.h"
|
||||||
|
#include "modules/limboai/bt/tasks/bt_task.h"
|
||||||
|
#include "modules/limboai/bt/tasks/utility/bt_evaluate_expression.h"
|
||||||
|
|
||||||
|
#include "core/os/memory.h"
|
||||||
|
#include "core/variant/array.h"
|
||||||
|
|
||||||
|
namespace TestEvaluateExpression {
|
||||||
|
|
||||||
|
TEST_CASE("[Modules][LimboAI] BTEvaluateExpression") {
|
||||||
|
Ref<BTEvaluateExpression> ee = memnew(BTEvaluateExpression);
|
||||||
|
|
||||||
|
SUBCASE("When node parameter is null") {
|
||||||
|
ee->set_node_param(nullptr);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("With object on the blackboard") {
|
||||||
|
Node *dummy = memnew(Node);
|
||||||
|
Ref<Blackboard> bb = memnew(Blackboard);
|
||||||
|
|
||||||
|
Ref<BBNode> node_param = memnew(BBNode);
|
||||||
|
ee->set_node_param(node_param);
|
||||||
|
Ref<CallbackCounter> callback_counter = memnew(CallbackCounter);
|
||||||
|
bb->set_var("object", callback_counter);
|
||||||
|
node_param->set_value_source(BBParam::BLACKBOARD_VAR);
|
||||||
|
node_param->set_variable("object");
|
||||||
|
ee->set_expression_string("callback()");
|
||||||
|
|
||||||
|
ee->initialize(dummy, bb);
|
||||||
|
|
||||||
|
SUBCASE("When expression string is empty") {
|
||||||
|
ee->set_expression_string("");
|
||||||
|
CHECK(ee->parse() == ERR_INVALID_PARAMETER);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
SUBCASE("When expression string calls non-existent function") {
|
||||||
|
ee->set_expression_string("not_found()");
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
SUBCASE("When expression string accesses a non-existent property") {
|
||||||
|
ee->set_expression_string("not_found");
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
SUBCASE("When expression string can't be parsed") {
|
||||||
|
ee->set_expression_string("assignment = failure");
|
||||||
|
CHECK(ee->parse() == ERR_INVALID_PARAMETER);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
}
|
||||||
|
SUBCASE("When expression is valid") {
|
||||||
|
ee->set_expression_string("callback()");
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 1);
|
||||||
|
}
|
||||||
|
SUBCASE("With inputs") {
|
||||||
|
ee->set_expression_string("callback_delta(delta)");
|
||||||
|
|
||||||
|
SUBCASE("Should fail with 0 inputs") {
|
||||||
|
ee->set_input_include_delta(false);
|
||||||
|
ee->set_input_names(PackedStringArray());
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
ee->set_input_values(TypedArray<BBVariant>());
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 0);
|
||||||
|
}
|
||||||
|
SUBCASE("Should succeed with too many inputs") {
|
||||||
|
ee->set_input_include_delta(true);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("point_two");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant(0.2)));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 1);
|
||||||
|
}
|
||||||
|
SUBCASE("Should fail with a wrong type arg") {
|
||||||
|
ee->set_input_include_delta(false);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("delta");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant("wrong data type")));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 1);
|
||||||
|
}
|
||||||
|
SUBCASE("Should succeed with delta included") {
|
||||||
|
ee->set_input_include_delta(true);
|
||||||
|
ee->set_input_names(PackedStringArray());
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
ee->set_input_values(TypedArray<BBVariant>());
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 1);
|
||||||
|
}
|
||||||
|
SUBCASE("Should succeed with one float arg") {
|
||||||
|
ee->set_input_include_delta(false);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("delta");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant(0.2)));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("Should fail with too many method arguments") {
|
||||||
|
ee->set_expression_string("callback_delta(delta, extra)");
|
||||||
|
ee->set_input_include_delta(true);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("point_two");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant(0.2)));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::FAILURE);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("When toggling input_include_delta") {
|
||||||
|
ee->set_expression_string("delta + extra");
|
||||||
|
ee->set_result_var("sum_result");
|
||||||
|
|
||||||
|
SUBCASE("Sum should be greater than 1 with input_include_delta set to false") {
|
||||||
|
ee->set_input_include_delta(false);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("delta");
|
||||||
|
input_names.push_back("extra");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant(0.01666)));
|
||||||
|
input_values.push_back(memnew(BBVariant(1)));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
CHECK(float(ee->get_blackboard()->get_var("sum_result", 0)) > 1);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("Sum should be greater than 1 with input_include_delta set to true") {
|
||||||
|
ee->set_input_include_delta(true);
|
||||||
|
PackedStringArray input_names;
|
||||||
|
input_names.push_back("extra");
|
||||||
|
ee->set_input_names(input_names);
|
||||||
|
CHECK(ee->parse() == OK);
|
||||||
|
TypedArray<BBVariant> input_values;
|
||||||
|
input_values.push_back(memnew(BBVariant(1)));
|
||||||
|
ee->set_input_values(input_values);
|
||||||
|
ERR_PRINT_OFF;
|
||||||
|
CHECK(ee->execute(0.01666) == BTTask::SUCCESS);
|
||||||
|
CHECK(float(ee->get_blackboard()->get_var("sum_result", 0)) > 1);
|
||||||
|
ERR_PRINT_ON;
|
||||||
|
CHECK(callback_counter->num_callbacks == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memdelete(dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace TestEvaluateExpression
|
||||||
|
|
||||||
|
#endif // TEST_EVALUATE_EXPRESSION_H
|
Loading…
Reference in New Issue