Merge pull request #17 from limbonaut/callmethod-improvements

Improvements for the `CallMethod` task:
- Allow storing return value on the blackboard
- Allows specifying variables from the blackboard as arguments in additions to raw values.

Also, improvements to BBParam property editor to better utilize space in the inspector.

WARNING: Breaks compatibility if you are using `CallMethod` tasks. `CallMethod` arguments in existing trees will need to be reassigned!

Resolves #13
This commit is contained in:
Serhii Snitsaruk 2024-01-16 11:43:05 +01:00 committed by GitHub
commit 076269e5e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 172 additions and 51 deletions

View File

@ -39,5 +39,10 @@ void BBVariant::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, vtypes), "set_type", "get_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, vtypes), "set_type", "get_type");
} }
BBVariant::BBVariant(const Variant &p_value) {
set_type(p_value.get_type());
set_saved_value(p_value);
}
BBVariant::BBVariant() { BBVariant::BBVariant() {
} }

View File

@ -27,6 +27,7 @@ public:
virtual Variant::Type get_type() const override; virtual Variant::Type get_type() const override;
void set_type(Variant::Type p_type); void set_type(Variant::Type p_type);
BBVariant(const Variant &p_value);
BBVariant(); BBVariant();
}; };

View File

@ -12,6 +12,11 @@
#include "bt_call_method.h" #include "bt_call_method.h"
#include "../../../util/limbo_compat.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 //**** Setters / Getters
@ -33,11 +38,16 @@ void BTCallMethod::set_include_delta(bool p_include_delta) {
emit_changed(); emit_changed();
} }
void BTCallMethod::set_args(Array p_args) { void BTCallMethod::set_args(TypedArray<BBVariant> p_args) {
args = p_args; args = p_args;
emit_changed(); emit_changed();
} }
void BTCallMethod::set_result_var(const String &p_result_var) {
result_var = p_result_var;
emit_changed();
}
//**** Task Implementation //**** Task Implementation
PackedStringArray BTCallMethod::get_configuration_warnings() { PackedStringArray BTCallMethod::get_configuration_warnings() {
@ -63,10 +73,11 @@ String BTCallMethod::_generate_name() {
} }
args_str += vformat("%s", args).trim_prefix("[").trim_suffix("]"); args_str += vformat("%s", args).trim_prefix("[").trim_suffix("]");
} }
return vformat("CallMethod %s(%s) node: %s", return vformat("CallMethod %s(%s) node: %s %s",
(method != StringName() ? method : "???"), method != StringName() ? method : "???",
args_str, args_str,
(node_param.is_valid() && !node_param->to_string().is_empty() ? node_param->to_string() : "???")); node_param.is_valid() && !node_param->to_string().is_empty() ? node_param->to_string() : "???",
result_var.is_empty() ? "" : LW_NAME(output_var_prefix) + LimboUtility::get_singleton()->decorate_var(result_var));
} }
BT::Status BTCallMethod::_tick(double p_delta) { BT::Status BTCallMethod::_tick(double p_delta) {
@ -75,6 +86,9 @@ BT::Status BTCallMethod::_tick(double p_delta) {
Object *obj = node_param->get_value(get_agent(), get_blackboard()); Object *obj = node_param->get_value(get_agent(), get_blackboard());
ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTCallMethod: Failed to get object: " + node_param->to_string()); ERR_FAIL_COND_V_MSG(obj == nullptr, FAILURE, "BTCallMethod: Failed to get object: " + node_param->to_string());
Variant result;
Array call_args;
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
const Variant delta = include_delta ? Variant(p_delta) : Variant(); const Variant delta = include_delta ? Variant(p_delta) : Variant();
const Variant **argptrs = nullptr; const Variant **argptrs = nullptr;
@ -86,28 +100,34 @@ BT::Status BTCallMethod::_tick(double p_delta) {
argptrs[0] = &delta; argptrs[0] = &delta;
} }
for (int i = 0; i < args.size(); i++) { for (int i = 0; i < args.size(); i++) {
argptrs[i + int(include_delta)] = &args[i]; Ref<BBVariant> param = args[i];
call_args.push_back(param->get_value(get_agent(), get_blackboard()));
argptrs[i + int(include_delta)] = &call_args[i];
} }
} }
Callable::CallError ce; Callable::CallError ce;
obj->callp(method, argptrs, argument_count, ce); result = obj->callp(method, argptrs, argument_count, ce);
if (ce.error != Callable::CallError::CALL_OK) { if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(FAILURE, "BTCallMethod: Error calling method: " + Variant::get_call_error_text(obj, method, argptrs, argument_count, ce) + "."); ERR_FAIL_V_MSG(FAILURE, "BTCallMethod: Error calling method: " + Variant::get_call_error_text(obj, method, argptrs, argument_count, ce) + ".");
} }
#elif LIMBOAI_GDEXTENSION #elif LIMBOAI_GDEXTENSION
Array call_args;
if (include_delta) { if (include_delta) {
call_args.push_back(Variant(p_delta)); call_args.push_back(Variant(p_delta));
call_args.append_array(args); }
} else { for (int i = 0; i < args.size(); i++) {
call_args = args; Ref<BBVariant> param = args[i];
call_args.push_back(param->get_value(get_agent(), get_blackboard()));
} }
// TODO: Unsure how to detect call error, so we return SUCCESS for now... // TODO: Unsure how to detect call error, so we return SUCCESS for now...
obj->callv(method, call_args); result = obj->callv(method, call_args);
#endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION #endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION
if (!result_var.is_empty()) {
get_blackboard()->set_var(result_var, result);
}
return SUCCESS; return SUCCESS;
} }
@ -122,12 +142,15 @@ void BTCallMethod::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_args"), &BTCallMethod::get_args); ClassDB::bind_method(D_METHOD("get_args"), &BTCallMethod::get_args);
ClassDB::bind_method(D_METHOD("set_include_delta", "p_include_delta"), &BTCallMethod::set_include_delta); ClassDB::bind_method(D_METHOD("set_include_delta", "p_include_delta"), &BTCallMethod::set_include_delta);
ClassDB::bind_method(D_METHOD("is_delta_included"), &BTCallMethod::is_delta_included); ClassDB::bind_method(D_METHOD("is_delta_included"), &BTCallMethod::is_delta_included);
ClassDB::bind_method(D_METHOD("set_result_var", "p_result_var"), &BTCallMethod::set_result_var);
ClassDB::bind_method(D_METHOD("get_result_var"), &BTCallMethod::get_result_var);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "BBNode"), "set_node_param", "get_node_param"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "BBNode"), "set_node_param", "get_node_param");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "method"), "set_method", "get_method"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "method"), "set_method", "get_method");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "result_var"), "set_result_var", "get_result_var");
ADD_GROUP("Arguments", "args_"); ADD_GROUP("Arguments", "args_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "args_include_delta"), "set_include_delta", "is_delta_included"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "args_include_delta"), "set_include_delta", "is_delta_included");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "args"), "set_args", "get_args"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "args", PROPERTY_HINT_ARRAY_TYPE, RESOURCE_TYPE_HINT("BBVariant")), "set_args", "get_args");
// ADD_PROPERTY_DEFAULT("args_include_delta", false); // ADD_PROPERTY_DEFAULT("args_include_delta", false);
} }

View File

@ -15,6 +15,7 @@
#include "../bt_action.h" #include "../bt_action.h"
#include "../../../blackboard/bb_param/bb_node.h" #include "../../../blackboard/bb_param/bb_node.h"
#include "../../../blackboard/bb_param/bb_variant.h"
class BTCallMethod : public BTAction { class BTCallMethod : public BTAction {
GDCLASS(BTCallMethod, BTAction); GDCLASS(BTCallMethod, BTAction);
@ -23,8 +24,9 @@ class BTCallMethod : public BTAction {
private: private:
StringName method; StringName method;
Ref<BBNode> node_param; Ref<BBNode> node_param;
Array args; TypedArray<BBVariant> args;
bool include_delta = false; bool include_delta = false;
String result_var;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -39,12 +41,15 @@ public:
void set_node_param(Ref<BBNode> p_object); void set_node_param(Ref<BBNode> p_object);
Ref<BBNode> get_node_param() const { return node_param; } Ref<BBNode> get_node_param() const { return node_param; }
void set_args(Array p_args); void set_args(TypedArray<BBVariant> p_args);
Array get_args() const { return args; } TypedArray<BBVariant> get_args() const { return args; }
void set_include_delta(bool p_include_delta); void set_include_delta(bool p_include_delta);
bool is_delta_included() const { return include_delta; } bool is_delta_included() const { return 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; virtual PackedStringArray get_configuration_warnings() override;
BTCallMethod(); BTCallMethod();

View File

@ -114,9 +114,7 @@ Makes a copy of the BehaviorTree resource.
void **copy_other** **(** :ref:`BehaviorTree<class_BehaviorTree>` p_other **)** void **copy_other** **(** :ref:`BehaviorTree<class_BehaviorTree>` p_other **)**
.. container:: contribute Become a copy of another behavior tree.
There is currently no description for this method. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!
.. rst-class:: classref-item-separator .. rst-class:: classref-item-separator

View File

@ -31,15 +31,17 @@ Properties
.. table:: .. table::
:widths: auto :widths: auto
+-----------------------------+---------------------------------------------------------------------------+-----------+ +-------------------------------------+---------------------------------------------------------------------------+-----------+
| Array | :ref:`args<class_BTCallMethod_property_args>` | ``[]`` | | :ref:`BBVariant[]<class_BBVariant>` | :ref:`args<class_BTCallMethod_property_args>` | ``[]`` |
+-----------------------------+---------------------------------------------------------------------------+-----------+ +-------------------------------------+---------------------------------------------------------------------------+-----------+
| bool | :ref:`args_include_delta<class_BTCallMethod_property_args_include_delta>` | ``false`` | | bool | :ref:`args_include_delta<class_BTCallMethod_property_args_include_delta>` | ``false`` |
+-----------------------------+---------------------------------------------------------------------------+-----------+ +-------------------------------------+---------------------------------------------------------------------------+-----------+
| StringName | :ref:`method<class_BTCallMethod_property_method>` | ``&""`` | | StringName | :ref:`method<class_BTCallMethod_property_method>` | ``&""`` |
+-----------------------------+---------------------------------------------------------------------------+-----------+ +-------------------------------------+---------------------------------------------------------------------------+-----------+
| :ref:`BBNode<class_BBNode>` | :ref:`node<class_BTCallMethod_property_node>` | | | :ref:`BBNode<class_BBNode>` | :ref:`node<class_BTCallMethod_property_node>` | |
+-----------------------------+---------------------------------------------------------------------------+-----------+ +-------------------------------------+---------------------------------------------------------------------------+-----------+
| String | :ref:`result_var<class_BTCallMethod_property_result_var>` | ``""`` |
+-------------------------------------+---------------------------------------------------------------------------+-----------+
.. rst-class:: classref-section-separator .. rst-class:: classref-section-separator
@ -54,12 +56,12 @@ Property Descriptions
.. rst-class:: classref-property .. rst-class:: classref-property
Array **args** = ``[]`` :ref:`BBVariant[]<class_BBVariant>` **args** = ``[]``
.. rst-class:: classref-property-setget .. rst-class:: classref-property-setget
- void **set_args** **(** Array value **)** - void **set_args** **(** :ref:`BBVariant[]<class_BBVariant>` value **)**
- Array **get_args** **(** **)** - :ref:`BBVariant[]<class_BBVariant>` **get_args** **(** **)**
The arguments to be passed when calling the method. The arguments to be passed when calling the method.
@ -114,6 +116,23 @@ The name of the method to be called.
Specifies the ``Node`` or ``Object`` instance containing the method to be called. Specifies the ``Node`` or ``Object`` instance containing the method to be called.
.. rst-class:: classref-item-separator
----
.. _class_BTCallMethod_property_result_var:
.. rst-class:: classref-property
String **result_var** = ``""``
.. rst-class:: classref-property-setget
- void **set_result_var** **(** String value **)**
- String **get_result_var** **(** **)**
if non-empty, assign the result of the method call to the blackboard variable specified by this property.
.. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)` .. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`
.. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)` .. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`
.. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)` .. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)`

View File

@ -64,7 +64,7 @@ Methods
+-------------------------------+------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------+------------------------------------------------------------------------------------------------------------------------------+
| String | :ref:`_generate_name<class_BTTask_private_method__generate_name>` **(** **)** |virtual| |const| | | String | :ref:`_generate_name<class_BTTask_private_method__generate_name>` **(** **)** |virtual| |const| |
+-------------------------------+------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------+------------------------------------------------------------------------------------------------------------------------------+
| PackedStringArray | :ref:`_get_configuration_warning<class_BTTask_private_method__get_configuration_warning>` **(** **)** |virtual| |const| | | PackedStringArray | :ref:`_get_configuration_warnings<class_BTTask_private_method__get_configuration_warnings>` **(** **)** |virtual| |const| |
+-------------------------------+------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------+------------------------------------------------------------------------------------------------------------------------------+
| void | :ref:`_setup<class_BTTask_private_method__setup>` **(** **)** |virtual| | | void | :ref:`_setup<class_BTTask_private_method__setup>` **(** **)** |virtual| |
+-------------------------------+------------------------------------------------------------------------------------------------------------------------------+ +-------------------------------+------------------------------------------------------------------------------------------------------------------------------+
@ -249,11 +249,11 @@ Called to generate a display name for the task unless :ref:`custom_name<class_BT
---- ----
.. _class_BTTask_private_method__get_configuration_warning: .. _class_BTTask_private_method__get_configuration_warnings:
.. rst-class:: classref-method .. rst-class:: classref-method
PackedStringArray **_get_configuration_warning** **(** **)** |virtual| |const| PackedStringArray **_get_configuration_warnings** **(** **)** |virtual| |const|
The string returned by this method is shown as a warning message in the behavior tree editor. Any task script that overrides this method must include ``@tool`` annotation at the top of the file. The string returned by this method is shown as a warning message in the behavior tree editor. Any task script that overrides this method must include ``@tool`` annotation at the top of the file.

View File

@ -10,7 +10,7 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<members> <members>
<member name="args" type="Array" setter="set_args" getter="get_args" default="[]"> <member name="args" type="BBVariant[]" setter="set_args" getter="get_args" default="[]">
The arguments to be passed when calling the method. The arguments to be passed when calling the method.
</member> </member>
<member name="args_include_delta" type="bool" setter="set_include_delta" getter="is_delta_included" default="false"> <member name="args_include_delta" type="bool" setter="set_include_delta" getter="is_delta_included" default="false">
@ -22,5 +22,8 @@
<member name="node" type="BBNode" setter="set_node_param" getter="get_node_param"> <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. Specifies the [Node] or [Object] instance containing the method to be called.
</member> </member>
<member name="result_var" type="String" setter="set_result_var" getter="get_result_var" default="&quot;&quot;">
if non-empty, assign the result of the method call to the blackboard variable specified by this property.
</member>
</members> </members>
</class> </class>

View File

@ -31,7 +31,7 @@
Called to generate a display name for the task unless [member custom_name] is set. See [method get_task_name]. Called to generate a display name for the task unless [member custom_name] is set. See [method get_task_name].
</description> </description>
</method> </method>
<method name="_get_configuration_warning" qualifiers="virtual const"> <method name="_get_configuration_warnings" qualifiers="virtual const">
<return type="PackedStringArray" /> <return type="PackedStringArray" />
<description> <description>
The string returned by this method is shown as a warning message in the behavior tree editor. Any task script that overrides this method must include [code]@tool[/code] annotation at the top of the file. The string returned by this method is shown as a warning message in the behavior tree editor. Any task script that overrides this method must include [code]@tool[/code] annotation at the top of the file.
@ -126,7 +126,7 @@
Returns the root task of the behavior tree. Returns the root task of the behavior tree.
</description> </description>
</method> </method>
<method name="get_task_name" qualifiers="const"> <method name="get_task_name">
<return type="String" /> <return type="String" />
<description> <description>
The string returned by this method is used to represent the task in the editor. The string returned by this method is used to represent the task in the editor.
@ -169,7 +169,7 @@
Returns [code]null[/code] if this task has no parent or it is the last child in the parent's children list. Returns [code]null[/code] if this task has no parent or it is the last child in the parent's children list.
</description> </description>
</method> </method>
<method name="print_tree" qualifiers="const"> <method name="print_tree">
<return type="void" /> <return type="void" />
<param index="0" name="p_initial_tabs" type="int" default="0" /> <param index="0" name="p_initial_tabs" type="int" default="0" />
<description> <description>

View File

@ -21,6 +21,13 @@
Makes a copy of the BehaviorTree resource. Makes a copy of the BehaviorTree resource.
</description> </description>
</method> </method>
<method name="copy_other">
<return type="void" />
<param index="0" name="p_other" type="BehaviorTree" />
<description>
Become a copy of another behavior tree.
</description>
</method>
<method name="get_root_task" qualifiers="const"> <method name="get_root_task" qualifiers="const">
<return type="BTTask" /> <return type="BTTask" />
<description> <description>

View File

@ -15,7 +15,6 @@
#include "editor_property_bb_param.h" #include "editor_property_bb_param.h"
#include "core/variant/variant.h"
#include "modules/limboai/blackboard/bb_param/bb_param.h" #include "modules/limboai/blackboard/bb_param/bb_param.h"
#include "modules/limboai/blackboard/bb_param/bb_variant.h" #include "modules/limboai/blackboard/bb_param/bb_variant.h"
#include "modules/limboai/editor/mode_switch_button.h" #include "modules/limboai/editor/mode_switch_button.h"
@ -23,9 +22,11 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/io/marshalls.h" #include "core/io/marshalls.h"
#include "core/object/class_db.h" #include "core/object/class_db.h"
#include "core/object/object.h"
#include "core/object/ref_counted.h" #include "core/object/ref_counted.h"
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "core/variant/variant.h"
#include "editor/editor_inspector.h" #include "editor/editor_inspector.h"
#include "editor/editor_properties.h" #include "editor/editor_properties.h"
#include "editor/editor_properties_array_dict.h" #include "editor/editor_properties_array_dict.h"
@ -55,6 +56,8 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
_remove_value_editor(); _remove_value_editor();
} }
bool is_bottom = false;
switch (p_type) { switch (p_type) {
case Variant::NIL: { case Variant::NIL: {
value_editor = memnew(EditorPropertyNil); value_editor = memnew(EditorPropertyNil);
@ -78,6 +81,7 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
} else { } else {
value_editor = memnew(EditorPropertyText); value_editor = memnew(EditorPropertyText);
} }
is_bottom = (property_hint == PROPERTY_HINT_MULTILINE_TEXT);
} break; } break;
case Variant::VECTOR2: { case Variant::VECTOR2: {
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2); EditorPropertyVector2 *editor = memnew(EditorPropertyVector2);
@ -93,66 +97,79 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2); EditorPropertyRect2 *editor = memnew(EditorPropertyRect2);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::RECT2I: { case Variant::RECT2I: {
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i); EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i);
editor->setup(-100000, 100000); editor->setup(-100000, 100000);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::VECTOR3: { case Variant::VECTOR3: {
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3); EditorPropertyVector3 *editor = memnew(EditorPropertyVector3);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::VECTOR3I: { case Variant::VECTOR3I: {
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i); EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i);
editor->setup(-100000, 100000); editor->setup(-100000, 100000);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::VECTOR4: { case Variant::VECTOR4: {
EditorPropertyVector4 *editor = memnew(EditorPropertyVector4); EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::VECTOR4I: { case Variant::VECTOR4I: {
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i); EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
editor->setup(-100000, 100000); editor->setup(-100000, 100000);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::TRANSFORM2D: { case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::PLANE: { case Variant::PLANE: {
EditorPropertyPlane *editor = memnew(EditorPropertyPlane); EditorPropertyPlane *editor = memnew(EditorPropertyPlane);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::QUATERNION: { case Variant::QUATERNION: {
EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion); EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::AABB: { case Variant::AABB: {
EditorPropertyAABB *editor = memnew(EditorPropertyAABB); EditorPropertyAABB *editor = memnew(EditorPropertyAABB);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::BASIS: { case Variant::BASIS: {
EditorPropertyBasis *editor = memnew(EditorPropertyBasis); EditorPropertyBasis *editor = memnew(EditorPropertyBasis);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::TRANSFORM3D: { case Variant::TRANSFORM3D: {
EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D); EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::PROJECTION: { case Variant::PROJECTION: {
EditorPropertyProjection *editor = memnew(EditorPropertyProjection); EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true); editor->setup(-100000, 100000, EDITOR_GET("interface/inspector/default_float_step"), true);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::COLOR: { case Variant::COLOR: {
value_editor = memnew(EditorPropertyColor); value_editor = memnew(EditorPropertyColor);
@ -161,6 +178,7 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
EditorPropertyText *editor = memnew(EditorPropertyText); EditorPropertyText *editor = memnew(EditorPropertyText);
editor->set_string_name(true); editor->set_string_name(true);
value_editor = editor; value_editor = editor;
is_bottom = (property_hint == PROPERTY_HINT_MULTILINE_TEXT);
} break; } break;
case Variant::NODE_PATH: { case Variant::NODE_PATH: {
value_editor = memnew(EditorPropertyNodePath); value_editor = memnew(EditorPropertyNodePath);
@ -176,9 +194,11 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
EditorPropertyResource *editor = memnew(EditorPropertyResource); EditorPropertyResource *editor = memnew(EditorPropertyResource);
editor->setup(_get_edited_param().ptr(), SNAME("saved_value"), "Resource"); editor->setup(_get_edited_param().ptr(), SNAME("saved_value"), "Resource");
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
case Variant::DICTIONARY: { case Variant::DICTIONARY: {
value_editor = memnew(EditorPropertyDictionary); value_editor = memnew(EditorPropertyDictionary);
is_bottom = true;
} break; } break;
case Variant::ARRAY: case Variant::ARRAY:
@ -194,6 +214,7 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
EditorPropertyArray *editor = memnew(EditorPropertyArray); EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(p_type); editor->setup(p_type);
value_editor = editor; value_editor = editor;
is_bottom = true;
} break; } break;
default: { default: {
@ -202,15 +223,25 @@ void EditorPropertyBBParam::_create_value_editor(Variant::Type p_type) {
} }
} }
value_editor->set_name_split_ratio(0.0); value_editor->set_name_split_ratio(0.0);
editor_hbox->add_child(value_editor); value_editor->set_use_folding(is_using_folding());
value_editor->set_selectable(false);
value_editor->set_h_size_flags(SIZE_EXPAND_FILL); value_editor->set_h_size_flags(SIZE_EXPAND_FILL);
value_editor->set_meta(SNAME("_param_type"), p_type); value_editor->set_meta(SNAME("_param_type"), p_type);
value_editor->connect(SNAME("property_changed"), callable_mp(this, &EditorPropertyBBParam::_value_edited)); value_editor->connect(SNAME("property_changed"), callable_mp(this, &EditorPropertyBBParam::_value_edited));
if (is_bottom) {
bottom_container->add_child(value_editor);
set_bottom_editor(bottom_container);
bottom_container->show();
} else {
set_bottom_editor(nullptr);
editor_hbox->add_child(value_editor);
bottom_container->hide();
}
} }
void EditorPropertyBBParam::_remove_value_editor() { void EditorPropertyBBParam::_remove_value_editor() {
if (value_editor) { if (value_editor) {
editor_hbox->remove_child(value_editor); value_editor->get_parent()->remove_child(value_editor);
value_editor->queue_free(); value_editor->queue_free();
value_editor = nullptr; value_editor = nullptr;
} }
@ -245,15 +276,15 @@ void EditorPropertyBBParam::update_property() {
variable_edit->set_text(param->get_variable()); variable_edit->set_text(param->get_variable());
variable_edit->set_editable(true); variable_edit->set_editable(true);
variable_edit->show(); variable_edit->show();
mode_button->set_mode(Mode::BIND_VAR, true); mode_button->call_deferred(SNAME("set_mode"), Mode::BIND_VAR, true);
type_choice->hide(); type_choice->hide();
} else { } else {
variable_edit->hide();
_create_value_editor(param->get_type()); _create_value_editor(param->get_type());
variable_edit->hide();
value_editor->show(); value_editor->show();
value_editor->set_object_and_property(param.ptr(), SNAME("saved_value")); value_editor->set_object_and_property(param.ptr(), SNAME("saved_value"));
mode_button->set_mode(Mode::SPECIFY_VALUE, true);
value_editor->update_property(); value_editor->update_property();
mode_button->call_deferred(SNAME("set_mode"), Mode::SPECIFY_VALUE, true);
type_choice->set_visible(is_variant_param); type_choice->set_visible(is_variant_param);
} }
@ -308,6 +339,10 @@ EditorPropertyBBParam::EditorPropertyBBParam() {
add_child(hbox); add_child(hbox);
hbox->add_theme_constant_override(SNAME("separation"), 0); hbox->add_theme_constant_override(SNAME("separation"), 0);
bottom_container = memnew(MarginContainer);
bottom_container->set_theme_type_variation("MarginContainer4px");
add_child(bottom_container);
mode_button = memnew(ModeSwitchButton); mode_button = memnew(ModeSwitchButton);
hbox->add_child(mode_button); hbox->add_child(mode_button);
mode_button->set_focus_mode(FOCUS_NONE); mode_button->set_focus_mode(FOCUS_NONE);

View File

@ -22,6 +22,7 @@
#include "modules/limboai/editor/mode_switch_button.h" #include "modules/limboai/editor/mode_switch_button.h"
#include "scene/gui/box_container.h" #include "scene/gui/box_container.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/menu_button.h" #include "scene/gui/menu_button.h"
class EditorPropertyBBParam : public EditorProperty { class EditorPropertyBBParam : public EditorProperty {
@ -38,6 +39,7 @@ private:
Mode mode = Mode::SPECIFY_VALUE; Mode mode = Mode::SPECIFY_VALUE;
HBoxContainer *hbox = nullptr; HBoxContainer *hbox = nullptr;
MarginContainer *bottom_container = nullptr;
HBoxContainer *editor_hbox = nullptr; HBoxContainer *editor_hbox = nullptr;
ModeSwitchButton *mode_button = nullptr; ModeSwitchButton *mode_button = nullptr;
EditorProperty *value_editor = nullptr; EditorProperty *value_editor = nullptr;

21
gdextension/update_rst.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
usage () { echo -e "Usage: Call from the Godot source root to update LimboAI rst class documentation."; }
msg () { echo -e "$@"; }
set -e
if [ ! -d "${PWD}/modules/limboai" ]; then
usage
exit 1
fi
rm -rf /tmp/rst
./doc/tools/make_rst.py --output /tmp/rst doc/tools doc/classes/@GlobalScope.xml modules/limboai/doc_classes || /bin/true
msg Removing old rst class documentation...
rm ./modules/limboai/doc/source/classes/class_*
msg Copying new rst class documentation...
cp -r -f /tmp/rst/class_* modules/limboai/doc/source/classes/
msg Cleaning up...
rm modules/limboai/doc/source/classes/class_@globalscope.rst
msg Done!

View File

@ -70,7 +70,7 @@ TEST_CASE("[Modules][LimboAI] BTCallMethod") {
SUBCASE("Should fail with 0 arguments") { SUBCASE("Should fail with 0 arguments") {
cm->set_include_delta(false); cm->set_include_delta(false);
cm->set_args(Array()); cm->set_args(TypedArray<BBVariant>());
ERR_PRINT_OFF; ERR_PRINT_OFF;
CHECK(cm->execute(0.01666) == BTTask::FAILURE); CHECK(cm->execute(0.01666) == BTTask::FAILURE);
ERR_PRINT_ON; ERR_PRINT_ON;
@ -78,8 +78,8 @@ TEST_CASE("[Modules][LimboAI] BTCallMethod") {
} }
SUBCASE("Should fail with too many arguments") { SUBCASE("Should fail with too many arguments") {
cm->set_include_delta(true); cm->set_include_delta(true);
Array args; TypedArray<BBVariant> args;
args.push_back(0.2); args.push_back(memnew(BBVariant(0.2)));
cm->set_args(args); cm->set_args(args);
ERR_PRINT_OFF; ERR_PRINT_OFF;
CHECK(cm->execute(0.01666) == BTTask::FAILURE); CHECK(cm->execute(0.01666) == BTTask::FAILURE);
@ -88,8 +88,8 @@ TEST_CASE("[Modules][LimboAI] BTCallMethod") {
} }
SUBCASE("Should fail with a wrong type arg") { SUBCASE("Should fail with a wrong type arg") {
cm->set_include_delta(false); cm->set_include_delta(false);
Array args; TypedArray<BBVariant> args;
args.push_back("wrong_data"); args.push_back(memnew(BBVariant("wrong data type")));
cm->set_args(args); cm->set_args(args);
ERR_PRINT_OFF; ERR_PRINT_OFF;
CHECK(cm->execute(0.01666) == BTTask::FAILURE); CHECK(cm->execute(0.01666) == BTTask::FAILURE);
@ -98,14 +98,13 @@ TEST_CASE("[Modules][LimboAI] BTCallMethod") {
} }
SUBCASE("Should succeed with delta included") { SUBCASE("Should succeed with delta included") {
cm->set_include_delta(true); cm->set_include_delta(true);
cm->set_args(Array());
CHECK(cm->execute(0.01666) == BTTask::SUCCESS); CHECK(cm->execute(0.01666) == BTTask::SUCCESS);
CHECK(callback_counter->num_callbacks == 1); CHECK(callback_counter->num_callbacks == 1);
} }
SUBCASE("Should succeed with one float arg") { SUBCASE("Should succeed with one float arg") {
cm->set_include_delta(false); cm->set_include_delta(false);
Array args; TypedArray<BBVariant> args;
args.push_back(0.2); args.push_back(memnew(BBVariant(0.2)));
cm->set_args(args); cm->set_args(args);
CHECK(cm->execute(0.01666) == BTTask::SUCCESS); CHECK(cm->execute(0.01666) == BTTask::SUCCESS);
CHECK(callback_counter->num_callbacks == 1); CHECK(callback_counter->num_callbacks == 1);

View File

@ -170,6 +170,7 @@ inline void VARIANT_DELETE_IF_OBJECT(Variant m_variant) {
#define PROJECT_CONFIG_FILE() GET_PROJECT_SETTINGS_DIR().path_join("limbo_ai.cfg") #define PROJECT_CONFIG_FILE() GET_PROJECT_SETTINGS_DIR().path_join("limbo_ai.cfg")
#define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1) #define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1)
#define RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED

View File

@ -136,4 +136,5 @@ LimboStringNames::LimboStringNames() {
EVENT_FINISHED = "finished"; EVENT_FINISHED = "finished";
repeat_forever.parse_utf8("Repeat ∞"); repeat_forever.parse_utf8("Repeat ∞");
output_var_prefix.parse_utf8("");
} }

View File

@ -151,6 +151,7 @@ public:
String EVENT_FINISHED; String EVENT_FINISHED;
String repeat_forever; String repeat_forever;
String output_var_prefix;
}; };
#define LW_NAME(m_arg) LimboStringNames::get_singleton()->m_arg #define LW_NAME(m_arg) LimboStringNames::get_singleton()->m_arg