From 57ce55540b4ecd36ea0668a410b9040c00f3062a Mon Sep 17 00:00:00 2001 From: Chris Cranford Date: Wed, 24 Apr 2024 16:26:48 -0400 Subject: [PATCH] GH-283 Support method chaining --- src/script/nodes/functions/call_function.cpp | 45 ++++++++++++++++---- src/script/nodes/functions/call_function.h | 2 + 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/script/nodes/functions/call_function.cpp b/src/script/nodes/functions/call_function.cpp index 5b228a06..e393868f 100644 --- a/src/script/nodes/functions/call_function.cpp +++ b/src/script/nodes/functions/call_function.cpp @@ -33,7 +33,8 @@ class OScriptNodeCallFunctionInstance : public OScriptNodeInstance Object* _owner{ nullptr }; int _argument_count{ 0 }; int _argument_offset{ 2 }; - bool _pure = false; + bool _pure{ false }; + bool _chained{ false }; Array _args; int _do_pure(OScriptNodeExecutionContext& p_context) const @@ -139,10 +140,14 @@ class OScriptNodeCallFunctionInstance : public OScriptNodeInstance { Variant result = instance->callv(_function_name, _args); p_context.set_output(0, result); + if (_chained) + p_context.set_output(1, p_context.get_input(0)); } else { instance->callv(_function_name, _args); + if (_chained) + p_context.set_output(0, p_context.get_input(0)); } return 0; } @@ -161,22 +166,22 @@ void OScriptNodeCallFunction::_bind_methods() void OScriptNodeCallFunction::_get_property_list(List* r_list) const { - int32_t read_only_serialize = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY; - int32_t read_only_editor = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY; - r_list->push_back(PropertyInfo(Variant::STRING, "guid", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); - r_list->push_back(PropertyInfo(Variant::STRING, "function_name", PROPERTY_HINT_NONE, "", read_only_editor)); - r_list->push_back(PropertyInfo(Variant::STRING_NAME, "target_class_name", PROPERTY_HINT_NONE, "", read_only_serialize)); - r_list->push_back(PropertyInfo(Variant::INT, "target_type", PROPERTY_HINT_NONE, "", read_only_serialize)); + r_list->push_back(PropertyInfo(Variant::STRING, "function_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + r_list->push_back(PropertyInfo(Variant::STRING_NAME, "target_class_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + r_list->push_back(PropertyInfo(Variant::INT, "target_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); const String flags = "Pure,Const,Is Bead,Is Self,Virtual,VarArg,Static,Object Core,Editor"; - r_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, flags, read_only_serialize)); + r_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, flags, PROPERTY_USAGE_STORAGE)); if (_is_method_info_serialized()) r_list->push_back(PropertyInfo(Variant::DICTIONARY, "method", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); if (_reference.method.flags & METHOD_FLAG_VARARG) r_list->push_back(PropertyInfo(Variant::INT, "variable_arg_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + + if (_chainable) + r_list->push_back(PropertyInfo(Variant::BOOL, "chain")); } bool OScriptNodeCallFunction::_get(const StringName& p_name, Variant& r_value) const @@ -216,6 +221,11 @@ bool OScriptNodeCallFunction::_get(const StringName& p_name, Variant& r_value) c r_value = _vararg_count; return true; } + else if (p_name.match("chain")) + { + r_value = _chain; + return true; + } return false; } @@ -253,6 +263,12 @@ bool OScriptNodeCallFunction::_set(const StringName& p_name, const Variant& p_va _notify_pins_changed(); return true; } + else if (p_name.match("chain")) + { + _chain = p_value; + _notify_pins_changed(); + return true; + } return false; } @@ -264,6 +280,7 @@ void OScriptNodeCallFunction::_create_pins_for_method(const MethodInfo& p_method create_pin(PD_Output, "ExecOut")->set_flags(OScriptNodePin::Flags::EXECUTION); } + _chainable = false; if (get_argument_offset() != 0) { Variant::Type target_type = _reference.target_type != Variant::NIL ? _reference.target_type : Variant::OBJECT; @@ -275,6 +292,9 @@ void OScriptNodeCallFunction::_create_pins_for_method(const MethodInfo& p_method target->set_target_class(get_owning_script()->get_base_type()); else target->set_target_class("Object"); + + _chainable = true; + notify_property_list_changed(); } } @@ -326,6 +346,14 @@ void OScriptNodeCallFunction::_create_pins_for_method(const MethodInfo& p_method rv->set_flags(OScriptNodePin::Flags::DATA); rv->set_target_class(p_method.return_val.class_name); } + + if (_chainable && _chain) + { + Ref chain = create_pin(PD_Output, "return_target", Variant::OBJECT); + chain->set_flags(OScriptNodePin::Flags::DATA); + chain->set_label("Target"); + chain->set_target_class(find_pin("target", PD_Input)->get_target_class()); + } } bool OScriptNodeCallFunction::_has_execution_pins(const MethodInfo& p_method) const @@ -412,6 +440,7 @@ OScriptNodeInstance* OScriptNodeCallFunction::instantiate(OScriptInstance* p_ins i->_reference = _reference; i->_function_name = _reference.name; i->_pure = _function_flags.has_flag(FF_PURE); + i->_chained = _chain; return i; } diff --git a/src/script/nodes/functions/call_function.h b/src/script/nodes/functions/call_function.h index 9dad0078..f02954ed 100644 --- a/src/script/nodes/functions/call_function.h +++ b/src/script/nodes/functions/call_function.h @@ -70,6 +70,8 @@ class OScriptNodeCallFunction : public OScriptNode BitField _function_flags{ FF_NONE }; //! Function flags OScriptFunctionReference _reference; //! Function reference int _vararg_count{ 0 }; //! Variable argument count + bool _chain{ false }; //! If the node should chain function calls + bool _chainable{ false }; //! Whether the node is chainable //~ Begin Wrapped Interface void _get_property_list(List* r_list) const;