-
-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/** | ||
* bt_call_method.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_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(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_vars.resize(input_vars.size() + int(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_vars(Vector<String> p_input_vars) { | ||
if (input_vars.size() != p_input_vars.size()) { | ||
processed_input_vars.resize(p_input_vars.size() + int(input_include_delta)); | ||
} | ||
input_vars = p_input_vars; | ||
emit_changed(); | ||
} | ||
|
||
void BTEvaluateExpression::set_input_values(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() { | ||
ERR_FAIL_COND_MSG(expression_string == String(), "BTEvaluateExpression: Expression String is not set."); | ||
String *processed_input_vars_ptr = processed_input_vars.ptrw(); | ||
if (input_include_delta) { | ||
processed_input_vars_ptr[0] = "delta"; | ||
} | ||
for (int i = 0; i < input_vars.size(); ++i) { | ||
processed_input_vars_ptr[i] = input_vars[i]; | ||
} | ||
|
||
is_parsed = expression.parse(expression_string, processed_input_vars); | ||
ERR_FAIL_COND_MSG(is_parsed != Error::OK, "BTEvaluateExpression: Failed to parse expression: " + expression.get_error_text()); | ||
} | ||
|
||
String BTEvaluateExpression::_generate_name() { | ||
String input_vars_str = input_include_delta ? "delta" : ""; | ||
if (input_vars.size() > 0) { | ||
if (!input_vars_str.is_empty()) { | ||
input_vars_str += ", "; | ||
} | ||
input_vars_str += vformat("%s", input_vars).trim_prefix("[").trim_suffix("]").replace("\"", ""); | ||
} | ||
return vformat("EvaluateExpression %s with vars [%s] node: %s %s", | ||
expression_string != String() ? expression_string : "???", | ||
input_vars_str, | ||
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 == String(), 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 = int(input_include_delta); i < input_values.size(); ++i) { | ||
const Ref<BBVariant> &bb_variant = input_values[i]; | ||
processed_input_values[i] = 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("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_vars", "p_input_vars"), &BTEvaluateExpression::set_input_vars); | ||
ClassDB::bind_method(D_METHOD("get_input_vars"), &BTEvaluateExpression::get_input_vars); | ||
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_delta_included"), &BTEvaluateExpression::is_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_delta_included"); | ||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "input_vars", PROPERTY_HINT_ARRAY_TYPE, "String"), "set_input_vars", "get_input_vars"); | ||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "input_values", PROPERTY_HINT_ARRAY_TYPE, RESOURCE_TYPE_HINT("BBVariant")), "set_input_values", "get_input_values"); | ||
} | ||
|
||
BTEvaluateExpression::BTEvaluateExpression() { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/** | ||
* bt_call_method.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_EVALUATE_EXPRESSION_H | ||
#define BT_EVALUATE_EXPRESSION_H | ||
|
||
#include "../bt_action.h" | ||
#include "core/math/expression.h" | ||
|
||
#include "../../../blackboard/bb_param/bb_node.h" | ||
#include "../../../blackboard/bb_param/bb_string.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; | ||
Vector<String> input_vars; | ||
TypedArray<BBVariant> input_values; | ||
bool input_include_delta = false; | ||
Vector<String> processed_input_vars; | ||
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: | ||
void set_expression_string(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_vars(Vector<String> p_input_vars); | ||
Vector<String> get_input_vars() const { return input_vars; } | ||
|
||
void set_input_values(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_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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?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> | ||
<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 _setup] 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_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 _setup] after toggling [member input_include_delta] 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_vars]. The values are mapped to the variables by their array index. | ||
</member> | ||
<member name="input_vars" type="PackedStringArray" setter="set_input_vars" getter="get_input_vars" default="PackedStringArray()"> | ||
List of variables within the [member expression_string] for which the user will provide values for through [member input_values]. | ||
[b]Warning:[/b] Call [method _setup] after updating [member input_vars] to update the internal [Expression] as it won't be updated automatically. | ||
</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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters