diff options
Diffstat (limited to 'modules/visual_script')
25 files changed, 1548 insertions, 2146 deletions
diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml index db1ef2adc6..5112ea43a7 100644 --- a/modules/visual_script/doc_classes/VisualScript.xml +++ b/modules/visual_script/doc_classes/VisualScript.xml @@ -9,7 +9,7 @@ You are most likely to use this class via the Visual Script editor or when writing plugins for it. </description> <tutorials> - <link>https://docs.godotengine.org/en/latest/getting_started/scripting/visual_script/index.html</link> + <link title="VisualScript tutorial index">https://docs.godotengine.org/en/latest/getting_started/scripting/visual_script/index.html</link> </tutorials> <methods> <method name="add_custom_signal"> @@ -26,23 +26,23 @@ </return> <argument index="0" name="name" type="StringName"> </argument> + <argument index="1" name="func_node_id" type="int"> + </argument> <description> - Add a function with the specified name to the VisualScript. + Add a function with the specified name to the VisualScript, and assign the root [VisualScriptFunction] node's id as [code]func_node_id[/code]. </description> </method> <method name="add_node"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> - <argument index="2" name="node" type="VisualScriptNode"> + <argument index="1" name="node" type="VisualScriptNode"> </argument> - <argument index="3" name="position" type="Vector2" default="Vector2( 0, 0 )"> + <argument index="2" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> - Add a node to a function of the VisualScript. + Add a node to the VisualScript. </description> </method> <method name="add_variable"> @@ -157,15 +157,13 @@ <method name="data_connect"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="from_node" type="int"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="2" name="from_port" type="int"> + <argument index="1" name="from_port" type="int"> </argument> - <argument index="3" name="to_node" type="int"> + <argument index="2" name="to_node" type="int"> </argument> - <argument index="4" name="to_port" type="int"> + <argument index="3" name="to_port" type="int"> </argument> <description> Connect two data ports. The value of [code]from_node[/code]'s [code]from_port[/code] would be fed into [code]to_node[/code]'s [code]to_port[/code]. @@ -174,15 +172,13 @@ <method name="data_disconnect"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="1" name="from_node" type="int"> + <argument index="1" name="from_port" type="int"> </argument> - <argument index="2" name="from_port" type="int"> + <argument index="2" name="to_node" type="int"> </argument> - <argument index="3" name="to_node" type="int"> - </argument> - <argument index="4" name="to_port" type="int"> + <argument index="3" name="to_port" type="int"> </argument> <description> Disconnect two data ports previously connected with [method data_connect]. @@ -197,37 +193,31 @@ Returns the id of a function's entry point node. </description> </method> - <method name="get_function_scroll" qualifiers="const"> - <return type="Vector2"> - </return> - <argument index="0" name="name" type="StringName"> - </argument> - <description> - Returns the position of the center of the screen for a given function. - </description> - </method> <method name="get_node" qualifiers="const"> <return type="VisualScriptNode"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> - Returns a node given its id and its function. + Returns a node given its id. </description> </method> <method name="get_node_position" qualifiers="const"> <return type="Vector2"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> Returns a node's position in pixels. </description> </method> + <method name="get_scroll" qualifiers="const"> + <return type="Vector2"> + </return> + <description> + Returns the current position of the center of the screen. + </description> + </method> <method name="get_variable_default_value" qualifiers="const"> <return type="Variant"> </return> @@ -267,15 +257,13 @@ <method name="has_data_connection" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="from_node" type="int"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="2" name="from_port" type="int"> + <argument index="1" name="from_port" type="int"> </argument> - <argument index="3" name="to_node" type="int"> + <argument index="2" name="to_node" type="int"> </argument> - <argument index="4" name="to_port" type="int"> + <argument index="3" name="to_port" type="int"> </argument> <description> Returns whether the specified data ports are connected. @@ -293,9 +281,7 @@ <method name="has_node" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> Returns whether a node exists with the given id. @@ -304,13 +290,11 @@ <method name="has_sequence_connection" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="from_node" type="int"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="2" name="from_output" type="int"> + <argument index="1" name="from_output" type="int"> </argument> - <argument index="3" name="to_node" type="int"> + <argument index="2" name="to_node" type="int"> </argument> <description> Returns whether the specified sequence ports are connected. @@ -346,12 +330,10 @@ <method name="remove_node"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> - Remove a specific node. + Remove the node with the specified id. </description> </method> <method name="remove_variable"> @@ -399,13 +381,11 @@ <method name="sequence_connect"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="1" name="from_node" type="int"> + <argument index="1" name="from_output" type="int"> </argument> - <argument index="2" name="from_output" type="int"> - </argument> - <argument index="3" name="to_node" type="int"> + <argument index="2" name="to_node" type="int"> </argument> <description> Connect two sequence ports. The execution will flow from of [code]from_node[/code]'s [code]from_output[/code] into [code]to_node[/code]. @@ -415,29 +395,16 @@ <method name="sequence_disconnect"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> - </argument> - <argument index="1" name="from_node" type="int"> + <argument index="0" name="from_node" type="int"> </argument> - <argument index="2" name="from_output" type="int"> + <argument index="1" name="from_output" type="int"> </argument> - <argument index="3" name="to_node" type="int"> + <argument index="2" name="to_node" type="int"> </argument> <description> Disconnect two sequence ports previously connected with [method sequence_connect]. </description> </method> - <method name="set_function_scroll"> - <return type="void"> - </return> - <argument index="0" name="name" type="StringName"> - </argument> - <argument index="1" name="ofs" type="Vector2"> - </argument> - <description> - Position the center of the screen for a function. - </description> - </method> <method name="set_instance_base_type"> <return type="void"> </return> @@ -450,14 +417,21 @@ <method name="set_node_position"> <return type="void"> </return> - <argument index="0" name="func" type="StringName"> + <argument index="0" name="id" type="int"> </argument> - <argument index="1" name="id" type="int"> + <argument index="1" name="position" type="Vector2"> </argument> - <argument index="2" name="position" type="Vector2"> + <description> + Set the node position in the VisualScript graph. + </description> + </method> + <method name="set_scroll"> + <return type="void"> + </return> + <argument index="0" name="ofs" type="Vector2"> </argument> <description> - Position a node on the screen. + Set the screen center to the given position. </description> </method> <method name="set_variable_default_value"> @@ -496,9 +470,7 @@ </methods> <signals> <signal name="node_ports_changed"> - <argument index="0" name="function" type="String"> - </argument> - <argument index="1" name="id" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> Emitted when the ports of a node are changed. diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index ef4183e6f6..4004f1a04c 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -92,7 +92,7 @@ <constant name="MATH_STEP_DECIMALS" value="24" enum="BuiltinFunc"> Return the number of digit places after the decimal that the first non-zero digit occurs. </constant> - <constant name="MATH_STEPIFY" value="25" enum="BuiltinFunc"> + <constant name="MATH_SNAPPED" value="25" enum="BuiltinFunc"> Return the input snapped to a given step. </constant> <constant name="MATH_LERP" value="26" enum="BuiltinFunc"> @@ -111,61 +111,61 @@ <constant name="MATH_RANDOMIZE" value="31" enum="BuiltinFunc"> Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. </constant> - <constant name="MATH_RAND" value="32" enum="BuiltinFunc"> + <constant name="MATH_RANDI" value="32" enum="BuiltinFunc"> Return a random 32 bits integer value. To obtain a random value between 0 to N (where N is smaller than 2^32 - 1), you can use it with the remainder function. </constant> <constant name="MATH_RANDF" value="33" enum="BuiltinFunc"> Return a random floating-point value between 0 and 1. To obtain a random value between 0 to N, you can use it with multiplication. </constant> - <constant name="MATH_RANDOM" value="34" enum="BuiltinFunc"> + <constant name="MATH_RANDF_RANGE" value="34" enum="BuiltinFunc"> Return a random floating-point value between the two inputs. </constant> - <constant name="MATH_SEED" value="35" enum="BuiltinFunc"> + <constant name="MATH_RANDI_RANGE" value="35" enum="BuiltinFunc"> + Return a random 32-bit integer value between the two inputs. + </constant> + <constant name="MATH_SEED" value="36" enum="BuiltinFunc"> Set the seed for the random number generator. </constant> - <constant name="MATH_RANDSEED" value="36" enum="BuiltinFunc"> + <constant name="MATH_RANDSEED" value="37" enum="BuiltinFunc"> Return a random value from the given seed, along with the new seed. </constant> - <constant name="MATH_DEG2RAD" value="37" enum="BuiltinFunc"> + <constant name="MATH_DEG2RAD" value="38" enum="BuiltinFunc"> Convert the input from degrees to radians. </constant> - <constant name="MATH_RAD2DEG" value="38" enum="BuiltinFunc"> + <constant name="MATH_RAD2DEG" value="39" enum="BuiltinFunc"> Convert the input from radians to degrees. </constant> - <constant name="MATH_LINEAR2DB" value="39" enum="BuiltinFunc"> + <constant name="MATH_LINEAR2DB" value="40" enum="BuiltinFunc"> Convert the input from linear volume to decibel volume. </constant> - <constant name="MATH_DB2LINEAR" value="40" enum="BuiltinFunc"> + <constant name="MATH_DB2LINEAR" value="41" enum="BuiltinFunc"> Convert the input from decibel volume to linear volume. </constant> - <constant name="MATH_POLAR2CARTESIAN" value="41" enum="BuiltinFunc"> + <constant name="MATH_POLAR2CARTESIAN" value="42" enum="BuiltinFunc"> Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (X and Y axis). </constant> - <constant name="MATH_CARTESIAN2POLAR" value="42" enum="BuiltinFunc"> + <constant name="MATH_CARTESIAN2POLAR" value="43" enum="BuiltinFunc"> Converts a 2D point expressed in the cartesian coordinate system (X and Y axis) to the polar coordinate system (a distance from the origin and an angle). </constant> - <constant name="MATH_WRAP" value="43" enum="BuiltinFunc"> + <constant name="MATH_WRAP" value="44" enum="BuiltinFunc"> </constant> - <constant name="MATH_WRAPF" value="44" enum="BuiltinFunc"> + <constant name="MATH_WRAPF" value="45" enum="BuiltinFunc"> </constant> - <constant name="LOGIC_MAX" value="45" enum="BuiltinFunc"> + <constant name="LOGIC_MAX" value="46" enum="BuiltinFunc"> Return the greater of the two numbers, also known as their maximum. </constant> - <constant name="LOGIC_MIN" value="46" enum="BuiltinFunc"> + <constant name="LOGIC_MIN" value="47" enum="BuiltinFunc"> Return the lesser of the two numbers, also known as their minimum. </constant> - <constant name="LOGIC_CLAMP" value="47" enum="BuiltinFunc"> + <constant name="LOGIC_CLAMP" value="48" enum="BuiltinFunc"> Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to [code]min(max(input, range_low), range_high)[/code]. </constant> - <constant name="LOGIC_NEAREST_PO2" value="48" enum="BuiltinFunc"> + <constant name="LOGIC_NEAREST_PO2" value="49" enum="BuiltinFunc"> Return the nearest power of 2 to the input. </constant> - <constant name="OBJ_WEAKREF" value="49" enum="BuiltinFunc"> + <constant name="OBJ_WEAKREF" value="50" enum="BuiltinFunc"> Create a [WeakRef] from the input. </constant> - <constant name="FUNC_FUNCREF" value="50" enum="BuiltinFunc"> - Create a [FuncRef] from the input. - </constant> <constant name="TYPE_CONVERT" value="51" enum="BuiltinFunc"> Convert between types. </constant> diff --git a/modules/visual_script/doc_classes/VisualScriptLists.xml b/modules/visual_script/doc_classes/VisualScriptLists.xml index 5b64d8438b..8a7254b46a 100644 --- a/modules/visual_script/doc_classes/VisualScriptLists.xml +++ b/modules/visual_script/doc_classes/VisualScriptLists.xml @@ -4,7 +4,7 @@ A Visual Script virtual class for in-graph editable nodes. </brief_description> <description> - A Visual Script virtual class that defines the shape and the default behaviour of the nodes that have to be in-graph editable nodes. + A Visual Script virtual class that defines the shape and the default behavior of the nodes that have to be in-graph editable nodes. </description> <tutorials> </tutorials> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml index f13d449064..1c22070ab1 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml @@ -31,5 +31,7 @@ </constant> <constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode"> </constant> + <constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode"> + </constant> </constants> </class> diff --git a/modules/visual_script/icons/VisualScript.svg b/modules/visual_script/icons/VisualScript.svg index f6475d590e..2352ba5d87 100644 --- a/modules/visual_script/icons/VisualScript.svg +++ b/modules/visual_script/icons/VisualScript.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<ellipse cx="3" cy="1039.4" r="2" fill="#6e6e6e"/> -<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625v2h5.2715a2 2 0 0 1 -0.27148 -1 2 2 0 0 1 2 -2 2 2 0 0 1 2 2 2 2 0 0 1 -0.26953 1h5.2695v-2l-2.2578-0.56445a5 5 0 0 0 -0.2793 -0.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2zm-4 9v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2zm8 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0 -2 2 2 0 0 0 -1.7324 -1h2v-2h-2z" fill="#e0e0e0"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625v2h5.2715a2 2 0 0 1 -.27148-1 2 2 0 0 1 2-2 2 2 0 0 1 2 2 2 2 0 0 1 -.26953 1h5.2695v-2l-2.2578-.56445a5 5 0 0 0 -.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2zm-4 9v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm8 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 8afed1229f..4c7b66e368 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "register_types.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/io/resource_loader.h" #include "visual_script.h" #include "visual_script_builtin_funcs.h" diff --git a/modules/visual_script/register_types.h b/modules/visual_script/register_types.h index c18c2930b1..b02a93ebc1 100644 --- a/modules/visual_script/register_types.h +++ b/modules/visual_script/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 1af4b46e22..fe92f59179 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "visual_script.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "scene/main/node.h" #include "visual_script_nodes.h" -//used by editor, this is not really saved +// Used by editor, this is not really saved. void VisualScriptNode::set_breakpoint(bool p_breakpoint) { breakpoint = p_breakpoint; } @@ -55,8 +55,8 @@ void VisualScriptNode::set_default_input_value(int p_port, const Variant &p_valu default_input_values[p_port] = p_value; #ifdef TOOLS_ENABLED - for (Set<VisualScript *>::Element *E = scripts_used.front(); E; E = E->next()) { - E->get()->set_edited(true); + if (script_used.is_valid()) { + script_used->set_edited(true); } #endif } @@ -73,28 +73,28 @@ void VisualScriptNode::_set_default_input_values(Array p_values) { void VisualScriptNode::validate_input_default_values() { default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize - //actually validate on save + // Actually validate on save. for (int i = 0; i < get_input_value_port_count(); i++) { Variant::Type expected = get_input_value_port_info(i).type; if (expected == Variant::NIL || expected == default_input_values[i].get_type()) { continue; } else { - //not the same, reconvert + // Not the same, reconvert. Callable::CallError ce; Variant existing = default_input_values[i]; const Variant *existingp = &existing; - default_input_values[i] = Variant::construct(expected, &existingp, 1, ce, false); + Variant::construct(expected, default_input_values[i], &existingp, 1, ce); if (ce.error != Callable::CallError::CALL_OK) { //could not convert? force.. - default_input_values[i] = Variant::construct(expected, nullptr, 0, ce, false); + Variant::construct(expected, default_input_values[i], nullptr, 0, ce); } } } } Array VisualScriptNode::_get_default_input_values() const { - //validate on save, since on load there is little info about this + // Validate on save, since on load there is little info about this. Array values = default_input_values; values.resize(get_input_value_port_count()); @@ -118,6 +118,8 @@ void VisualScriptNode::_bind_methods() { } VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inputs, int p_output) const { + ERR_FAIL_COND_V(get_output_value_port_count() <= p_output, TypeGuess()); + PropertyInfo pinfo = get_output_value_port_info(p_output); TypeGuess tg; @@ -131,11 +133,7 @@ VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inp } Ref<VisualScript> VisualScriptNode::get_visual_script() const { - if (scripts_used.size()) { - return Ref<VisualScript>(scripts_used.front()->get()); - } - - return Ref<VisualScript>(); + return script_used; } VisualScriptNode::VisualScriptNode() { @@ -165,13 +163,15 @@ VisualScriptNodeInstance::~VisualScriptNodeInstance() { } } -void VisualScript::add_function(const StringName &p_name) { +void VisualScript::add_function(const StringName &p_name, int p_func_node_id) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(functions.has(p_name)); + ERR_FAIL_COND(variables.has(p_name)); + ERR_FAIL_COND(custom_signals.has(p_name)); functions[p_name] = Function(); - functions[p_name].scroll = Vector2(-50, -100); + functions[p_name].func_id = p_func_node_id; } bool VisualScript::has_function(const StringName &p_name) const { @@ -182,11 +182,7 @@ void VisualScript::remove_function(const StringName &p_name) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_name)); - for (Map<int, Function::NodeData>::Element *E = functions[p_name].nodes.front(); E; E = E->next()) { - E->get().node->disconnect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed)); - E->get().node->scripts_used.erase(this); - } - + // Let the editor handle the node removal. functions.erase(p_name); } @@ -207,53 +203,36 @@ void VisualScript::rename_function(const StringName &p_name, const StringName &p functions.erase(p_name); } -void VisualScript::set_function_scroll(const StringName &p_name, const Vector2 &p_scroll) { - ERR_FAIL_COND(!functions.has(p_name)); - functions[p_name].scroll = p_scroll; +void VisualScript::set_scroll(const Vector2 &p_scroll) { + scroll = p_scroll; } -Vector2 VisualScript::get_function_scroll(const StringName &p_name) const { - ERR_FAIL_COND_V(!functions.has(p_name), Vector2()); - return functions[p_name].scroll; +Vector2 VisualScript::get_scroll() const { + return scroll; } void VisualScript::get_function_list(List<StringName> *r_functions) const { - for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - r_functions->push_back(E->key()); - } - - r_functions->sort_custom<StringName::AlphCompare>(); + functions.get_key_list(r_functions); + // r_functions->sort_custom<StringName::AlphCompare>(); // Don't force sorting. } int VisualScript::get_function_node_id(const StringName &p_name) const { ERR_FAIL_COND_V(!functions.has(p_name), -1); - return functions[p_name].function_id; + return functions[p_name].func_id; } void VisualScript::_node_ports_changed(int p_id) { - StringName function; - - for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - if (E->get().nodes.has(p_id)) { - function = E->key(); - break; - } - } - - ERR_FAIL_COND(function == StringName()); - - Function &func = functions[function]; - Ref<VisualScriptNode> vsn = func.nodes[p_id].node; + Ref<VisualScriptNode> vsn = nodes[p_id].node; vsn->validate_input_default_values(); - //must revalidate all the functions + // Must revalidate all the functions. { List<SequenceConnection> to_remove; - for (Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) { + for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_output >= vsn->get_output_sequence_port_count()) { to_remove.push_back(E->get()); } @@ -263,7 +242,7 @@ void VisualScript::_node_ports_changed(int p_id) { } while (to_remove.size()) { - func.sequence_connections.erase(to_remove.front()->get()); + sequence_connections.erase(to_remove.front()->get()); to_remove.pop_front(); } } @@ -271,7 +250,7 @@ void VisualScript::_node_ports_changed(int p_id) { { List<DataConnection> to_remove; - for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { + for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_port >= vsn->get_output_value_port_count()) { to_remove.push_back(E->get()); } @@ -281,63 +260,47 @@ void VisualScript::_node_ports_changed(int p_id) { } while (to_remove.size()) { - func.data_connections.erase(to_remove.front()->get()); + data_connections.erase(to_remove.front()->get()); to_remove.pop_front(); } } #ifdef TOOLS_ENABLED - set_edited(true); //something changed, let's set as edited - emit_signal("node_ports_changed", function, p_id); + set_edited(true); // Something changed, let's set as edited. + emit_signal("node_ports_changed", p_id); #endif } -void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos) { +void VisualScript::add_node(int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos) { ERR_FAIL_COND(instances.size()); - ERR_FAIL_COND(!functions.has(p_func)); - - for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - ERR_FAIL_COND(E->get().nodes.has(p_id)); //id can exist only one in script, even for different functions - } + ERR_FAIL_COND(nodes.has(p_id)); // ID can exist only one in script. - Function &func = functions[p_func]; - - if (Object::cast_to<VisualScriptFunction>(*p_node)) { - //the function indeed - ERR_FAIL_COND_MSG(func.function_id >= 0, "A function node has already been set here."); - - func.function_id = p_id; - } - - Function::NodeData nd; + NodeData nd; nd.node = p_node; nd.pos = p_pos; Ref<VisualScriptNode> vsn = p_node; vsn->connect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed), varray(p_id)); - vsn->scripts_used.insert(this); - vsn->validate_input_default_values(); // Validate when fully loaded + vsn->script_used = Ref<VisualScript>(this); + vsn->validate_input_default_values(); // Validate when fully loaded. - func.nodes[p_id] = nd; + nodes[p_id] = nd; } -void VisualScript::remove_node(const StringName &p_func, int p_id) { +void VisualScript::remove_node(int p_id) { ERR_FAIL_COND(instances.size()); - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; - - ERR_FAIL_COND(!func.nodes.has(p_id)); + ERR_FAIL_COND(!nodes.has(p_id)); { List<SequenceConnection> to_remove; - for (Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) { + for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { to_remove.push_back(E->get()); } } while (to_remove.size()) { - func.sequence_connections.erase(to_remove.front()->get()); + sequence_connections.erase(to_remove.front()->get()); to_remove.pop_front(); } } @@ -345,122 +308,88 @@ void VisualScript::remove_node(const StringName &p_func, int p_id) { { List<DataConnection> to_remove; - for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { + for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { to_remove.push_back(E->get()); } } while (to_remove.size()) { - func.data_connections.erase(to_remove.front()->get()); + data_connections.erase(to_remove.front()->get()); to_remove.pop_front(); } } - if (Object::cast_to<VisualScriptFunction>(func.nodes[p_id].node.ptr())) { - func.function_id = -1; //revert to invalid - } + nodes[p_id].node->disconnect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed)); + nodes[p_id].node->script_used.unref(); - func.nodes[p_id].node->disconnect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed)); - func.nodes[p_id].node->scripts_used.erase(this); - - func.nodes.erase(p_id); + nodes.erase(p_id); } -bool VisualScript::has_node(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); - const Function &func = functions[p_func]; - - return func.nodes.has(p_id); +bool VisualScript::has_node(int p_id) const { + return nodes.has(p_id); } -Ref<VisualScriptNode> VisualScript::get_node(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), Ref<VisualScriptNode>()); - const Function &func = functions[p_func]; - - ERR_FAIL_COND_V(!func.nodes.has(p_id), Ref<VisualScriptNode>()); +Ref<VisualScriptNode> VisualScript::get_node(int p_id) const { + ERR_FAIL_COND_V(!nodes.has(p_id), Ref<VisualScriptNode>()); - return func.nodes[p_id].node; + return nodes[p_id].node; } -void VisualScript::set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos) { +void VisualScript::set_node_position(int p_id, const Point2 &p_pos) { ERR_FAIL_COND(instances.size()); - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; - - ERR_FAIL_COND(!func.nodes.has(p_id)); - func.nodes[p_id].pos = p_pos; + ERR_FAIL_COND(!nodes.has(p_id)); + nodes[p_id].pos = p_pos; } -Point2 VisualScript::get_node_position(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), Point2()); - const Function &func = functions[p_func]; - - ERR_FAIL_COND_V(!func.nodes.has(p_id), Point2()); - return func.nodes[p_id].pos; +Point2 VisualScript::get_node_position(int p_id) const { + ERR_FAIL_COND_V(!nodes.has(p_id), Point2()); + return nodes[p_id].pos; } -void VisualScript::get_node_list(const StringName &p_func, List<int> *r_nodes) const { - ERR_FAIL_COND(!functions.has(p_func)); - const Function &func = functions[p_func]; - - for (const Map<int, Function::NodeData>::Element *E = func.nodes.front(); E; E = E->next()) { - r_nodes->push_back(E->key()); - } +void VisualScript::get_node_list(List<int> *r_nodes) const { + nodes.get_key_list(r_nodes); } -void VisualScript::sequence_connect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) { +void VisualScript::sequence_connect(int p_from_node, int p_from_output, int p_to_node) { ERR_FAIL_COND(instances.size()); - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; SequenceConnection sc; sc.from_node = p_from_node; sc.from_output = p_from_output; sc.to_node = p_to_node; - ERR_FAIL_COND(func.sequence_connections.has(sc)); + ERR_FAIL_COND(sequence_connections.has(sc)); - func.sequence_connections.insert(sc); + sequence_connections.insert(sc); } -void VisualScript::sequence_disconnect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) { - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; - +void VisualScript::sequence_disconnect(int p_from_node, int p_from_output, int p_to_node) { SequenceConnection sc; sc.from_node = p_from_node; sc.from_output = p_from_output; sc.to_node = p_to_node; - ERR_FAIL_COND(!func.sequence_connections.has(sc)); + ERR_FAIL_COND(!sequence_connections.has(sc)); - func.sequence_connections.erase(sc); + sequence_connections.erase(sc); } -bool VisualScript::has_sequence_connection(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); - const Function &func = functions[p_func]; - +bool VisualScript::has_sequence_connection(int p_from_node, int p_from_output, int p_to_node) const { SequenceConnection sc; sc.from_node = p_from_node; sc.from_output = p_from_output; sc.to_node = p_to_node; - return func.sequence_connections.has(sc); + return sequence_connections.has(sc); } -void VisualScript::get_sequence_connection_list(const StringName &p_func, List<SequenceConnection> *r_connection) const { - ERR_FAIL_COND(!functions.has(p_func)); - const Function &func = functions[p_func]; - - for (const Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) { +void VisualScript::get_sequence_connection_list(List<SequenceConnection> *r_connection) const { + for (const Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { r_connection->push_back(E->get()); } } -void VisualScript::data_connect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { +void VisualScript::data_connect(int p_from_node, int p_from_port, int p_to_node, int p_to_port) { ERR_FAIL_COND(instances.size()); - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; DataConnection dc; dc.from_node = p_from_node; @@ -468,72 +397,55 @@ void VisualScript::data_connect(const StringName &p_func, int p_from_node, int p dc.to_node = p_to_node; dc.to_port = p_to_port; - ERR_FAIL_COND(func.data_connections.has(dc)); + ERR_FAIL_COND(data_connections.has(dc)); - func.data_connections.insert(dc); + data_connections.insert(dc); } -void VisualScript::data_disconnect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { - ERR_FAIL_COND(!functions.has(p_func)); - Function &func = functions[p_func]; - +void VisualScript::data_disconnect(int p_from_node, int p_from_port, int p_to_node, int p_to_port) { DataConnection dc; dc.from_node = p_from_node; dc.from_port = p_from_port; dc.to_node = p_to_node; dc.to_port = p_to_port; - ERR_FAIL_COND(!func.data_connections.has(dc)); + ERR_FAIL_COND(!data_connections.has(dc)); - func.data_connections.erase(dc); + data_connections.erase(dc); } -bool VisualScript::has_data_connection(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); - const Function &func = functions[p_func]; - +bool VisualScript::has_data_connection(int p_from_node, int p_from_port, int p_to_node, int p_to_port) const { DataConnection dc; dc.from_node = p_from_node; dc.from_port = p_from_port; dc.to_node = p_to_node; dc.to_port = p_to_port; - return func.data_connections.has(dc); + return data_connections.has(dc); } -bool VisualScript::is_input_value_port_connected(const StringName &p_func, int p_node, int p_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); - const Function &func = functions[p_func]; - - for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { +bool VisualScript::is_input_value_port_connected(int p_node, int p_port) const { + for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().to_node == p_node && E->get().to_port == p_port) { return true; } } - return false; } -bool VisualScript::get_input_value_port_connection_source(const StringName &p_func, int p_node, int p_port, int *r_node, int *r_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); - const Function &func = functions[p_func]; - - for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { +bool VisualScript::get_input_value_port_connection_source(int p_node, int p_port, int *r_node, int *r_port) const { + for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().to_node == p_node && E->get().to_port == p_port) { *r_node = E->get().from_node; *r_port = E->get().from_port; return true; } } - return false; } -void VisualScript::get_data_connection_list(const StringName &p_func, List<DataConnection> *r_connection) const { - ERR_FAIL_COND(!functions.has(p_func)); - const Function &func = functions[p_func]; - - for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { +void VisualScript::get_data_connection_list(List<DataConnection> *r_connection) const { + for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { r_connection->push_back(E->get()); } } @@ -653,11 +565,8 @@ Dictionary VisualScript::_get_variable_info(const StringName &p_name) const { } void VisualScript::get_variable_list(List<StringName> *r_variables) const { - for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - r_variables->push_back(E->key()); - } - - r_variables->sort_custom<StringName::AlphCompare>(); + variables.get_key_list(r_variables); + // r_variables->sort_custom<StringName::AlphCompare>(); // Don't force it. } void VisualScript::set_instance_base_type(const StringName &p_type) { @@ -680,24 +589,19 @@ void VisualScript::rename_variable(const StringName &p_name, const StringName &p variables[p_new_name] = variables[p_name]; variables.erase(p_name); - - List<StringName> funcs; - get_function_list(&funcs); - for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions - List<int> ids; - get_node_list(F->get(), &ids); - for (List<int>::Element *E = ids.front(); E; E = E->next()) { - Ref<VisualScriptVariableGet> nodeget = get_node(F->get(), E->get()); - if (nodeget.is_valid()) { - if (nodeget->get_variable() == p_name) { - nodeget->set_variable(p_new_name); - } - } else { - Ref<VisualScriptVariableSet> nodeset = get_node(F->get(), E->get()); - if (nodeset.is_valid()) { - if (nodeset->get_variable() == p_name) { - nodeset->set_variable(p_new_name); - } + List<int> ids; + get_node_list(&ids); + for (List<int>::Element *E = ids.front(); E; E = E->next()) { + Ref<VisualScriptVariableGet> nodeget = get_node(E->get()); + if (nodeget.is_valid()) { + if (nodeget->get_variable() == p_name) { + nodeget->set_variable(p_new_name); + } + } else { + Ref<VisualScriptVariableSet> nodeset = get_node(E->get()); + if (nodeset.is_valid()) { + if (nodeset->get_variable() == p_name) { + nodeset->set_variable(p_new_name); } } } @@ -808,23 +712,24 @@ void VisualScript::get_custom_signal_list(List<StringName> *r_custom_signals) co } int VisualScript::get_available_id() const { - int max_id = 0; - for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - if (E->get().nodes.empty()) { - continue; + // This is infinitely increasing, + // so one might want to implement a better solution, + // if the there is a case for huge number of nodes to be added to visual script. + List<int> nds; + nodes.get_key_list(&nds); + int max = -1; + for (const List<int>::Element *E = nds.front(); E; E = E->next()) { + if (E->get() > max) { + max = E->get(); } - - int last_id = E->get().nodes.back()->key(); - max_id = MAX(max_id, last_id + 1); } - - return max_id; + return (max + 1); } ///////////////////////////////// bool VisualScript::can_instance() const { - return true; //ScriptServer::is_scripting_enabled(); + return true; // ScriptServer::is_scripting_enabled(); } StringName VisualScript::get_instance_base_type() const { @@ -832,7 +737,7 @@ StringName VisualScript::get_instance_base_type() const { } Ref<Script> VisualScript::get_base_script() const { - return Ref<Script>(); // no inheritance in visual script + return Ref<Script>(); // No inheritance in visual script. } #ifdef TOOLS_ENABLED @@ -842,20 +747,23 @@ void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) void VisualScript::_update_placeholders() { if (placeholders.size() == 0) { - return; //no bother if no placeholders + return; // No bother if no placeholders. } List<PropertyInfo> pinfo; Map<StringName, Variant> values; - for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - if (!E->get()._export) { + List<StringName> keys; + variables.get_key_list(&keys); + + for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { + if (!variables[E->get()]._export) { continue; } - PropertyInfo p = E->get().info; - p.name = String(E->key()); + PropertyInfo p = variables[E->get()].info; + p.name = String(E->get()); pinfo.push_back(p); - values[p.name] = E->get().default_value; + values[p.name] = variables[E->get()].default_value; } for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { @@ -875,17 +783,18 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { List<PropertyInfo> pinfo; Map<StringName, Variant> values; - for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - if (!E->get()._export) { + List<StringName> keys; + variables.get_key_list(&keys); + + for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) { + if (!variables[E->get()]._export) continue; - } - PropertyInfo p = E->get().info; - p.name = String(E->key()); + PropertyInfo p = variables[E->get()].info; + p.name = String(E->get()); pinfo.push_back(p); - values[p.name] = E->get().default_value; + values[p.name] = variables[E->get()].default_value; } - sins->update(pinfo, values); return sins; @@ -928,7 +837,7 @@ bool VisualScript::is_tool() const { } bool VisualScript::is_valid() const { - return true; //always valid + return true; // Always valid. } ScriptLanguage *VisualScript::get_language() const { @@ -964,11 +873,14 @@ bool VisualScript::get_property_default_value(const StringName &p_property, Vari } void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { - for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { + List<StringName> funcs; + functions.get_key_list(&funcs); + + for (List<StringName>::Element *E = funcs.front(); E; E = E->next()) { MethodInfo mi; - mi.name = E->key(); - if (E->get().function_id >= 0) { - Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node; + mi.name = E->get(); + if (functions[E->get()].func_id >= 0) { + Ref<VisualScriptFunction> func = nodes[functions[E->get()].func_id].node; if (func.is_valid()) { for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arg; @@ -988,15 +900,15 @@ bool VisualScript::has_method(const StringName &p_method) const { } MethodInfo VisualScript::get_method_info(const StringName &p_method) const { - const Map<StringName, Function>::Element *E = functions.find(p_method); - if (!E) { + const Function funct = functions[p_method]; + if (funct.func_id == -1) { return MethodInfo(); } MethodInfo mi; - mi.name = E->key(); - if (E->get().function_id >= 0) { - Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node; + mi.name = p_method; + if (funct.func_id >= 0) { + Ref<VisualScriptFunction> func = nodes[funct.func_id].node; if (func.is_valid()) { for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arg; @@ -1028,28 +940,18 @@ void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const { } int VisualScript::get_member_line(const StringName &p_member) const { -#ifdef TOOLS_ENABLED - if (has_function(p_member)) { - for (Map<int, Function::NodeData>::Element *E = functions[p_member].nodes.front(); E; E = E->next()) { - if (Object::cast_to<VisualScriptFunction>(E->get().node.ptr())) { - return E->key(); - } - } - } -#endif - return -1; + return functions[p_member].func_id; // will be -1 if not found } #ifdef TOOLS_ENABLED bool VisualScript::are_subnodes_edited() const { - for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - if (F->get().node->is_edited()) { - return true; - } + List<int> keys; + nodes.get_key_list(&keys); + for (const List<int>::Element *F = keys.front(); F; F = F->next()) { + if (nodes[F->get()].node->is_edited()) { + return true; } } - return false; } #endif @@ -1140,85 +1042,41 @@ void VisualScript::_set_data(const Dictionary &p_data) { Array funcs = d["functions"]; functions.clear(); - Vector2 last_pos = Vector2(-100 * funcs.size(), -100 * funcs.size()); // this is the center of the last fn box - Vector2 last_size = Vector2(0.0, 0.0); - for (int i = 0; i < funcs.size(); i++) { Dictionary func = funcs[i]; - - StringName name = func["name"]; - //int id=func["function_id"]; - add_function(name); - - set_function_scroll(name, func["scroll"]); - - Array nodes = func["nodes"]; - - if (!d.has("vs_unify") && nodes.size() > 0) { - Vector2 top_left = nodes[1]; - Vector2 bottom_right = nodes[1]; - - for (int j = 0; j < nodes.size(); j += 3) { - Point2 pos = nodes[j + 1]; - if (pos.y > top_left.y) { - top_left.y = pos.y; - } - if (pos.y < bottom_right.y) { - bottom_right.y = pos.y; - } - if (pos.x > bottom_right.x) { - bottom_right.x = pos.x; - } - if (pos.x < top_left.x) { - top_left.x = pos.x; - } - } - - Vector2 size = Vector2(bottom_right.x - top_left.x, top_left.y - bottom_right.y); - - Vector2 offset = last_pos + (last_size / 2.0) + (size / 2.0); // dunno I might just keep it in one axis but diagonal feels better.... - - last_pos = offset; - last_size = size; - - for (int j = 0; j < nodes.size(); j += 3) { - add_node(name, nodes[j], nodes[j + 2], offset + nodes[j + 1]); // also add an additional buffer if you want to - } - - } else { - for (int j = 0; j < nodes.size(); j += 3) { - add_node(name, nodes[j], nodes[j + 2], nodes[j + 1]); - } + add_function(func["name"], func["function_id"]); + } + { + Array nodes = d["nodes"]; + for (int i = 0; i < nodes.size(); i += 3) { + add_node(nodes[i], nodes[i + 2], nodes[i + 1]); } - Array sequence_connections = func["sequence_connections"]; + Array sequence_connections = d["sequence_connections"]; for (int j = 0; j < sequence_connections.size(); j += 3) { - sequence_connect(name, sequence_connections[j + 0], sequence_connections[j + 1], sequence_connections[j + 2]); + sequence_connect(sequence_connections[j + 0], sequence_connections[j + 1], sequence_connections[j + 2]); } - Array data_connections = func["data_connections"]; - + Array data_connections = d["data_connections"]; for (int j = 0; j < data_connections.size(); j += 4) { - data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]); + data_connect(data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]); } } + is_tool_script = d["is_tool_script"]; + scroll = d["scroll"]; - if (d.has("is_tool_script")) { - is_tool_script = d["is_tool_script"]; - } else { - is_tool_script = false; - } - - // Takes all the rpc methods + // Takes all the rpc methods. rpc_functions.clear(); rpc_variables.clear(); - for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - if (E->get().function_id >= 0 && E->get().nodes.find(E->get().function_id)) { - Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; + List<StringName> fns; + functions.get_key_list(&fns); + for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) { + if (functions[E->get()].func_id >= 0 && nodes.has(functions[E->get()].func_id)) { + Ref<VisualScriptFunction> vsf = nodes[functions[E->get()].func_id].node; if (vsf.is_valid()) { if (vsf->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) { ScriptNetData nd; - nd.name = E->key(); + nd.name = E->get(); nd.mode = vsf->get_rpc_mode(); if (rpc_functions.find(nd) == -1) { rpc_functions.push_back(nd); @@ -1228,8 +1086,6 @@ void VisualScript::_set_data(const Dictionary &p_data) { } } - // Visual script doesn't have rset :( - // Sort so we are 100% that they are always the same. rpc_functions.sort_custom<SortNetData>(); } @@ -1237,12 +1093,15 @@ void VisualScript::_set_data(const Dictionary &p_data) { Dictionary VisualScript::_get_data() const { Dictionary d; d["base_type"] = base_type; + Array vars; - for (const Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - Dictionary var = _get_variable_info(E->key()); - var["name"] = E->key(); //make sure it's the right one - var["default_value"] = E->get().default_value; - var["export"] = E->get()._export; + List<StringName> var_names; + variables.get_key_list(&var_names); + for (const List<StringName>::Element *E = var_names.front(); E; E = E->next()) { + Dictionary var = _get_variable_info(E->get()); + var["name"] = E->get(); // Make sure it's the right one. + var["default_value"] = variables[E->get()].default_value; + var["export"] = variables[E->get()]._export; vars.push_back(var); } d["variables"] = vars; @@ -1264,78 +1123,73 @@ Dictionary VisualScript::_get_data() const { d["signals"] = sigs; Array funcs; - - for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { + List<StringName> func_names; + functions.get_key_list(&func_names); + for (const List<StringName>::Element *E = func_names.front(); E; E = E->next()) { Dictionary func; - func["name"] = E->key(); - func["function_id"] = E->get().function_id; - func["scroll"] = E->get().scroll; - - Array nodes; - - for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - nodes.push_back(F->key()); - nodes.push_back(F->get().pos); - nodes.push_back(F->get().node); - } - - func["nodes"] = nodes; - - Array sequence_connections; - - for (const Set<SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) { - sequence_connections.push_back(F->get().from_node); - sequence_connections.push_back(F->get().from_output); - sequence_connections.push_back(F->get().to_node); - } - - func["sequence_connections"] = sequence_connections; - - Array data_connections; + func["name"] = E->get(); + func["function_id"] = functions[E->get()].func_id; + funcs.push_back(func); + } + d["functions"] = funcs; - for (const Set<DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) { - data_connections.push_back(F->get().from_node); - data_connections.push_back(F->get().from_port); - data_connections.push_back(F->get().to_node); - data_connections.push_back(F->get().to_port); - } + Array nds; + List<int> node_ids; + nodes.get_key_list(&node_ids); + for (const List<int>::Element *F = node_ids.front(); F; F = F->next()) { + nds.push_back(F->get()); + nds.push_back(nodes[F->get()].pos); + nds.push_back(nodes[F->get()].node); + } + d["nodes"] = nds; - func["data_connections"] = data_connections; + Array seqconns; + for (const Set<SequenceConnection>::Element *F = sequence_connections.front(); F; F = F->next()) { + seqconns.push_back(F->get().from_node); + seqconns.push_back(F->get().from_output); + seqconns.push_back(F->get().to_node); + } + d["sequence_connections"] = seqconns; - funcs.push_back(func); + Array dataconns; + for (const Set<DataConnection>::Element *F = data_connections.front(); F; F = F->next()) { + dataconns.push_back(F->get().from_node); + dataconns.push_back(F->get().from_port); + dataconns.push_back(F->get().to_node); + dataconns.push_back(F->get().to_port); } + d["data_connections"] = dataconns; - d["functions"] = funcs; d["is_tool_script"] = is_tool_script; - d["vs_unify"] = true; + d["scroll"] = scroll; return d; } void VisualScript::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_function", "name"), &VisualScript::add_function); + ClassDB::bind_method(D_METHOD("add_function", "name", "func_node_id"), &VisualScript::add_function); ClassDB::bind_method(D_METHOD("has_function", "name"), &VisualScript::has_function); ClassDB::bind_method(D_METHOD("remove_function", "name"), &VisualScript::remove_function); ClassDB::bind_method(D_METHOD("rename_function", "name", "new_name"), &VisualScript::rename_function); - ClassDB::bind_method(D_METHOD("set_function_scroll", "name", "ofs"), &VisualScript::set_function_scroll); - ClassDB::bind_method(D_METHOD("get_function_scroll", "name"), &VisualScript::get_function_scroll); + ClassDB::bind_method(D_METHOD("set_scroll", "ofs"), &VisualScript::set_scroll); + ClassDB::bind_method(D_METHOD("get_scroll"), &VisualScript::get_scroll); - ClassDB::bind_method(D_METHOD("add_node", "func", "id", "node", "position"), &VisualScript::add_node, DEFVAL(Point2())); - ClassDB::bind_method(D_METHOD("remove_node", "func", "id"), &VisualScript::remove_node); + ClassDB::bind_method(D_METHOD("add_node", "id", "node", "position"), &VisualScript::add_node, DEFVAL(Point2())); + ClassDB::bind_method(D_METHOD("remove_node", "id"), &VisualScript::remove_node); ClassDB::bind_method(D_METHOD("get_function_node_id", "name"), &VisualScript::get_function_node_id); - ClassDB::bind_method(D_METHOD("get_node", "func", "id"), &VisualScript::get_node); - ClassDB::bind_method(D_METHOD("has_node", "func", "id"), &VisualScript::has_node); - ClassDB::bind_method(D_METHOD("set_node_position", "func", "id", "position"), &VisualScript::set_node_position); - ClassDB::bind_method(D_METHOD("get_node_position", "func", "id"), &VisualScript::get_node_position); + ClassDB::bind_method(D_METHOD("get_node", "id"), &VisualScript::get_node); + ClassDB::bind_method(D_METHOD("has_node", "id"), &VisualScript::has_node); + ClassDB::bind_method(D_METHOD("set_node_position", "id", "position"), &VisualScript::set_node_position); + ClassDB::bind_method(D_METHOD("get_node_position", "id"), &VisualScript::get_node_position); - ClassDB::bind_method(D_METHOD("sequence_connect", "func", "from_node", "from_output", "to_node"), &VisualScript::sequence_connect); - ClassDB::bind_method(D_METHOD("sequence_disconnect", "func", "from_node", "from_output", "to_node"), &VisualScript::sequence_disconnect); - ClassDB::bind_method(D_METHOD("has_sequence_connection", "func", "from_node", "from_output", "to_node"), &VisualScript::has_sequence_connection); + ClassDB::bind_method(D_METHOD("sequence_connect", "from_node", "from_output", "to_node"), &VisualScript::sequence_connect); + ClassDB::bind_method(D_METHOD("sequence_disconnect", "from_node", "from_output", "to_node"), &VisualScript::sequence_disconnect); + ClassDB::bind_method(D_METHOD("has_sequence_connection", "from_node", "from_output", "to_node"), &VisualScript::has_sequence_connection); - ClassDB::bind_method(D_METHOD("data_connect", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_connect); - ClassDB::bind_method(D_METHOD("data_disconnect", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_disconnect); - ClassDB::bind_method(D_METHOD("has_data_connection", "func", "from_node", "from_port", "to_node", "to_port"), &VisualScript::has_data_connection); + ClassDB::bind_method(D_METHOD("data_connect", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_connect); + ClassDB::bind_method(D_METHOD("data_disconnect", "from_node", "from_port", "to_node", "to_port"), &VisualScript::data_disconnect); + ClassDB::bind_method(D_METHOD("has_data_connection", "from_node", "from_port", "to_node", "to_port"), &VisualScript::has_data_connection); ClassDB::bind_method(D_METHOD("add_variable", "name", "default_value", "export"), &VisualScript::add_variable, DEFVAL(Variant()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("has_variable", "name"), &VisualScript::has_variable); @@ -1371,7 +1225,7 @@ void VisualScript::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); - ADD_SIGNAL(MethodInfo("node_ports_changed", PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("node_ports_changed", PropertyInfo(Variant::INT, "id"))); } VisualScript::VisualScript() { @@ -1380,16 +1234,12 @@ VisualScript::VisualScript() { } bool VisualScript::inherits_script(const Ref<Script> &p_script) const { - return this == p_script.ptr(); //there is no inheritance in visual scripts, so this is enough -} - -StringName VisualScript::get_default_func() const { - return StringName("f_312843592"); + return this == p_script.ptr(); // There is no inheritance in visual scripts, so this is enough. } -Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_func, int from_node) { +Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) { List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>); - get_sequence_connection_list(edited_func, sc); + get_sequence_connection_list(sc); Set<int> connected; for (List<VisualScript::SequenceConnection>::Element *E = sc->front(); E; E = E->next()) { if (E->get().from_node == from_node) { @@ -1401,8 +1251,11 @@ Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_ } VisualScript::~VisualScript() { - while (!functions.empty()) { - remove_function(functions.front()->key()); + // Remove all nodes and stuff that hold data refs. + List<int> nds; + nodes.get_key_list(&nds); + for (const List<int>::Element *E = nds.front(); E; E = E->next()) { + remove_node(E->get()); } } @@ -1430,20 +1283,21 @@ bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { - for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) { - if (!E->get()._export) { + List<StringName> vars; + script->variables.get_key_list(&vars); + for (const List<StringName>::Element *E = vars.front(); E; E = E->next()) { + if (!script->variables[E->get()]._export) { continue; } - PropertyInfo p = E->get().info; - p.name = String(E->key()); + PropertyInfo p = script->variables[E->get()].info; + p.name = String(E->get()); p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; p_properties->push_back(p); } } Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - const Map<StringName, VisualScript::Variable>::Element *E = script->variables.find(p_name); - if (!E) { + if (!script->variables.has(p_name)) { if (r_is_valid) { *r_is_valid = false; } @@ -1454,19 +1308,17 @@ Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, *r_is_valid = true; } - return E->get().info.type; + return script->variables[p_name].info.type; } void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) { - if (E->key() == script->get_default_func()) { - continue; - } - + List<StringName> fns; + script->functions.get_key_list(&fns); + for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) { MethodInfo mi; - mi.name = E->key(); - if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) { - Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; + mi.name = E->get(); + if (script->functions[E->get()].func_id >= 0 && script->nodes.has(script->functions[E->get()].func_id)) { + Ref<VisualScriptFunction> vsf = script->nodes[script->functions[E->get()].func_id].node; if (vsf.is_valid()) { for (int i = 0; i < vsf->get_argument_count(); i++) { PropertyInfo arg; @@ -1476,21 +1328,16 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { mi.arguments.push_back(arg); } - if (!vsf->is_sequenced()) { //assumed constant if not sequenced + if (!vsf->is_sequenced()) { // Assumed constant if not sequenced. mi.flags |= METHOD_FLAG_CONST; } } } - p_list->push_back(mi); } } bool VisualScriptInstance::has_method(const StringName &p_method) const { - if (p_method == script->get_default_func()) { - return false; - } - return script->functions.has(p_method); } @@ -1506,7 +1353,7 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int pass_stack[node->pass_idx] = p_pass; - if (!node->dependencies.empty()) { + if (!node->dependencies.is_empty()) { int dc = node->dependencies.size(); VisualScriptNodeInstance **deps = node->dependencies.ptrw(); @@ -1522,10 +1369,10 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK; if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) { - //is a default value (unassigned input port) + // Is a default value (unassigned input port). input_args[i] = &default_values[index]; } else { - //regular temporary in stack + // Rregular temporary in stack. input_args[i] = &variant_stack[index]; } } @@ -1536,7 +1383,7 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int Variant *working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)nullptr; node->step(input_args, output_args, VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE, working_mem, r_error, error_str); - //ignore return + // Ignore return. if (r_error.error != Callable::CallError::CALL_OK) { *r_error_node = node; } @@ -1547,7 +1394,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p ERR_FAIL_COND_V(!F, Variant()); Function *f = &F->get(); - //this call goes separate, so it can e yielded and suspended + // This call goes separate, so it can e yielded and suspended. Variant *variant_stack = (Variant *)p_stack; bool *sequence_bits = (bool *)(variant_stack + f->max_stack); const Variant **input_args = (const Variant **)(sequence_bits + f->node_count); @@ -1573,27 +1420,27 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p #endif while (true) { - p_pass++; //increment pass + p_pass++; // Increment pass. current_node_id = node->get_id(); VSDEBUG("==========AT NODE: " + itos(current_node_id) + " base: " + node->get_base_node()->get_class_name()); VSDEBUG("AT STACK POS: " + itos(flow_stack_pos)); - //setup working mem + // Setup working mem. working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)nullptr; VSDEBUG("WORKING MEM: " + itos(node->working_mem_idx)); if (current_node_id == f->node) { - //if function node, set up function arguments from beginning of stack + // If function node, set up function arguments from beginning of stack. for (int i = 0; i < f->argument_count; i++) { input_args[i] = &variant_stack[i]; } } else { - //run dependencies first + // Run dependencies first. - if (!node->dependencies.empty()) { + if (!node->dependencies.is_empty()) { int dc = node->dependencies.size(); VisualScriptNodeInstance **deps = node->dependencies.ptrw(); @@ -1608,18 +1455,18 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } if (!error) { - //setup input pointers normally + // Setup input pointers normally. VSDEBUG("INPUT PORTS: " + itos(node->input_port_count)); for (int i = 0; i < node->input_port_count; i++) { int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK; if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) { - //is a default value (unassigned input port) + // Is a default value (unassigned input port). input_args[i] = &default_values[index]; VSDEBUG("\tPORT " + itos(i) + " DEFAULT VAL"); } else { - //regular temporary in stack + // Regular temporary in stack. input_args[i] = &variant_stack[index]; VSDEBUG("PORT " + itos(i) + " AT STACK " + itos(index)); } @@ -1631,7 +1478,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p break; } - //setup output pointers + // Setup output pointers. VSDEBUG("OUTPUT PORTS: " + itos(node->output_port_count)); for (int i = 0; i < node->output_port_count; i++) { @@ -1639,15 +1486,15 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p VSDEBUG("PORT " + itos(i) + " AT STACK " + itos(node->output_ports[i])); } - //do step + // Do step. VisualScriptNodeInstance::StartMode start_mode; { if (p_resuming_yield) { start_mode = VisualScriptNodeInstance::START_MODE_RESUME_YIELD; - p_resuming_yield = false; // should resume only the first time + p_resuming_yield = false; // Should resume only the first time. } else if (flow_stack && (flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT)) { - //if there is a push bit, it means we are continuing a sequence + // If there is a push bit, it means we are continuing a sequence. start_mode = VisualScriptNodeInstance::START_MODE_CONTINUE_SEQUENCE; } else { start_mode = VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE; @@ -1659,13 +1506,13 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p int ret = node->step(input_args, output_args, start_mode, working_mem, r_error, error_str); if (r_error.error != Callable::CallError::CALL_OK) { - //use error from step + // Use error from step. error = true; break; } if (ret & VisualScriptNodeInstance::STEP_YIELD_BIT) { - //yielded! + // Yielded! if (node->get_working_memory_size() == 0) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("A node yielded without working memory, please read the docs on how to yield properly!"); @@ -1681,7 +1528,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p break; } - //step 1, capture all state + // Step 1, capture all state. state->instance_id = get_owner_ptr()->get_instance_id(); state->script_id = get_script()->get_instance_id(); state->instance = this; @@ -1693,11 +1540,11 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p state->stack.resize(p_stack_size); state->pass = p_pass; copymem(state->stack.ptrw(), p_stack, p_stack_size); - //step 2, run away, return directly + // Step 2, run away, return directly. r_error.error = Callable::CallError::CALL_OK; #ifdef DEBUG_ENABLED - //will re-enter later, so exiting + // Will re-enter later, so exiting. if (EngineDebugger::is_active()) { VisualScriptLanguage::singleton->exit_function(); } @@ -1742,18 +1589,18 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p error_str = RTR("Return value must be assigned to first element of node working memory! Fix your node please."); error = true; } else { - //assign from working memory, first element + // Assign from working memory, first element. return_value = *working_mem; } VSDEBUG("EXITING FUNCTION - VALUE " + String(return_value)); - break; //exit function requested, bye + break; // Exit function requested, bye } - VisualScriptNodeInstance *next = nullptr; //next node + VisualScriptNodeInstance *next = nullptr; // Next node. if ((ret == output || ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) && node->sequence_output_count) { - //if no exit bit was set, and has sequence outputs, guess next node + // If no exit bit was set, and has sequence outputs, guess next node. if (output >= node->sequence_output_count) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("Node returned an invalid sequence output: ") + itos(output); @@ -1766,21 +1613,21 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } if (flow_stack) { - //update flow stack pos (may have changed) + // Update flow stack pos (may have changed). flow_stack[flow_stack_pos] = current_node_id; - //add stack push bit if requested + // Add stack push bit if requested. if (ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) { flow_stack[flow_stack_pos] |= VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT; - sequence_bits[node->sequence_index] = true; //remember sequence bit + sequence_bits[node->sequence_index] = true; // Remember sequence bit. VSDEBUG("NEXT SEQ - FLAG BIT"); } else { - sequence_bits[node->sequence_index] = false; //forget sequence bit + sequence_bits[node->sequence_index] = false; // Forget sequence bit. VSDEBUG("NEXT SEQ - NORMAL"); } if (ret & VisualScriptNodeInstance::STEP_FLAG_GO_BACK_BIT) { - //go back request + // Go back request. if (flow_stack_pos > 0) { flow_stack_pos--; @@ -1788,20 +1635,20 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p VSDEBUG("NEXT IS GO BACK"); } else { VSDEBUG("NEXT IS GO BACK, BUT NO NEXT SO EXIT"); - break; //simply exit without value or error + break; // Simply exit without value or error. } } else if (next) { if (sequence_bits[next->sequence_index]) { - // what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front + // What happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front // because each node has a working memory, we can't really do a sub-sequence // as a result, the sequence will be restarted and the stack will roll back to find where this node - // started the sequence + // started the sequence. bool found = false; for (int i = flow_stack_pos; i >= 0; i--) { if ((flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK) == next->get_id()) { - flow_stack_pos = i; //roll back and remove bit + flow_stack_pos = i; // Roll back and remove bit. flow_stack[i] = next->get_id(); sequence_bits[next->sequence_index] = false; found = true; @@ -1819,7 +1666,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p VSDEBUG("RE-ENTERED A LOOP, RETURNED STACK POS TO - " + itos(flow_stack_pos)); } else { - // check for stack overflow + // Check for stack overflow. if (flow_stack_pos + 1 >= flow_max) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("Stack overflow with stack depth: ") + itos(output); @@ -1836,7 +1683,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } } else { - //no next node, try to go back in stack to pushed bit + // No next node, try to go back in stack to pushed bit. bool found = false; @@ -1852,22 +1699,22 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p if (!found) { VSDEBUG("NO NEXT NODE, NO GO BACK, EXITING"); - break; //done, couldn't find a push stack bit + break; // Done, couldn't find a push stack bit. } VSDEBUG("NO NEXT NODE, GO BACK TO: " + itos(flow_stack_pos)); } } else { - node = next; //stackless mode, simply assign next node + node = next; // Stackless mode, simply assign next node. } } if (error) { - //error - // function, file, line, error, explanation + // Error + // Function, file, line, error, explanation. String err_file = script->get_path(); String err_func = p_method; - int err_line = current_node_id; //not a line but it works as one + int err_line = current_node_id; // Not a line but it works as one. if (node && (r_error.error != Callable::CallError::CALL_ERROR_INVALID_METHOD || error_str == String())) { if (error_str != String()) { @@ -1906,7 +1753,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } #endif - //clean up variant stack + // Clean up variant stack. for (int i = 0; i < f->max_stack; i++) { variant_stack[i].~Variant(); } @@ -1954,7 +1801,7 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)nullptr; for (int i = 0; i < f->node_count; i++) { - sequence_bits[i] = false; //all starts as false + sequence_bits[i] = false; // All starts as false. } zeromem(pass_stack, f->pass_stack_size * sizeof(int)); @@ -1988,12 +1835,12 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p return Variant(); } - //allocate variant stack + // Allocate variant stack. for (int i = 0; i < f->max_stack; i++) { memnew_placement(&variant_stack[i], Variant); } - //allocate function arguments (must be copied for yield to work properly) + // Allocate function arguments (must be copied for yield to work properly). for (int i = 0; i < p_argcount; i++) { variant_stack[i] = *p_args[i]; } @@ -2002,12 +1849,12 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p } void VisualScriptInstance::notification(int p_notification) { - //do nothing as this is called using virtual + // Do nothing as this is called using virtual. Variant what = p_notification; const Variant *whatp = &what; Callable::CallError ce; - call(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); //do as call + call(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); // Do as call. } String VisualScriptInstance::to_string(bool *r_valid) { @@ -2086,7 +1933,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o max_output_args = 0; if (Object::cast_to<Node>(p_owner)) { - //turn on these if they exist and base is a node + // Turn on these if they exist and base is a node. Node *node = Object::cast_to<Node>(p_owner); if (p_script->functions.has("_process")) { node->set_process(true); @@ -2105,190 +1952,236 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } } - for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) { - variables[E->key()] = E->get().default_value; - } - - for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) { - if (E->key() == script->get_default_func()) { - continue; - } - - Function function; - function.node = E->get().function_id; - function.max_stack = 0; - function.flow_stack_size = 0; - function.pass_stack_size = 0; - function.node_count = 0; - - Map<StringName, int> local_var_indices; - - if (function.node < 0) { - VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E->key())); - - ERR_CONTINUE(function.node < 0); + // Setup variables. + { + List<StringName> keys; + script->variables.get_key_list(&keys); + for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) { + variables[E->get()] = script->variables[E->get()].default_value; } + } - { - Ref<VisualScriptFunction> func_node = script->get_node(E->key(), E->get().function_id); - - if (func_node.is_null()) { - VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E->key())); + // Setup functions from sequence trees. + { + List<StringName> keys; + script->functions.get_key_list(&keys); + for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) { + const VisualScript::Function vsfn = p_script->functions[E->get()]; + Function function; + function.node = vsfn.func_id; + function.max_stack = 0; + function.flow_stack_size = 0; + function.pass_stack_size = 0; + function.node_count = 0; + + Map<StringName, int> local_var_indices; + + if (function.node < 0) { + VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E->get())); + ERR_CONTINUE(function.node < 0); } - ERR_CONTINUE(!func_node.is_valid()); + { + Ref<VisualScriptFunction> func_node = script->get_node(vsfn.func_id); - function.argument_count = func_node->get_argument_count(); - function.max_stack += function.argument_count; - function.flow_stack_size = func_node->is_stack_less() ? 0 : func_node->get_stack_size(); - max_input_args = MAX(max_input_args, function.argument_count); - } - - //multiple passes are required to set up this complex thing.. - - //first create the nodes - for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - Ref<VisualScriptNode> node = F->get().node; - - VisualScriptNodeInstance *instance = node->instance(this); //create instance - ERR_FAIL_COND(!instance); - - instance->base = node.ptr(); + if (func_node.is_null()) { + VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E->get())); + } - instance->id = F->key(); - instance->input_port_count = node->get_input_value_port_count(); - instance->input_ports = nullptr; - instance->output_port_count = node->get_output_value_port_count(); - instance->output_ports = nullptr; - instance->sequence_output_count = node->get_output_sequence_port_count(); - instance->sequence_index = function.node_count++; - instance->sequence_outputs = nullptr; - instance->pass_idx = -1; + ERR_CONTINUE(!func_node.is_valid()); - if (instance->input_port_count) { - instance->input_ports = memnew_arr(int, instance->input_port_count); - for (int i = 0; i < instance->input_port_count; i++) { - instance->input_ports[i] = -1; //if not assigned, will become default value - } + function.argument_count = func_node->get_argument_count(); + function.max_stack += function.argument_count; + function.flow_stack_size = func_node->is_stack_less() ? 0 : func_node->get_stack_size(); + max_input_args = MAX(max_input_args, function.argument_count); } - - if (instance->output_port_count) { - instance->output_ports = memnew_arr(int, instance->output_port_count); - for (int i = 0; i < instance->output_port_count; i++) { - instance->output_ports[i] = -1; //if not assigned, will output to trash + // Function nodes graphs. + Set<VisualScript::SequenceConnection> seqconns; + Set<VisualScript::DataConnection> dataconns; + Set<int> node_ids; + node_ids.insert(function.node); + { + List<int> nd_queue; + nd_queue.push_back(function.node); + while (!nd_queue.is_empty()) { + for (const Set<VisualScript::SequenceConnection>::Element *F = script->sequence_connections.front(); F; F = F->next()) { + if (nd_queue.front()->get() == F->get().from_node && !node_ids.has(F->get().to_node)) { + nd_queue.push_back(F->get().to_node); + node_ids.insert(F->get().to_node); + } + if (nd_queue.front()->get() == F->get().from_node && !seqconns.has(F->get())) { + seqconns.insert(F->get()); + } + } + nd_queue.pop_front(); } - } - - if (instance->sequence_output_count) { - instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance *, instance->sequence_output_count); - for (int i = 0; i < instance->sequence_output_count; i++) { - instance->sequence_outputs[i] = nullptr; //if it remains null, flow ends here + HashMap<int, HashMap<int, Pair<int, int>>> dc_lut; // :: to -> to_port -> (from, from_port) + for (const Set<VisualScript::DataConnection>::Element *F = script->data_connections.front(); F; F = F->next()) { + dc_lut[F->get().to_node][F->get().to_port] = Pair<int, int>(F->get().from_node, F->get().from_port); + } + for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + nd_queue.push_back(F->get()); + } + List<int> dc_keys; + while (!nd_queue.is_empty()) { + int ky = nd_queue.front()->get(); + dc_lut[ky].get_key_list(&dc_keys); + for (const List<int>::Element *F = dc_keys.front(); F; F = F->next()) { + VisualScript::DataConnection dc; + dc.from_node = dc_lut[ky][F->get()].first; + dc.from_port = dc_lut[ky][F->get()].second; + dc.to_node = ky; + dc.to_port = F->get(); + dataconns.insert(dc); + nd_queue.push_back(dc.from_node); + node_ids.insert(dc.from_node); + } + dc_keys.clear(); // Necessary as get_key_list does a push_back not a set. + nd_queue.pop_front(); } } - if (Object::cast_to<VisualScriptLocalVar>(node.ptr()) || Object::cast_to<VisualScriptLocalVarSet>(*node)) { - //working memory is shared only for this node, for the same variables - Ref<VisualScriptLocalVar> vslv = node; - - StringName var_name; + //Multiple passes are required to set up this complex thing.. + //First create the nodes. + for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + Ref<VisualScriptNode> node = script->nodes[F->get()].node; + + VisualScriptNodeInstance *instance = node->instance(this); // Create instance. + ERR_FAIL_COND(!instance); + + instance->base = node.ptr(); + + instance->id = F->get(); + instance->input_port_count = node->get_input_value_port_count(); + instance->input_ports = NULL; + instance->output_port_count = node->get_output_value_port_count(); + instance->output_ports = NULL; + instance->sequence_output_count = node->get_output_sequence_port_count(); + instance->sequence_index = function.node_count++; + instance->sequence_outputs = NULL; + instance->pass_idx = -1; + + if (instance->input_port_count) { + instance->input_ports = memnew_arr(int, instance->input_port_count); + for (int i = 0; i < instance->input_port_count; i++) { + instance->input_ports[i] = -1; // If not assigned, will become default value. + } + } - if (Object::cast_to<VisualScriptLocalVar>(*node)) { - var_name = String(Object::cast_to<VisualScriptLocalVar>(*node)->get_var_name()).strip_edges(); - } else { - var_name = String(Object::cast_to<VisualScriptLocalVarSet>(*node)->get_var_name()).strip_edges(); + if (instance->output_port_count) { + instance->output_ports = memnew_arr(int, instance->output_port_count); + for (int i = 0; i < instance->output_port_count; i++) { + instance->output_ports[i] = -1; // If not assigned, will output to trash. + } } - if (!local_var_indices.has(var_name)) { - local_var_indices[var_name] = function.max_stack; - function.max_stack++; + if (instance->sequence_output_count) { + instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance *, instance->sequence_output_count); + for (int i = 0; i < instance->sequence_output_count; i++) { + instance->sequence_outputs[i] = NULL; // If it remains null, flow ends here. + } } - instance->working_mem_idx = local_var_indices[var_name]; + if (Object::cast_to<VisualScriptLocalVar>(node.ptr()) || Object::cast_to<VisualScriptLocalVarSet>(*node)) { + // Working memory is shared only for this node, for the same variables. + Ref<VisualScriptLocalVar> vslv = node; - } else if (instance->get_working_memory_size()) { - instance->working_mem_idx = function.max_stack; - function.max_stack += instance->get_working_memory_size(); - } else { - instance->working_mem_idx = -1; //no working mem - } + StringName var_name; - max_input_args = MAX(max_input_args, instance->input_port_count); - max_output_args = MAX(max_output_args, instance->output_port_count); + if (Object::cast_to<VisualScriptLocalVar>(*node)) + var_name = String(Object::cast_to<VisualScriptLocalVar>(*node)->get_var_name()).strip_edges(); + else + var_name = String(Object::cast_to<VisualScriptLocalVarSet>(*node)->get_var_name()).strip_edges(); - instances[F->key()] = instance; - } + if (!local_var_indices.has(var_name)) { + local_var_indices[var_name] = function.max_stack; + function.max_stack++; + } - function.trash_pos = function.max_stack++; //create pos for trash + instance->working_mem_idx = local_var_indices[var_name]; - //second pass, do data connections + } else if (instance->get_working_memory_size()) { + instance->working_mem_idx = function.max_stack; + function.max_stack += instance->get_working_memory_size(); + } else { + instance->working_mem_idx = -1; //no working mem + } - for (const Set<VisualScript::DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) { - VisualScript::DataConnection dc = F->get(); - ERR_CONTINUE(!instances.has(dc.from_node)); - VisualScriptNodeInstance *from = instances[dc.from_node]; - ERR_CONTINUE(!instances.has(dc.to_node)); - VisualScriptNodeInstance *to = instances[dc.to_node]; - ERR_CONTINUE(dc.from_port >= from->output_port_count); - ERR_CONTINUE(dc.to_port >= to->input_port_count); + max_input_args = MAX(max_input_args, instance->input_port_count); + max_output_args = MAX(max_output_args, instance->output_port_count); - if (from->output_ports[dc.from_port] == -1) { - int stack_pos = function.max_stack++; - from->output_ports[dc.from_port] = stack_pos; + instances[F->get()] = instance; } - if (from->get_sequence_output_count() == 0 && to->dependencies.find(from) == -1) { - //if the node we are reading from has no output sequence, we must call step() before reading from it. - if (from->pass_idx == -1) { - from->pass_idx = function.pass_stack_size; - function.pass_stack_size++; + function.trash_pos = function.max_stack++; // create pos for trash + + // Second pass, do data connections. + for (const Set<VisualScript::DataConnection>::Element *F = dataconns.front(); F; F = F->next()) { + VisualScript::DataConnection dc = F->get(); + ERR_CONTINUE(!instances.has(dc.from_node)); + VisualScriptNodeInstance *from = instances[dc.from_node]; + ERR_CONTINUE(!instances.has(dc.to_node)); + VisualScriptNodeInstance *to = instances[dc.to_node]; + ERR_CONTINUE(dc.from_port >= from->output_port_count); + ERR_CONTINUE(dc.to_port >= to->input_port_count); + + if (from->output_ports[dc.from_port] == -1) { + int stack_pos = function.max_stack++; + from->output_ports[dc.from_port] = stack_pos; } - to->dependencies.push_back(from); - } - - to->input_ports[dc.to_port] = from->output_ports[dc.from_port]; //read from wherever the stack is - } - //third pass, do sequence connections + if (from->get_sequence_output_count() == 0 && to->dependencies.find(from) == -1) { + // If the node we are reading from has no output sequence, we must call step() before reading from it. + if (from->pass_idx == -1) { + from->pass_idx = function.pass_stack_size; + function.pass_stack_size++; + } + to->dependencies.push_back(from); + } - for (const Set<VisualScript::SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) { - VisualScript::SequenceConnection sc = F->get(); - ERR_CONTINUE(!instances.has(sc.from_node)); - VisualScriptNodeInstance *from = instances[sc.from_node]; - ERR_CONTINUE(!instances.has(sc.to_node)); - VisualScriptNodeInstance *to = instances[sc.to_node]; - ERR_CONTINUE(sc.from_output >= from->sequence_output_count); + to->input_ports[dc.to_port] = from->output_ports[dc.from_port]; // Read from wherever the stack is. + } - from->sequence_outputs[sc.from_output] = to; - } + // Third pass, do sequence connections. + for (const Set<VisualScript::SequenceConnection>::Element *F = seqconns.front(); F; F = F->next()) { + VisualScript::SequenceConnection sc = F->get(); + ERR_CONTINUE(!instances.has(sc.from_node)); + VisualScriptNodeInstance *from = instances[sc.from_node]; + ERR_CONTINUE(!instances.has(sc.to_node)); + VisualScriptNodeInstance *to = instances[sc.to_node]; + ERR_CONTINUE(sc.from_output >= from->sequence_output_count); - //fourth pass: - // 1) unassigned input ports to default values - // 2) connect unassigned output ports to trash + from->sequence_outputs[sc.from_output] = to; + } - for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - ERR_CONTINUE(!instances.has(F->key())); + //fourth pass: + // 1) unassigned input ports to default values + // 2) connect unassigned output ports to trash + for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) { + ERR_CONTINUE(!instances.has(F->get())); - Ref<VisualScriptNode> node = F->get().node; - VisualScriptNodeInstance *instance = instances[F->key()]; + Ref<VisualScriptNode> node = script->nodes[F->get()].node; + VisualScriptNodeInstance *instance = instances[F->get()]; - // connect to default values - for (int i = 0; i < instance->input_port_count; i++) { - if (instance->input_ports[i] == -1) { - //unassigned, connect to default val - instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT; - default_values.push_back(node->get_default_input_value(i)); + // Connect to default values. + for (int i = 0; i < instance->input_port_count; i++) { + if (instance->input_ports[i] == -1) { + // Unassigned, connect to default val. + instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT; + default_values.push_back(node->get_default_input_value(i)); + } } - } - // connect to trash - for (int i = 0; i < instance->output_port_count; i++) { - if (instance->output_ports[i] == -1) { - instance->output_ports[i] = function.trash_pos; //trash is same for all + // Connect to trash. + for (int i = 0; i < instance->output_port_count; i++) { + if (instance->output_ports[i] == -1) { + instance->output_ports[i] = function.trash_pos; //trash is same for all + } } } - } - functions[E->key()] = function; + functions[E->get()] = function; + } } } @@ -2354,7 +2247,7 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int Variant *working_mem = ((Variant *)stack.ptr()) + working_mem_index; - *working_mem = args; //arguments go to working mem. + *working_mem = args; // Arguments go to working mem. Variant ret = instance->_call_internal(function, stack.ptrw(), stack.size(), node, flow_stack_pos, pass, true, r_error); function = StringName(); //invalidate @@ -2367,7 +2260,7 @@ void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p binds.push_back(p_binds[i]); } binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing - p_obj->connect_compat(p_signal, this, "_signal_callback", binds, CONNECT_ONESHOT); + p_obj->connect(p_signal, Callable(this, "_signal_callback"), binds, CONNECT_ONESHOT); } bool VisualScriptFunctionState::is_valid() const { @@ -2388,7 +2281,7 @@ Variant VisualScriptFunctionState::resume(Array p_args) { Variant *working_mem = ((Variant *)stack.ptr()) + working_mem_index; - *working_mem = p_args; //arguments go to working mem. + *working_mem = p_args; // Arguments go to working mem. Variant ret = instance->_call_internal(function, stack.ptrw(), stack.size(), node, flow_stack_pos, pass, true, r_error); function = StringName(); //invalidate @@ -2498,7 +2391,7 @@ void VisualScriptLanguage::add_global_constant(const StringName &p_variable, con /* DEBUGGER FUNCTIONS */ bool VisualScriptLanguage::debug_break_parse(const String &p_file, int p_node, const String &p_error) { - //break because of parse error + // Break because of parse error. if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { _debug_parse_err_node = p_node; @@ -2635,7 +2528,6 @@ void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String f->debug_get_stack_member_state(*_call_stack[l].line,&locals); for( List<Pair<StringName,int> >::Element *E = locals.front();E;E=E->next() ) { - p_locals->push_back(E->get().first); p_values->push_back(_call_stack[l].stack[E->get().second]); } @@ -2667,7 +2559,7 @@ void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<Strin } void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - //no globals are really reachable in gdscript + // No globals are really reachable in gdscript. } String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { @@ -2743,7 +2635,7 @@ VisualScriptLanguage::VisualScriptLanguage() { ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/visual_script/max_call_stack", PropertyInfo(Variant::INT, "debug/settings/visual_script/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater")); //minimum is 1024 if (EngineDebugger::is_active()) { - //debugging enabled! + // Debugging enabled! _debug_max_call_stack = dmcs; _call_stack = memnew_arr(CallLevel, _debug_max_call_stack + 1); diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index cb5ed37ba1..bdb3c3a16b 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,8 +33,9 @@ #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" +#include "core/doc_data.h" +#include "core/object/script_language.h" #include "core/os/thread.h" -#include "core/script_language.h" class VisualScriptInstance; class VisualScriptNodeInstance; @@ -45,7 +46,7 @@ class VisualScriptNode : public Resource { friend class VisualScript; - Set<VisualScript *> scripts_used; + Ref<VisualScript> script_used; Array default_input_values; bool breakpoint; @@ -82,7 +83,7 @@ public: virtual String get_text() const; virtual String get_category() const = 0; - //used by editor, this is not really saved + // Used by editor, this is not really saved. void set_breakpoint(bool p_breakpoint); bool is_breakpoint() const; @@ -105,9 +106,9 @@ public: class VisualScriptNodeInstance { friend class VisualScriptInstance; - friend class VisualScriptLanguage; //for debugger + friend class VisualScriptLanguage; // For debugger. - enum { //input argument addressing + enum { // Input argument addressing. INPUT_SHIFT = 1 << 24, INPUT_MASK = INPUT_SHIFT - 1, INPUT_DEFAULT_VALUE_BIT = INPUT_SHIFT, // from unassigned input port, using default value (edited by user) @@ -137,13 +138,13 @@ public: enum { STEP_SHIFT = 1 << 24, STEP_MASK = STEP_SHIFT - 1, - STEP_FLAG_PUSH_STACK_BIT = STEP_SHIFT, //push bit to stack - STEP_FLAG_GO_BACK_BIT = STEP_SHIFT << 1, //go back to previous node - STEP_NO_ADVANCE_BIT = STEP_SHIFT << 2, //do not advance past this node - STEP_EXIT_FUNCTION_BIT = STEP_SHIFT << 3, //return from function - STEP_YIELD_BIT = STEP_SHIFT << 4, //yield (will find VisualScriptFunctionState state in first working memory) + STEP_FLAG_PUSH_STACK_BIT = STEP_SHIFT, // push bit to stack + STEP_FLAG_GO_BACK_BIT = STEP_SHIFT << 1, // go back to previous node + STEP_NO_ADVANCE_BIT = STEP_SHIFT << 2, // do not advance past this node + STEP_EXIT_FUNCTION_BIT = STEP_SHIFT << 3, // return from function + STEP_YIELD_BIT = STEP_SHIFT << 4, // yield (will find VisualScriptFunctionState state in first working memory) - FLOW_STACK_PUSHED_BIT = 1 << 30, //in flow stack, means bit was pushed (must go back here if end of sequence) + FLOW_STACK_PUSHED_BIT = 1 << 30, // in flow stack, means bit was pushed (must go back here if end of sequence) FLOW_STACK_MASK = FLOW_STACK_PUSHED_BIT - 1 }; @@ -156,7 +157,7 @@ public: virtual int get_working_memory_size() const { return 0; } - virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) = 0; //do a step, return which sequence port to go out + virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) = 0; // Do a step, return which sequence port to go out. Ref<VisualScriptNode> get_base_node() { return Ref<VisualScriptNode>(base); } @@ -210,34 +211,32 @@ private: Variant::Type type; }; - struct Function { - struct NodeData { - Point2 pos; - Ref<VisualScriptNode> node; - }; - - Map<int, NodeData> nodes; - - Set<SequenceConnection> sequence_connections; + struct NodeData { + Point2 pos; + Ref<VisualScriptNode> node; + }; - Set<DataConnection> data_connections; + HashMap<int, NodeData> nodes; // Can be a sparse map. - int function_id; + Set<SequenceConnection> sequence_connections; + Set<DataConnection> data_connections; - Vector2 scroll; + Vector2 scroll; - Function() { function_id = -1; } + struct Function { + int func_id; + Function() { func_id = -1; } }; struct Variable { PropertyInfo info; Variant default_value; bool _export; - // add getter & setter options here + // Add getter & setter options here. }; - Map<StringName, Function> functions; - Map<StringName, Variable> variables; + HashMap<StringName, Function> functions; + HashMap<StringName, Variable> variables; Map<StringName, Vector<Argument>> custom_signals; Vector<ScriptNetData> rpc_functions; Vector<ScriptNetData> rpc_variables; @@ -248,7 +247,7 @@ private: #ifdef TOOLS_ENABLED Set<PlaceHolderScriptInstance *> placeholders; - //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); + // void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override; void _update_placeholders(); #endif @@ -266,37 +265,38 @@ protected: public: bool inherits_script(const Ref<Script> &p_script) const override; - // TODO: Remove it in future when breaking changes are acceptable - StringName get_default_func() const; - void add_function(const StringName &p_name); + void set_scroll(const Vector2 &p_scroll); + Vector2 get_scroll() const; + + void add_function(const StringName &p_name, int p_func_node_id); bool has_function(const StringName &p_name) const; void remove_function(const StringName &p_name); void rename_function(const StringName &p_name, const StringName &p_new_name); - void set_function_scroll(const StringName &p_name, const Vector2 &p_scroll); - Vector2 get_function_scroll(const StringName &p_name) const; void get_function_list(List<StringName> *r_functions) const; int get_function_node_id(const StringName &p_name) const; void set_tool_enabled(bool p_enabled); - void add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos = Point2()); - void remove_node(const StringName &p_func, int p_id); - bool has_node(const StringName &p_func, int p_id) const; - Ref<VisualScriptNode> get_node(const StringName &p_func, int p_id) const; - void set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos); - Point2 get_node_position(const StringName &p_func, int p_id) const; - void get_node_list(const StringName &p_func, List<int> *r_nodes) const; - - void sequence_connect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node); - void sequence_disconnect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node); - bool has_sequence_connection(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) const; - void get_sequence_connection_list(const StringName &p_func, List<SequenceConnection> *r_connection) const; - - void data_connect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port); - void data_disconnect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port); - bool has_data_connection(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const; - void get_data_connection_list(const StringName &p_func, List<DataConnection> *r_connection) const; - bool is_input_value_port_connected(const StringName &p_func, int p_node, int p_port) const; - bool get_input_value_port_connection_source(const StringName &p_func, int p_node, int p_port, int *r_node, int *r_port) const; + void add_node(int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos = Point2()); + void remove_node(int p_id); + bool has_node(int p_id) const; + Ref<VisualScriptNode> get_node(int p_id) const; + void set_node_position(int p_id, const Point2 &p_pos); + Point2 get_node_position(int p_id) const; + void get_node_list(List<int> *r_nodes) const; + + void sequence_connect(int p_from_node, int p_from_output, int p_to_node); + void sequence_disconnect(int p_from_node, int p_from_output, int p_to_node); + bool has_sequence_connection(int p_from_node, int p_from_output, int p_to_node) const; + void get_sequence_connection_list(List<SequenceConnection> *r_connection) const; + Set<int> get_output_sequence_ports_connected(int from_node); + + void data_connect(int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void data_disconnect(int p_from_node, int p_from_port, int p_to_node, int p_to_port); + bool has_data_connection(int p_from_node, int p_from_port, int p_to_node, int p_to_port) const; + void get_data_connection_list(List<DataConnection> *r_connection) const; + + bool is_input_value_port_connected(int p_node, int p_port) const; + bool get_input_value_port_connection_source(int p_node, int p_port, int *r_node, int *r_port) const; void add_variable(const StringName &p_name, const Variant &p_default_value = Variant(), bool p_export = false); bool has_variable(const StringName &p_name) const; @@ -342,6 +342,13 @@ public: virtual void set_source_code(const String &p_code) override; virtual Error reload(bool p_keep_state = false) override; +#ifdef TOOLS_ENABLED + virtual const Vector<DocData::ClassDoc> &get_documentation() const override { + static Vector<DocData::ClassDoc> docs; + return docs; + } +#endif // TOOLS_ENABLED + virtual bool is_tool() const override; virtual bool is_valid() const override; @@ -384,7 +391,7 @@ class VisualScriptInstance : public ScriptInstance { Object *owner; Ref<VisualScript> script; - Map<StringName, Variant> variables; //using variable path, not script + Map<StringName, Variant> variables; // Using variable path, not script. Map<int, VisualScriptNodeInstance *> instances; struct Function { @@ -407,9 +414,8 @@ class VisualScriptInstance : public ScriptInstance { void _dependency_step(VisualScriptNodeInstance *node, int p_pass, int *pass_stack, const Variant **input_args, Variant **output_args, Variant *variant_stack, Callable::CallError &r_error, String &error_str, VisualScriptNodeInstance **r_error_node); Variant _call_internal(const StringName &p_method, void *p_stack, int p_stack_size, VisualScriptNodeInstance *p_node, int p_flow_stack_pos, int p_pass, bool p_resuming_yield, Callable::CallError &r_error); - //Map<StringName,Function> functions; - friend class VisualScriptFunctionState; //for yield - friend class VisualScriptLanguage; //for debugger + friend class VisualScriptFunctionState; // For yield. + friend class VisualScriptLanguage; // For debugger. public: virtual bool set(const StringName &p_name, const Variant &p_value); virtual bool get(const StringName &p_name, Variant &r_ret) const; @@ -530,7 +536,7 @@ public: _FORCE_INLINE_ void enter_function(VisualScriptInstance *p_instance, const StringName *p_function, Variant *p_stack, Variant **p_work_mem, int *current_id) { if (Thread::get_main_id() != Thread::get_caller_id()) { - return; //no support for other threads than main for now + return; // No support for other threads than main for now. } if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { @@ -538,7 +544,7 @@ public: } if (_debug_call_stack_pos >= _debug_max_call_stack) { - //stack overflow + // Stack overflow. _debug_error = "Stack Overflow (Stack Size: " + itos(_debug_max_call_stack) + ")"; EngineDebugger::get_script_debugger()->debug(this); return; @@ -554,7 +560,7 @@ public: _FORCE_INLINE_ void exit_function() { if (Thread::get_main_id() != Thread::get_caller_id()) { - return; //no support for other threads than main for now + return; // No support for other threads than main for now. } if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { @@ -632,7 +638,7 @@ public: ~VisualScriptLanguage(); }; -//aid for registering +// Aid for registering. template <class T> static Ref<VisualScriptNode> create_node_generic(const String &p_name) { Ref<T> node; diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index a0dcd76d10..2558c1d7ec 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,12 @@ #include "visual_script_builtin_funcs.h" -#include "core/class_db.h" -#include "core/func_ref.h" #include "core/io/marshalls.h" #include "core/math/math_funcs.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" #include "core/os/os.h" -#include "core/reference.h" -#include "core/variant_parser.h" +#include "core/variant/variant_parser.h" const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX] = { "sin", @@ -64,7 +63,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "is_inf", "ease", "step_decimals", - "stepify", + "snapped", "lerp", "inverse_lerp", "range_lerp", @@ -73,7 +72,8 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "randomize", "randi", "randf", - "rand_range", + "randf_range", + "randi_range", "seed", "rand_seed", "deg2rad", @@ -89,7 +89,6 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "clamp", "nearest_po2", "weakref", - "funcref", "convert", "typeof", "type_exists", @@ -143,7 +142,7 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const { int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { switch (p_func) { case MATH_RANDOMIZE: - case MATH_RAND: + case MATH_RANDI: case MATH_RANDF: return 0; case MATH_SIN: @@ -193,13 +192,13 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { case MATH_POSMOD: case MATH_POW: case MATH_EASE: - case MATH_STEPIFY: - case MATH_RANDOM: + case MATH_SNAPPED: + case MATH_RANDF_RANGE: + case MATH_RANDI_RANGE: case MATH_POLAR2CARTESIAN: case MATH_CARTESIAN2POLAR: case LOGIC_MAX: case LOGIC_MIN: - case FUNC_FUNCREF: case TYPE_CONVERT: case COLORN: return 2; @@ -310,7 +309,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case MATH_STEP_DECIMALS: { return PropertyInfo(Variant::FLOAT, "step"); } break; - case MATH_STEPIFY: { + case MATH_SNAPPED: { if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "s"); } else { @@ -361,16 +360,23 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const } } break; case MATH_RANDOMIZE: - case MATH_RAND: + case MATH_RANDI: case MATH_RANDF: { } break; - case MATH_RANDOM: { + case MATH_RANDF_RANGE: { if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "from"); } else { return PropertyInfo(Variant::FLOAT, "to"); } } break; + case MATH_RANDI_RANGE: { + if (p_idx == 0) { + return PropertyInfo(Variant::INT, "from"); + } else { + return PropertyInfo(Variant::INT, "to"); + } + } break; case MATH_SEED: case MATH_RANDSEED: { return PropertyInfo(Variant::INT, "seed"); @@ -426,13 +432,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case OBJ_WEAKREF: { return PropertyInfo(Variant::OBJECT, "source"); } break; - case FUNC_FUNCREF: { - if (p_idx == 0) { - return PropertyInfo(Variant::OBJECT, "instance"); - } else { - return PropertyInfo(Variant::STRING, "funcname"); - } - } break; case TYPE_CONVERT: { if (p_idx == 0) { return PropertyInfo(Variant::NIL, "what"); @@ -538,7 +537,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case MATH_STEP_DECIMALS: { t = Variant::INT; } break; - case MATH_STEPIFY: + case MATH_SNAPPED: case MATH_LERP: case MATH_LERP_ANGLE: case MATH_INVERSE_LERP: @@ -551,13 +550,16 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case MATH_RANDOMIZE: { } break; - case MATH_RAND: { + case MATH_RANDI: { t = Variant::INT; } break; case MATH_RANDF: - case MATH_RANDOM: { + case MATH_RANDF_RANGE: { t = Variant::FLOAT; } break; + case MATH_RANDI_RANGE: { + t = Variant::INT; + } break; case MATH_SEED: { } break; case MATH_RANDSEED: { @@ -593,10 +595,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons t = Variant::OBJECT; } break; - case FUNC_FUNCREF: { - t = Variant::OBJECT; - - } break; case TYPE_CONVERT: { } break; case TEXT_ORD: @@ -649,7 +647,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons /* String VisualScriptBuiltinFunc::get_caption() const { - return "BuiltinFunc"; } @@ -808,10 +805,10 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(0); *r_return = Math::step_decimals((double)*p_inputs[0]); } break; - case VisualScriptBuiltinFunc::MATH_STEPIFY: { + case VisualScriptBuiltinFunc::MATH_SNAPPED: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); - *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]); + *r_return = Math::snapped((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LERP: { VALIDATE_ARG_NUM(0); @@ -861,17 +858,22 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in Math::randomize(); } break; - case VisualScriptBuiltinFunc::MATH_RAND: { + case VisualScriptBuiltinFunc::MATH_RANDI: { *r_return = Math::rand(); } break; case VisualScriptBuiltinFunc::MATH_RANDF: { *r_return = Math::randf(); } break; - case VisualScriptBuiltinFunc::MATH_RANDOM: { + case VisualScriptBuiltinFunc::MATH_RANDF_RANGE: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]); } break; + case VisualScriptBuiltinFunc::MATH_RANDI_RANGE: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return = Math::random((int)*p_inputs[0], (int)*p_inputs[1]); + } break; case VisualScriptBuiltinFunc::MATH_SEED: { VALIDATE_ARG_NUM(0); uint64_t seed = *p_inputs[0]; @@ -1013,30 +1015,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } } break; - case VisualScriptBuiltinFunc::FUNC_FUNCREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - - return; - } - if (p_inputs[1]->get_type() != Variant::STRING && p_inputs[1]->get_type() != Variant::NODE_PATH) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::STRING; - - return; - } - - Ref<FuncRef> fr = memnew(FuncRef); - - fr->set_instance(*p_inputs[0]); - fr->set_function(*p_inputs[1]); - - *r_return = fr; - - } break; case VisualScriptBuiltinFunc::TYPE_CONVERT: { VALIDATE_ARG_NUM(1); int type = *p_inputs[1]; @@ -1048,7 +1026,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in return; } else { - *r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error); + Variant::construct(Variant::Type(type), *r_return, p_inputs, 1, r_error); } } break; case VisualScriptBuiltinFunc::TYPE_OF: { @@ -1060,7 +1038,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::TEXT_CHAR: { - CharType result[2] = { *p_inputs[0], 0 }; + char32_t result[2] = { *p_inputs[0], 0 }; *r_return = String(result); @@ -1276,16 +1254,17 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(MATH_ISINF); BIND_ENUM_CONSTANT(MATH_EASE); BIND_ENUM_CONSTANT(MATH_STEP_DECIMALS); - BIND_ENUM_CONSTANT(MATH_STEPIFY); + BIND_ENUM_CONSTANT(MATH_SNAPPED); BIND_ENUM_CONSTANT(MATH_LERP); BIND_ENUM_CONSTANT(MATH_INVERSE_LERP); BIND_ENUM_CONSTANT(MATH_RANGE_LERP); BIND_ENUM_CONSTANT(MATH_MOVE_TOWARD); BIND_ENUM_CONSTANT(MATH_DECTIME); BIND_ENUM_CONSTANT(MATH_RANDOMIZE); - BIND_ENUM_CONSTANT(MATH_RAND); + BIND_ENUM_CONSTANT(MATH_RANDI); BIND_ENUM_CONSTANT(MATH_RANDF); - BIND_ENUM_CONSTANT(MATH_RANDOM); + BIND_ENUM_CONSTANT(MATH_RANDF_RANGE); + BIND_ENUM_CONSTANT(MATH_RANDI_RANGE); BIND_ENUM_CONSTANT(MATH_SEED); BIND_ENUM_CONSTANT(MATH_RANDSEED); BIND_ENUM_CONSTANT(MATH_DEG2RAD); @@ -1301,7 +1280,6 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(LOGIC_CLAMP); BIND_ENUM_CONSTANT(LOGIC_NEAREST_PO2); BIND_ENUM_CONSTANT(OBJ_WEAKREF); - BIND_ENUM_CONSTANT(FUNC_FUNCREF); BIND_ENUM_CONSTANT(TYPE_CONVERT); BIND_ENUM_CONSTANT(TYPE_OF); BIND_ENUM_CONSTANT(TYPE_EXISTS); @@ -1366,7 +1344,7 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/ease", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_EASE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/step_decimals", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEP_DECIMALS>); - VisualScriptLanguage::singleton->add_register_func("functions/built_in/stepify", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_STEPIFY>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/snapped", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SNAPPED>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp_angle", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP_ANGLE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/inverse_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_INVERSE_LERP>); @@ -1375,9 +1353,10 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/move_toward", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_MOVE_TOWARD>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>); - VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDI>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>); - VisualScriptLanguage::singleton->add_register_func("functions/built_in/random", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOM>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf_range", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF_RANGE>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randi_range", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDI_RANGE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/seed", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randseed", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>); @@ -1396,7 +1375,6 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/nearest_po2", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/weakref", create_builtin_func_node<VisualScriptBuiltinFunc::OBJ_WEAKREF>); - VisualScriptLanguage::singleton->add_register_func("functions/built_in/funcref", create_builtin_func_node<VisualScriptBuiltinFunc::FUNC_FUNCREF>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/convert", create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/typeof", create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/type_exists", create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index aee2ed79ce..eaa2ef41e2 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -63,16 +63,17 @@ public: MATH_ISINF, MATH_EASE, MATH_STEP_DECIMALS, - MATH_STEPIFY, + MATH_SNAPPED, MATH_LERP, MATH_INVERSE_LERP, MATH_RANGE_LERP, MATH_MOVE_TOWARD, MATH_DECTIME, MATH_RANDOMIZE, - MATH_RAND, + MATH_RANDI, MATH_RANDF, - MATH_RANDOM, + MATH_RANDF_RANGE, + MATH_RANDI_RANGE, MATH_SEED, MATH_RANDSEED, MATH_DEG2RAD, @@ -88,7 +89,6 @@ public: LOGIC_CLAMP, LOGIC_NEAREST_PO2, OBJ_WEAKREF, - FUNC_FUNCREF, TYPE_CONVERT, TYPE_OF, TYPE_EXISTS, diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 5581ea9318..78e4a7f113 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #include "visual_script_editor.h" #include "core/input/input.h" -#include "core/object.h" +#include "core/object/class_db.h" +#include "core/object/script_language.h" #include "core/os/keyboard.h" -#include "core/script_language.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" @@ -199,7 +199,7 @@ protected: emit_signal("changed"); } void _var_value_changed() { - _change_notify("value"); //so the whole tree is not redrawn, makes editing smoother in general + _change_notify("value"); // So the whole tree is not redrawn, makes editing smoother in general. emit_signal("changed"); } @@ -227,6 +227,19 @@ protected: undo_redo->create_action(TTR("Set Variable Type")); undo_redo->add_do_method(script.ptr(), "set_variable_info", var, dc); undo_redo->add_undo_method(script.ptr(), "set_variable_info", var, d); + + // Setting the default value. + Variant::Type type = (Variant::Type)(int)p_value; + if (type != Variant::NIL) { + Variant default_value; + Callable::CallError ce; + Variant::construct(type, default_value, nullptr, 0, ce); + if (ce.error == Callable::CallError::CALL_OK) { + undo_redo->add_do_method(script.ptr(), "set_variable_default_value", var, default_value); + undo_redo->add_undo_method(script.ptr(), "set_variable_default_value", var, dc["value"]); + } + } + undo_redo->add_do_method(this, "_var_changed"); undo_redo->add_undo_method(this, "_var_changed"); undo_redo->commit_action(); @@ -309,7 +322,7 @@ protected: } p_list->push_back(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt)); p_list->push_back(PropertyInfo(script->get_variable_info(var).type, "value", script->get_variable_info(var).hint, script->get_variable_info(var).hint_string, PROPERTY_USAGE_DEFAULT)); - // Update this when PropertyHint changes + // Update this when PropertyHint changes. p_list->push_back(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,ExpRange,Enum,ExpEasing,Length,SpriteFrame,KeyAccel,Flags,Layers2dRender,Layers2dPhysics,Layer3dRender,Layer3dPhysics,File,Dir,GlobalFile,GlobalDir,ResourceType,MultilineText,PlaceholderText,ColorNoAlpha,ImageCompressLossy,ImageCompressLossLess,ObjectId,String,NodePathToEditedNode,MethodOfVariantType,MethodOfBaseType,MethodOfInstance,MethodOfScript,PropertyOfVariantType,PropertyOfBaseType,PropertyOfInstance,PropertyOfScript,ObjectTooBig,NodePathValidTypes")); p_list->push_back(PropertyInfo(Variant::STRING, "hint_string")); p_list->push_back(PropertyInfo(Variant::BOOL, "export")); @@ -388,7 +401,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; - case Variant::_RID: + case Variant::RID: color = Color(0.41, 0.93, 0.6); break; case Variant::OBJECT: @@ -494,7 +507,7 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; - case Variant::_RID: + case Variant::RID: color = Color(0.17, 0.9, 0.45); break; case Variant::OBJECT: @@ -546,39 +559,29 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { void VisualScriptEditor::_update_graph_connections() { graph->clear_connections(); - List<StringName> funcs; - script->get_function_list(&funcs); + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(&sequence_conns); - if (funcs.size() <= 0) { - updating_graph = false; - return; + for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { + graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0); } - for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { - List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(F->get(), &sequence_conns); - - for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0); - } - - List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(F->get(), &data_conns); + List<VisualScript::DataConnection> data_conns; + script->get_data_connection_list(&data_conns); - for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { - VisualScript::DataConnection dc = E->get(); + for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { + VisualScript::DataConnection dc = E->get(); - Ref<VisualScriptNode> from_node = script->get_node(F->get(), E->get().from_node); - Ref<VisualScriptNode> to_node = script->get_node(F->get(), E->get().to_node); + Ref<VisualScriptNode> from_node = script->get_node(E->get().from_node); + Ref<VisualScriptNode> to_node = script->get_node(E->get().to_node); - if (to_node->has_input_sequence_port()) { - dc.to_port++; - } + if (to_node->has_input_sequence_port()) { + dc.to_port++; + } - dc.from_port += from_node->get_output_sequence_port_count(); + dc.from_port += from_node->get_output_sequence_port_count(); - graph->connect_node(itos(E->get().from_node), dc.from_port, itos(E->get().to_node), dc.to_port); - } + graph->connect_node(itos(E->get().from_node), dc.from_port, itos(E->get().to_node), dc.to_port); } } @@ -605,17 +608,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } } } - - List<StringName> funcs; - script->get_function_list(&funcs); - - if (funcs.size() <= 0) { - graph->hide(); - select_func_text->show(); - updating_graph = false; - return; - } - graph->show(); select_func_text->hide(); @@ -655,347 +647,351 @@ void VisualScriptEditor::_update_graph(int p_only_id) { }; Ref<Texture2D> seq_port = Control::get_theme_icon("VisualShaderPort", "EditorIcons"); + List<int> node_ids; + script->get_node_list(&node_ids); - for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions - - List<int> ids; - script->get_node_list(F->get(), &ids); - StringName editor_icons = "EditorIcons"; + List<int> ids; + script->get_node_list(&ids); + StringName editor_icons = "EditorIcons"; - for (List<int>::Element *E = ids.front(); E; E = E->next()) { - if (p_only_id >= 0 && p_only_id != E->get()) { - continue; - } + for (List<int>::Element *E = ids.front(); E; E = E->next()) { + if (p_only_id >= 0 && p_only_id != E->get()) { + continue; + } - Ref<VisualScriptNode> node = script->get_node(F->get(), E->get()); - Vector2 pos = script->get_node_position(F->get(), E->get()); + Ref<VisualScriptNode> node = script->get_node(E->get()); + Vector2 pos = script->get_node_position(E->get()); - GraphNode *gnode = memnew(GraphNode); - gnode->set_title(node->get_caption()); - gnode->set_offset(pos * EDSCALE); - if (error_line == E->get()) { - gnode->set_overlay(GraphNode::OVERLAY_POSITION); - } else if (node->is_breakpoint()) { - gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT); - } + GraphNode *gnode = memnew(GraphNode); + gnode->set_title(node->get_caption()); + gnode->set_position_offset(pos * EDSCALE); + if (error_line == E->get()) { + gnode->set_overlay(GraphNode::OVERLAY_POSITION); + } else if (node->is_breakpoint()) { + gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT); + } - gnode->set_meta("__vnode", node); - gnode->set_name(itos(E->get())); - gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E->get())); - gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E->get()), CONNECT_DEFERRED); + gnode->set_meta("__vnode", node); + gnode->set_name(itos(E->get())); + gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E->get())); + gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E->get()), CONNECT_DEFERRED); - if (E->get() != script->get_function_node_id(F->get())) { - //function can't be erased + { + Ref<VisualScriptFunction> v = node; + if (!v.is_valid()) { gnode->set_show_close_button(true); } + } - bool has_gnode_text = false; + bool has_gnode_text = false; - Ref<VisualScriptLists> nd_list = node; - bool is_vslist = nd_list.is_valid(); - if (is_vslist) { - HBoxContainer *hbnc = memnew(HBoxContainer); + Ref<VisualScriptLists> nd_list = node; + bool is_vslist = nd_list.is_valid(); + if (is_vslist) { + HBoxContainer *hbnc = memnew(HBoxContainer); + if (nd_list->is_input_port_editable()) { + has_gnode_text = true; + Button *btn = memnew(Button); + btn->set_text(TTR("Add Input Port")); + hbnc->add_child(btn); + btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E->get()), CONNECT_DEFERRED); + } + if (nd_list->is_output_port_editable()) { if (nd_list->is_input_port_editable()) { - has_gnode_text = true; - Button *btn = memnew(Button); - btn->set_text(TTR("Add Input Port")); - hbnc->add_child(btn); - btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E->get()), CONNECT_DEFERRED); - } - if (nd_list->is_output_port_editable()) { - if (nd_list->is_input_port_editable()) { - hbnc->add_spacer(); - } - has_gnode_text = true; - Button *btn = memnew(Button); - btn->set_text(TTR("Add Output Port")); - hbnc->add_child(btn); - btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E->get()), CONNECT_DEFERRED); + hbnc->add_spacer(); } - gnode->add_child(hbnc); - } else if (Object::cast_to<VisualScriptExpression>(node.ptr())) { has_gnode_text = true; - LineEdit *line_edit = memnew(LineEdit); - line_edit->set_text(node->get_text()); - line_edit->set_expand_to_text_length(true); - line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts")); - gnode->add_child(line_edit); - line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get())); - } else { - String text = node->get_text(); - if (!text.empty()) { - has_gnode_text = true; - Label *label = memnew(Label); - label->set_text(text); - gnode->add_child(label); - } + Button *btn = memnew(Button); + btn->set_text(TTR("Add Output Port")); + hbnc->add_child(btn); + btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E->get()), CONNECT_DEFERRED); } - - if (Object::cast_to<VisualScriptComment>(node.ptr())) { - Ref<VisualScriptComment> vsc = node; - gnode->set_comment(true); - gnode->set_resizable(true); - gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE); - gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E->get())); + gnode->add_child(hbnc); + } else if (Object::cast_to<VisualScriptExpression>(node.ptr())) { + has_gnode_text = true; + LineEdit *line_edit = memnew(LineEdit); + line_edit->set_text(node->get_text()); + line_edit->set_expand_to_text_length(true); + line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts")); + gnode->add_child(line_edit); + line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get())); + } else { + String text = node->get_text(); + if (!text.is_empty()) { + has_gnode_text = true; + Label *label = memnew(Label); + label->set_text(text); + gnode->add_child(label); } + } - if (node_styles.has(node->get_category())) { - Ref<StyleBoxFlat> sbf = node_styles[node->get_category()]; - if (gnode->is_comment()) { - sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode"); - } + if (Object::cast_to<VisualScriptComment>(node.ptr())) { + Ref<VisualScriptComment> vsc = node; + gnode->set_comment(true); + gnode->set_resizable(true); + gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE); + gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E->get())); + } - Color c = sbf->get_border_color(); - Color ic = c; - c.a = 1; - if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Color mono_color; - if (((c.r + c.g + c.b) / 3) < 0.7) { - mono_color = Color(1.0, 1.0, 1.0); - ic = Color(0.0, 0.0, 0.0, 0.7); - } else { - mono_color = Color(0.0, 0.0, 0.0); - ic = Color(1.0, 1.0, 1.0, 0.7); - } - mono_color.a = 0.85; - c = mono_color; + if (node_styles.has(node->get_category())) { + Ref<StyleBoxFlat> sbf = node_styles[node->get_category()]; + if (gnode->is_comment()) { + sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode"); + } + + Color c = sbf->get_border_color(); + Color ic = c; + c.a = 1; + if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { + Color mono_color; + if (((c.r + c.g + c.b) / 3) < 0.7) { + mono_color = Color(1.0, 1.0, 1.0); + ic = Color(0.0, 0.0, 0.0, 0.7); + } else { + mono_color = Color(0.0, 0.0, 0.0); + ic = Color(1.0, 1.0, 1.0, 0.7); } - gnode->add_theme_color_override("title_color", c); - c.a = 0.7; - gnode->add_theme_color_override("close_color", c); - gnode->add_theme_color_override("resizer_color", ic); - gnode->add_theme_style_override("frame", sbf); + mono_color.a = 0.85; + c = mono_color; } + gnode->add_theme_color_override("title_color", c); + c.a = 0.7; + gnode->add_theme_color_override("close_color", c); + gnode->add_theme_color_override("resizer_color", ic); + gnode->add_theme_style_override("frame", sbf); + } - const Color mono_color = get_theme_color("mono_color", "Editor"); + const Color mono_color = get_theme_color("mono_color", "Editor"); - int slot_idx = 0; + int slot_idx = 0; - bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String(); - if ((node->has_input_sequence_port() || single_seq_output) || has_gnode_text) { - // IF has_gnode_text is true BUT we have no sequence ports to draw (in here), - // we still draw the disabled default ones to shift up the slots by one, - // so the slots DON'T start with the content text. + bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String(); + if ((node->has_input_sequence_port() || single_seq_output) || has_gnode_text) { + // IF has_gnode_text is true BUT we have no sequence ports to draw (in here), + // we still draw the disabled default ones to shift up the slots by one, + // so the slots DON'T start with the content text. - // IF has_gnode_text is false, but we DO want to draw default sequence ports, - // we draw a dummy text to take up the position of the sequence nodes, so all the other ports are still aligned correctly. - if (!has_gnode_text) { - Label *dummy = memnew(Label); - dummy->set_text(" "); - gnode->add_child(dummy); - } - gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); - slot_idx++; + // IF has_gnode_text is false, but we DO want to draw default sequence ports, + // we draw a dummy text to take up the position of the sequence nodes, so all the other ports are still aligned correctly. + if (!has_gnode_text) { + Label *dummy = memnew(Label); + dummy->set_text(" "); + gnode->add_child(dummy); } + gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); + slot_idx++; + } - int mixed_seq_ports = 0; + int mixed_seq_ports = 0; - if (!single_seq_output) { - if (node->has_mixed_input_and_sequence_ports()) { - mixed_seq_ports = node->get_output_sequence_port_count(); - } else { - for (int i = 0; i < node->get_output_sequence_port_count(); i++) { - Label *text2 = memnew(Label); - text2->set_text(node->get_output_sequence_port_text(i)); - text2->set_align(Label::ALIGN_RIGHT); - gnode->add_child(text2); - gnode->set_slot(slot_idx, false, 0, Color(), true, TYPE_SEQUENCE, mono_color, seq_port, seq_port); - slot_idx++; - } + if (!single_seq_output) { + if (node->has_mixed_input_and_sequence_ports()) { + mixed_seq_ports = node->get_output_sequence_port_count(); + } else { + for (int i = 0; i < node->get_output_sequence_port_count(); i++) { + Label *text2 = memnew(Label); + text2->set_text(node->get_output_sequence_port_text(i)); + text2->set_align(Label::ALIGN_RIGHT); + gnode->add_child(text2); + gnode->set_slot(slot_idx, false, 0, Color(), true, TYPE_SEQUENCE, mono_color, seq_port, seq_port); + slot_idx++; } } + } - for (int i = 0; i < MAX(node->get_output_value_port_count(), MAX(mixed_seq_ports, node->get_input_value_port_count())); i++) { - bool left_ok = false; - Variant::Type left_type = Variant::NIL; - String left_name; + for (int i = 0; i < MAX(node->get_output_value_port_count(), MAX(mixed_seq_ports, node->get_input_value_port_count())); i++) { + bool left_ok = false; + Variant::Type left_type = Variant::NIL; + String left_name; - if (i < node->get_input_value_port_count()) { - PropertyInfo pi = node->get_input_value_port_info(i); - left_ok = true; - left_type = pi.type; - left_name = pi.name; - } + if (i < node->get_input_value_port_count()) { + PropertyInfo pi = node->get_input_value_port_info(i); + left_ok = true; + left_type = pi.type; + left_name = pi.name; + } - bool right_ok = false; - Variant::Type right_type = Variant::NIL; - String right_name; + bool right_ok = false; + Variant::Type right_type = Variant::NIL; + String right_name; - if (i >= mixed_seq_ports && i < node->get_output_value_port_count() + mixed_seq_ports) { - PropertyInfo pi = node->get_output_value_port_info(i - mixed_seq_ports); - right_ok = true; - right_type = pi.type; - right_name = pi.name; + if (i >= mixed_seq_ports && i < node->get_output_value_port_count() + mixed_seq_ports) { + PropertyInfo pi = node->get_output_value_port_info(i - mixed_seq_ports); + right_ok = true; + right_type = pi.type; + right_name = pi.name; + } + VBoxContainer *vbc = memnew(VBoxContainer); + HBoxContainer *hbc = memnew(HBoxContainer); + HBoxContainer *hbc2 = memnew(HBoxContainer); + vbc->add_child(hbc); + vbc->add_child(hbc2); + if (left_ok) { + Ref<Texture2D> t; + if (left_type >= 0 && left_type < Variant::VARIANT_MAX) { + t = type_icons[left_type]; + } + if (t.is_valid()) { + TextureRect *tf = memnew(TextureRect); + tf->set_texture(t); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + hbc->add_child(tf); } - VBoxContainer *vbc = memnew(VBoxContainer); - HBoxContainer *hbc = memnew(HBoxContainer); - HBoxContainer *hbc2 = memnew(HBoxContainer); - vbc->add_child(hbc); - vbc->add_child(hbc2); - if (left_ok) { - Ref<Texture2D> t; - if (left_type >= 0 && left_type < Variant::VARIANT_MAX) { - t = type_icons[left_type]; - } - if (t.is_valid()) { - TextureRect *tf = memnew(TextureRect); - tf->set_texture(t); - tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - hbc->add_child(tf); - } - - if (is_vslist) { - if (nd_list->is_input_port_name_editable()) { - LineEdit *name_box = memnew(LineEdit); - hbc->add_child(name_box); - name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); - name_box->set_text(left_name); - name_box->set_expand_to_text_length(true); - name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get())); - name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, true)); - } else { - hbc->add_child(memnew(Label(left_name))); - } - - if (nd_list->is_input_port_type_editable()) { - OptionButton *opbtn = memnew(OptionButton); - for (int j = Variant::NIL; j < Variant::VARIANT_MAX; j++) { - opbtn->add_item(Variant::get_type_name(Variant::Type(j))); - } - opbtn->select(left_type); - opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - hbc->add_child(opbtn); - opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, true), CONNECT_DEFERRED); - } - Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - hbc->add_child(rmbtn); - rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED); + if (is_vslist) { + if (nd_list->is_input_port_name_editable()) { + LineEdit *name_box = memnew(LineEdit); + hbc->add_child(name_box); + name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); + name_box->set_text(left_name); + name_box->set_expand_to_text_length(true); + name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get())); + name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, true)); } else { hbc->add_child(memnew(Label(left_name))); } - if (left_type != Variant::NIL && !script->is_input_value_port_connected(F->get(), E->get(), i)) { - PropertyInfo pi = node->get_input_value_port_info(i); - Button *button = memnew(Button); - Variant value = node->get_default_input_value(i); - if (value.get_type() != left_type) { - //different type? for now convert - //not the same, reconvert - Callable::CallError ce; - const Variant *existingp = &value; - value = Variant::construct(left_type, &existingp, 1, ce, false); + if (nd_list->is_input_port_type_editable()) { + OptionButton *opbtn = memnew(OptionButton); + for (int j = Variant::NIL; j < Variant::VARIANT_MAX; j++) { + opbtn->add_item(Variant::get_type_name(Variant::Type(j))); } - - if (left_type == Variant::COLOR) { - button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button), varray(button, value)); - } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { - Ref<Resource> res = value; - Array arr; - arr.push_back(button->get_instance_id()); - arr.push_back(String(value)); - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_button_resource_previewed", arr); - - } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) { - button->set_text(pi.hint_string.get_slice(",", value)); - } else { - button->set_text(value); - } - button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E->get(), i)); - hbc2->add_child(button); + opbtn->select(left_type); + opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + hbc->add_child(opbtn); + opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, true), CONNECT_DEFERRED); } + + Button *rmbtn = memnew(Button); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + hbc->add_child(rmbtn); + rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED); } else { - Control *c = memnew(Control); - c->set_custom_minimum_size(Size2(10, 0) * EDSCALE); - hbc->add_child(c); + hbc->add_child(memnew(Label(left_name))); } - hbc->add_spacer(); - hbc2->add_spacer(); + if (left_type != Variant::NIL && !script->is_input_value_port_connected(E->get(), i)) { + PropertyInfo pi = node->get_input_value_port_info(i); + Button *button = memnew(Button); + Variant value = node->get_default_input_value(i); + if (value.get_type() != left_type) { + //different type? for now convert + //not the same, reconvert + Callable::CallError ce; + const Variant *existingp = &value; + Variant::construct(left_type, value, &existingp, 1, ce); + } - if (i < mixed_seq_ports) { - Label *text2 = memnew(Label); - text2->set_text(node->get_output_sequence_port_text(i)); - text2->set_align(Label::ALIGN_RIGHT); - hbc->add_child(text2); + if (left_type == Variant::COLOR) { + button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); + button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button), varray(button, value)); + } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { + Ref<Resource> res = value; + Array arr; + arr.push_back(button->get_instance_id()); + arr.push_back(String(value)); + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_button_resource_previewed", arr); + + } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) { + button->set_text(pi.hint_string.get_slice(",", value)); + } else { + button->set_text(value); + } + button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E->get(), i)); + hbc2->add_child(button); } + } else { + Control *c = memnew(Control); + c->set_custom_minimum_size(Size2(10, 0) * EDSCALE); + hbc->add_child(c); + } - if (right_ok) { - if (is_vslist) { - Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - hbc->add_child(rmbtn); - rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED); - - if (nd_list->is_output_port_type_editable()) { - OptionButton *opbtn = memnew(OptionButton); - for (int j = Variant::NIL; j < Variant::VARIANT_MAX; j++) { - opbtn->add_item(Variant::get_type_name(Variant::Type(j))); - } - opbtn->select(right_type); - opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - hbc->add_child(opbtn); - opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, false), CONNECT_DEFERRED); - } + hbc->add_spacer(); + hbc2->add_spacer(); + + if (i < mixed_seq_ports) { + Label *text2 = memnew(Label); + text2->set_text(node->get_output_sequence_port_text(i)); + text2->set_align(Label::ALIGN_RIGHT); + hbc->add_child(text2); + } - if (nd_list->is_output_port_name_editable()) { - LineEdit *name_box = memnew(LineEdit); - hbc->add_child(name_box); - name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); - name_box->set_text(right_name); - name_box->set_expand_to_text_length(true); - name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get())); - name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, false)); - } else { - hbc->add_child(memnew(Label(right_name))); + if (right_ok) { + if (is_vslist) { + Button *rmbtn = memnew(Button); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + hbc->add_child(rmbtn); + rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED); + + if (nd_list->is_output_port_type_editable()) { + OptionButton *opbtn = memnew(OptionButton); + for (int j = Variant::NIL; j < Variant::VARIANT_MAX; j++) { + opbtn->add_item(Variant::get_type_name(Variant::Type(j))); } - } else { - hbc->add_child(memnew(Label(right_name))); + opbtn->select(right_type); + opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + hbc->add_child(opbtn); + opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, false), CONNECT_DEFERRED); } - Ref<Texture2D> t; - if (right_type >= 0 && right_type < Variant::VARIANT_MAX) { - t = type_icons[right_type]; - } - if (t.is_valid()) { - TextureRect *tf = memnew(TextureRect); - tf->set_texture(t); - tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - hbc->add_child(tf); + if (nd_list->is_output_port_name_editable()) { + LineEdit *name_box = memnew(LineEdit); + hbc->add_child(name_box); + name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0)); + name_box->set_text(right_name); + name_box->set_expand_to_text_length(true); + name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get())); + name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, false)); + } else { + hbc->add_child(memnew(Label(right_name))); } - } - - gnode->add_child(vbc); - - bool dark_theme = get_theme_constant("dark_theme", "Editor"); - if (i < mixed_seq_ports) { - gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), true, TYPE_SEQUENCE, mono_color, Ref<Texture2D>(), seq_port); } else { - gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), right_ok, right_type, _color_from_type(right_type, dark_theme)); + hbc->add_child(memnew(Label(right_name))); } - slot_idx++; + Ref<Texture2D> t; + if (right_type >= 0 && right_type < Variant::VARIANT_MAX) { + t = type_icons[right_type]; + } + if (t.is_valid()) { + TextureRect *tf = memnew(TextureRect); + tf->set_texture(t); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + hbc->add_child(tf); + } } - graph->add_child(gnode); + gnode->add_child(vbc); - if (gnode->is_comment()) { - graph->move_child(gnode, 0); + bool dark_theme = get_theme_constant("dark_theme", "Editor"); + if (i < mixed_seq_ports) { + gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), true, TYPE_SEQUENCE, mono_color, Ref<Texture2D>(), seq_port); + } else { + gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), right_ok, right_type, _color_from_type(right_type, dark_theme)); } + + slot_idx++; + } + + graph->add_child(gnode); + + if (gnode->is_comment()) { + graph->move_child(gnode, 0); } } + _update_graph_connections(); - // use default_func instead of default_func for now I think that should be good stop gap solution to ensure not breaking anything - graph->call_deferred("set_scroll_ofs", script->get_function_scroll(default_func) * EDSCALE); + + float graph_minimap_opacity = EditorSettings::get_singleton()->get("editors/visual_editors/minimap_opacity"); + graph->set_minimap_opacity(graph_minimap_opacity); + + // Use default_func instead of default_func for now I think that should be good stop gap solution to ensure not breaking anything. + graph->call_deferred("set_scroll_ofs", script->get_scroll() * EDSCALE); updating_graph = false; } void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, bool is_input) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1014,14 +1010,12 @@ void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, b void VisualScriptEditor::_update_node_size(int p_id) { Node *node = graph->get_node(itos(p_id)); if (Object::cast_to<Control>(node)) { - Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); //shrink if text is smaller + Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); // Shrink if text is smaller. } } void VisualScriptEditor::_port_name_focus_out(const Node *p_name_box, int p_id, int p_port, bool is_input) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1062,11 +1056,8 @@ void VisualScriptEditor::_update_members() { List<StringName> func_names; script->get_function_list(&func_names); + func_names.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *E = func_names.front(); E; E = E->next()) { - if (E->get() == default_func) { - continue; - } - TreeItem *ti = members->create_item(functions); ti->set_text(0, E->get()); ti->set_selectable(0, true); @@ -1124,8 +1115,8 @@ void VisualScriptEditor::_update_members() { TreeItem *ti = members->create_item(variables); ti->set_text(0, E->get()); - Variant var = script->get_variable_default_value(E->get()); - ti->set_suffix(0, "= " + String(var)); + + ti->set_suffix(0, "= " + _sanitized_variant_text(E->get())); ti->set_icon(0, type_icons[script->get_variable_info(E->get()).type]); ti->set_selectable(0, true); @@ -1167,6 +1158,20 @@ void VisualScriptEditor::_update_members() { updating_members = false; } +String VisualScriptEditor::_sanitized_variant_text(const StringName &property_name) { + Variant var = script->get_variable_default_value(property_name); + + if (script->get_variable_info(property_name).type != Variant::NIL) { + Callable::CallError ce; + const Variant *converted = &var; + Variant n; + Variant::construct(script->get_variable_info(property_name).type, n, &converted, 1, ce); + var = n; + } + + return String(var); +} + void VisualScriptEditor::_member_selected() { if (updating_members) { return; @@ -1185,7 +1190,7 @@ void VisualScriptEditor::_member_selected() { #endif if (held_ctrl) { ERR_FAIL_COND(!script->has_function(selected)); - _center_on_node(selected, script->get_function_node_id(selected)); + _center_on_node(script->get_function_node_id(selected)); } } } @@ -1228,8 +1233,8 @@ void VisualScriptEditor::_member_edited() { int node_id = script->get_function_node_id(name); Ref<VisualScriptFunction> func; - if (script->has_node(name, node_id)) { - func = script->get_node(name, node_id); + if (script->has_node(node_id)) { + func = script->get_node(node_id); } undo_redo->create_action(TTR("Rename Function")); undo_redo->add_do_method(script.ptr(), "rename_function", name, new_name); @@ -1239,21 +1244,17 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_undo_method(func.ptr(), "set_name", name); } - // also fix all function calls - List<StringName> flst; - script->get_function_list(&flst); - for (List<StringName>::Element *E = flst.front(); E; E = E->next()) { - List<int> lst; - script->get_node_list(E->get(), &lst); - for (List<int>::Element *F = lst.front(); F; F = F->next()) { - Ref<VisualScriptFunctionCall> fncall = script->get_node(E->get(), F->get()); - if (!fncall.is_valid()) { - continue; - } - if (fncall->get_function() == name) { - undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); - undo_redo->add_undo_method(fncall.ptr(), "set_function", name); - } + // Also fix all function calls. + List<int> lst; + script->get_node_list(&lst); + for (List<int>::Element *F = lst.front(); F; F = F->next()) { + Ref<VisualScriptFunctionCall> fncall = script->get_node(F->get()); + if (!fncall.is_valid()) { + continue; + } + if (fncall->get_function() == name) { + undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); + undo_redo->add_undo_method(fncall.ptr(), "set_function", name); } } @@ -1265,7 +1266,7 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } if (ti->get_parent() == root->get_children()->get_next()) { @@ -1281,7 +1282,7 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } if (ti->get_parent() == root->get_children()->get_next()->get_next()) { @@ -1295,7 +1296,7 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } } @@ -1329,10 +1330,13 @@ void VisualScriptEditor::_create_function() { func_node->add_argument(arg_type, arg_name); } + int func_node_id = script->get_available_id(); + undo_redo->create_action(TTR("Add Function")); - undo_redo->add_do_method(script.ptr(), "add_function", name); - undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node, ofs); + undo_redo->add_do_method(script.ptr(), "add_function", name, func_node_id); undo_redo->add_undo_method(script.ptr(), "remove_function", name); + undo_redo->add_do_method(script.ptr(), "add_node", func_node_id, func_node, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", func_node_id); undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); undo_redo->add_do_method(this, "_update_graph"); @@ -1416,11 +1420,12 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt if (ti->get_parent() == root) { //main buttons if (ti == root->get_children()) { - //add function, this one uses menu + // Add function, this one uses menu. if (p_button == 1) { + // Ensure script base exists otherwise use custom base type. + ERR_FAIL_COND(script.is_null()); new_virtual_method_select->select_method_from_base_type(script->get_instance_base_type(), String(), true); - return; } else if (p_button == 0) { String name = _validate_name("new_function"); @@ -1430,11 +1435,13 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt Ref<VisualScriptFunction> func_node; func_node.instance(); func_node->set_name(name); + int fn_id = script->get_available_id(); undo_redo->create_action(TTR("Add Function")); - undo_redo->add_do_method(script.ptr(), "add_function", name); - undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node, ofs); + undo_redo->add_do_method(script.ptr(), "add_function", name, fn_id); + undo_redo->add_do_method(script.ptr(), "add_node", fn_id, func_node, ofs); undo_redo->add_undo_method(script.ptr(), "remove_function", name); + undo_redo->add_do_method(script.ptr(), "remove_node", fn_id); undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); undo_redo->add_do_method(this, "_update_graph"); @@ -1446,11 +1453,11 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt _update_graph(); } - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } if (ti == root->get_children()->get_next()) { - //add variable + // Add variable. String name = _validate_name("new_variable"); selected = name; @@ -1462,11 +1469,11 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt undo_redo->add_do_method(this, "emit_signal", "edited_script_changed"); undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } if (ti == root->get_children()->get_next()->get_next()) { - //add variable + // Add variable. String name = _validate_name("new_signal"); selected = name; @@ -1478,7 +1485,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt undo_redo->add_do_method(this, "emit_signal", "edited_script_changed"); undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - return; //or crash because it will become invalid + return; // Or crash because it will become invalid. } } else if (ti->get_parent() == root->get_children()) { selected = ti->get_text(0); @@ -1490,9 +1497,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt } void VisualScriptEditor::_add_input_port(int p_id) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1512,9 +1517,7 @@ void VisualScriptEditor::_add_input_port(int p_id) { } void VisualScriptEditor::_add_output_port(int p_id) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1534,9 +1537,7 @@ void VisualScriptEditor::_add_output_port(int p_id) { } void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1546,17 +1547,17 @@ void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { undo_redo->create_action(TTR("Remove Input Port"), UndoRedo::MERGE_ENDS); int conn_from = -1, conn_port = -1; - script->get_input_value_port_connection_source(func, p_id, p_port, &conn_from, &conn_port); + script->get_input_value_port_connection_source(p_id, p_port, &conn_from, &conn_port); if (conn_from != -1) { - undo_redo->add_do_method(script.ptr(), "data_disconnect", func, conn_from, conn_port, p_id, p_port); + undo_redo->add_do_method(script.ptr(), "data_disconnect", conn_from, conn_port, p_id, p_port); } undo_redo->add_do_method(vsn.ptr(), "remove_input_data_port", p_port); undo_redo->add_do_method(this, "_update_graph", p_id); if (conn_from != -1) { - undo_redo->add_undo_method(script.ptr(), "data_connect", func, conn_from, conn_port, p_id, p_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", conn_from, conn_port, p_id, p_port); } undo_redo->add_undo_method(vsn.ptr(), "add_input_data_port", vsn->get_input_value_port_info(p_port).type, vsn->get_input_value_port_info(p_port).name, p_port); @@ -1568,9 +1569,7 @@ void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { } void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + Ref<VisualScriptLists> vsn = script->get_node(p_id); if (!vsn.is_valid()) { return; } @@ -1580,12 +1579,12 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { undo_redo->create_action(TTR("Remove Output Port"), UndoRedo::MERGE_ENDS); List<VisualScript::DataConnection> data_connections; - script->get_data_connection_list(func, &data_connections); + script->get_data_connection_list(&data_connections); HashMap<int, Set<int>> conn_map; for (const List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_port == p_port) { - // push into the connections map + // Push into the connections map. if (!conn_map.has(E->get().to_node)) { conn_map.set(E->get().to_node, Set<int>()); } @@ -1600,7 +1599,7 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { conn_map.get_key_list(&keys); for (const List<int>::Element *E = keys.front(); E; E = E->next()) { for (const Set<int>::Element *F = conn_map[E->get()].front(); F; F = F->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", func, p_id, p_port, E->get(), F->get()); + undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E->get(), F->get()); } } @@ -1613,9 +1612,7 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { } void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id) { - StringName func = _get_function_of_node(p_id); - - Ref<VisualScriptExpression> vse = script->get_node(func, p_id); + Ref<VisualScriptExpression> vse = script->get_node(p_id); if (!vse.is_valid()) { return; } @@ -1631,7 +1628,7 @@ void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id Node *node = graph->get_node(itos(p_id)); if (Object::cast_to<Control>(node)) { - Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); //shrink if text is smaller + Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); // Shrink if text is smaller. } updating_graph = false; @@ -1651,19 +1648,14 @@ Vector2 VisualScriptEditor::_get_available_pos(bool centered, Vector2 ofs) const while (true) { bool exists = false; - List<StringName> all_fn; - script->get_function_list(&all_fn); - for (List<StringName>::Element *F = all_fn.front(); F; F = F->next()) { - StringName curr_fn = F->get(); - List<int> existing; - script->get_node_list(curr_fn, &existing); - for (List<int>::Element *E = existing.front(); E; E = E->next()) { - Point2 pos = script->get_node_position(curr_fn, E->get()); - if (pos.distance_to(ofs) < 50) { - ofs += Vector2(graph->get_snap(), graph->get_snap()); - exists = true; - break; - } + List<int> existing; + script->get_node_list(&existing); + for (List<int>::Element *E = existing.front(); E; E = E->next()) { + Point2 pos = script->get_node_position(E->get()); + if (pos.distance_to(ofs) < 50) { + ofs += Vector2(graph->get_snap(), graph->get_snap()); + exists = true; + break; } } if (exists) { @@ -1695,7 +1687,7 @@ String VisualScriptEditor::_validate_name(const String &p_name) const { } void VisualScriptEditor::_on_nodes_delete() { - // delete all the selected nodes + // Delete all the selected nodes. List<int> to_erase; @@ -1708,7 +1700,7 @@ void VisualScriptEditor::_on_nodes_delete() { } } - if (to_erase.empty()) { + if (to_erase.is_empty()) { return; } @@ -1717,26 +1709,24 @@ void VisualScriptEditor::_on_nodes_delete() { for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { int cr_node = F->get(); - StringName func = _get_function_of_node(cr_node); - - undo_redo->add_do_method(script.ptr(), "remove_node", func, cr_node); - undo_redo->add_undo_method(script.ptr(), "add_node", func, cr_node, script->get_node(func, cr_node), script->get_node_position(func, cr_node)); + undo_redo->add_do_method(script.ptr(), "remove_node", cr_node); + undo_redo->add_undo_method(script.ptr(), "add_node", cr_node, script->get_node(cr_node), script->get_node_position(cr_node)); List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(func, &sequence_conns); + script->get_sequence_connection_list(&sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { if (E->get().from_node == cr_node || E->get().to_node == cr_node) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node); } } List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(func, &data_conns); + script->get_data_connection_list(&data_conns); for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { if (E->get().from_node == F->get() || E->get().to_node == F->get()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } } @@ -1748,7 +1738,6 @@ void VisualScriptEditor::_on_nodes_delete() { void VisualScriptEditor::_on_nodes_duplicate() { Set<int> to_duplicate; - List<StringName> funcs; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); @@ -1756,12 +1745,11 @@ void VisualScriptEditor::_on_nodes_duplicate() { if (gn->is_selected() && gn->is_close_button_visible()) { int id = gn->get_name().operator String().to_int(); to_duplicate.insert(id); - funcs.push_back(_get_function_of_node(id)); } } } - if (to_duplicate.empty()) { + if (to_duplicate.is_empty()) { return; } @@ -1772,9 +1760,8 @@ void VisualScriptEditor::_on_nodes_duplicate() { HashMap<int, int> remap; for (Set<int>::Element *F = to_duplicate.front(); F; F = F->next()) { - // duplicate from the specific function but place it into the default func as it would lack the connections - StringName func = _get_function_of_node(F->get()); - Ref<VisualScriptNode> node = script->get_node(func, F->get()); + // Duplicate from the specific function but place it into the default func as it would lack the connections. + Ref<VisualScriptNode> node = script->get_node(F->get()); Ref<VisualScriptNode> dupe = node->duplicate(true); @@ -1782,25 +1769,23 @@ void VisualScriptEditor::_on_nodes_duplicate() { remap.set(F->get(), new_id); to_select.insert(new_id); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, dupe, script->get_node_position(func, F->get()) + Vector2(20, 20)); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, dupe, script->get_node_position(F->get()) + Vector2(20, 20)); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); } - for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { - List<VisualScript::SequenceConnection> seqs; - script->get_sequence_connection_list(F->get(), &seqs); - for (List<VisualScript::SequenceConnection>::Element *E = seqs.front(); E; E = E->next()) { - if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", default_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); - } + List<VisualScript::SequenceConnection> seqs; + script->get_sequence_connection_list(&seqs); + for (List<VisualScript::SequenceConnection>::Element *E = seqs.front(); E; E = E->next()) { + if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); } + } - List<VisualScript::DataConnection> data; - script->get_data_connection_list(F->get(), &data); - for (List<VisualScript::DataConnection>::Element *E = data.front(); E; E = E->next()) { - if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) { - undo_redo->add_do_method(script.ptr(), "data_connect", default_func, remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); - } + List<VisualScript::DataConnection> data; + script->get_data_connection_list(&data); + for (List<VisualScript::DataConnection>::Element *E = data.front(); E; E = E->next()) { + if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) { + undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); } } @@ -1818,7 +1803,7 @@ void VisualScriptEditor::_on_nodes_duplicate() { } if (to_select.size()) { - EditorNode::get_singleton()->push_item(script->get_node(default_func, to_select.front()->get()).ptr()); + EditorNode::get_singleton()->push_item(script->get_node(to_select.front()->get()).ptr()); } } @@ -1831,7 +1816,7 @@ void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool n new_connect_node_select->select_from_visual_script(p_base_type, false, false); // neither connecting nor reset text - // ensure that the dialog fits inside the graph + // Ensure that the dialog fits inside the graph. Size2 bounds = graph->get_global_position() + graph->get_size() - new_connect_node_select->get_size(); pos.x = pos.x > bounds.x ? bounds.x : pos.x; pos.y = pos.y > bounds.y ? bounds.y : pos.y; @@ -1892,7 +1877,7 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { if (btn.is_valid() && btn->is_doubleclick()) { TreeItem *ti = members->get_selected(); if (ti && ti->get_parent() == members->get_root()->get_children()) { // to check if it's a function - _center_on_node(ti->get_metadata(0), script->get_function_node_id(ti->get_metadata(0))); + _center_on_node(script->get_function_node_id(ti->get_metadata(0))); } } } @@ -1910,8 +1895,8 @@ void VisualScriptEditor::_rename_function(const String &name, const String &new_ int node_id = script->get_function_node_id(name); Ref<VisualScriptFunction> func; - if (script->has_node(name, node_id)) { - func = script->get_node(name, node_id); + if (script->has_node(node_id)) { + func = script->get_node(node_id); } undo_redo->create_action(TTR("Rename Function")); undo_redo->add_do_method(script.ptr(), "rename_function", name, new_name); @@ -1921,21 +1906,17 @@ void VisualScriptEditor::_rename_function(const String &name, const String &new_ undo_redo->add_undo_method(func.ptr(), "set_name", name); } - // also fix all function calls - List<StringName> flst; - script->get_function_list(&flst); - for (List<StringName>::Element *E = flst.front(); E; E = E->next()) { - List<int> lst; - script->get_node_list(E->get(), &lst); - for (List<int>::Element *F = lst.front(); F; F = F->next()) { - Ref<VisualScriptFunctionCall> fncall = script->get_node(E->get(), F->get()); - if (!fncall.is_valid()) { - continue; - } - if (fncall->get_function() == name) { - undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); - undo_redo->add_undo_method(fncall.ptr(), "set_function", name); - } + // Also fix all function calls. + List<int> lst; + script->get_node_list(&lst); + for (List<int>::Element *F = lst.front(); F; F = F->next()) { + Ref<VisualScriptFunctionCall> fncall = script->get_node(F->get()); + if (!fncall.is_valid()) { + continue; + } + if (fncall->get_function() == name) { + undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); + undo_redo->add_undo_method(fncall.ptr(), "set_function", name); } } @@ -2088,7 +2069,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da ofs /= EDSCALE; - int new_id = _create_new_node_from_name(d["node_type"], ofs, default_func); + int new_id = _create_new_node_from_name(d["node_type"], ofs); Node *node = graph->get_node(itos(new_id)); if (node) { @@ -2127,8 +2108,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -2156,11 +2137,11 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, ofs); undo_redo->add_do_method(vnode.ptr(), "set_base_type", script->get_instance_base_type()); undo_redo->add_do_method(vnode.ptr(), "set_function", d["function"]); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -2188,8 +2169,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -2217,8 +2198,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Preload Node")); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, prnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, prnode, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -2257,8 +2238,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da prnode.instance(); prnode->set_preload(res); - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, prnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, prnode, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); new_ids.push_back(new_id); new_id++; ofs += Vector2(20, 20) * EDSCALE; @@ -2324,7 +2305,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da scene_node->set_node_path(sn->get_path_to(node)); n = scene_node; } else { - // ! Doesn't work properly + // ! Doesn't work properly. Ref<VisualScriptFunctionCall> call; call.instance(); call->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH); @@ -2335,8 +2316,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da selecting_method_id = base_id; } - undo_redo->add_do_method(script.ptr(), "add_node", default_func, base_id, n, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, base_id); + undo_redo->add_do_method(script.ptr(), "add_node", base_id, n, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", base_id); base_id++; ofs += Vector2(25, 25); @@ -2405,13 +2386,13 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da vnode = pget; } - undo_redo->add_do_method(script.ptr(), "add_node", default_func, base_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", base_id, vnode, ofs); undo_redo->add_do_method(vnode.ptr(), "set_property", d["property"]); if (!use_get) { undo_redo->add_do_method(vnode.ptr(), "set_default_input_value", 0, d["value"]); } - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, base_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", base_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -2450,12 +2431,12 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } vnode = pget; } - undo_redo->add_do_method(script.ptr(), "add_node", default_func, base_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", base_id, vnode, ofs); undo_redo->add_do_method(vnode.ptr(), "set_property", d["property"]); if (!use_get) { undo_redo->add_do_method(vnode.ptr(), "set_default_input_value", 0, d["value"]); } - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, base_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", base_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -2465,7 +2446,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) { - Ref<VisualScriptFunctionCall> vsfc = script->get_node(default_func, selecting_method_id); + Ref<VisualScriptFunctionCall> vsfc = script->get_node(selecting_method_id); if (!vsfc.is_valid()) { return; } @@ -2523,16 +2504,8 @@ void VisualScriptEditor::set_edited_resource(const RES &p_res) { script->connect("node_ports_changed", callable_mp(this, &VisualScriptEditor::_node_ports_changed)); - default_func = script->get_default_func(); - - if (!script->has_function(default_func)) // this is the supposed default function - { - script->add_function(default_func); - script->set_edited(true); //so that if a function was added it's saved - } - _update_graph(); - _update_members(); + call_deferred("_update_members"); } void VisualScriptEditor::enable_editor() { @@ -2551,7 +2524,7 @@ String VisualScriptEditor::get_name() { if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { name = script->get_path().get_file(); if (is_unsaved()) { - if (script->get_path().empty()) { + if (script->get_path().is_empty()) { name = TTR("[unsaved]"); } name += "(*)"; @@ -2573,13 +2546,12 @@ bool VisualScriptEditor::is_unsaved() { bool unsaved = script->is_edited() || script->are_subnodes_edited() || - script->get_path().empty(); // In memory. + script->get_path().is_empty(); // In memory. return unsaved; } Variant VisualScriptEditor::get_edit_state() { Dictionary d; - d["function"] = default_func; d["scroll"] = graph->get_scroll_ofs(); d["zoom"] = graph->get_zoom(); d["using_snap"] = graph->is_using_snap(); @@ -2589,9 +2561,6 @@ Variant VisualScriptEditor::get_edit_state() { void VisualScriptEditor::set_edit_state(const Variant &p_state) { Dictionary d = p_state; - if (d.has("function")) { - selected = default_func; - } _update_graph(); _update_members(); @@ -2610,11 +2579,11 @@ void VisualScriptEditor::set_edit_state(const Variant &p_state) { } } -void VisualScriptEditor::_center_on_node(const StringName &p_func, int p_id) { +void VisualScriptEditor::_center_on_node(int p_id) { Node *n = graph->get_node(itos(p_id)); GraphNode *gn = Object::cast_to<GraphNode>(n); - // clear selection + // Clear selection. for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gnd = Object::cast_to<GraphNode>(graph->get_child(i)); if (gnd) { @@ -2624,15 +2593,15 @@ void VisualScriptEditor::_center_on_node(const StringName &p_func, int p_id) { if (gn) { gn->set_selected(true); - Vector2 new_scroll = gn->get_offset() - graph->get_size() * 0.5 + gn->get_size() * 0.5; + Vector2 new_scroll = gn->get_position_offset() - graph->get_size() * 0.5 + gn->get_size() * 0.5; graph->set_scroll_ofs(new_scroll); - script->set_function_scroll(p_func, new_scroll / EDSCALE); + script->set_scroll(new_scroll / EDSCALE); script->set_edited(true); } } void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { - p_line += 1; //add one because script lines begin from 0. + p_line += 1; // Add one because script lines begin from 0. if (p_with_error) { error_line = p_line; @@ -2641,7 +2610,7 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { List<StringName> functions; script->get_function_list(&functions); for (List<StringName>::Element *E = functions.front(); E; E = E->next()) { - if (script->has_node(E->get(), p_line)) { + if (script->has_node(p_line)) { _update_graph(); _update_members(); @@ -2682,26 +2651,28 @@ void VisualScriptEditor::reload(bool p_soft) { _update_graph(); } -void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { +Array VisualScriptEditor::get_breakpoints() { + Array breakpoints; List<StringName> functions; script->get_function_list(&functions); for (List<StringName>::Element *E = functions.front(); E; E = E->next()) { List<int> nodes; - script->get_node_list(E->get(), &nodes); + script->get_node_list(&nodes); for (List<int>::Element *F = nodes.front(); F; F = F->next()) { - Ref<VisualScriptNode> vsn = script->get_node(E->get(), F->get()); + Ref<VisualScriptNode> vsn = script->get_node(F->get()); if (vsn->is_breakpoint()) { - p_breakpoints->push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero + breakpoints.push_back(F->get() - 1); // Subtract 1 because breakpoints in text start from zero. } } } + return breakpoints; } void VisualScriptEditor::add_callback(const String &p_function, PackedStringArray p_args) { if (script->has_function(p_function)) { _update_members(); _update_graph(); - _center_on_node(p_function, script->get_function_node_id(p_function)); + _center_on_node(script->get_function_node_id(p_function)); return; } @@ -2725,15 +2696,15 @@ void VisualScriptEditor::add_callback(const String &p_function, PackedStringArra func->add_argument(type, name); } - + int fn_id = script->get_available_id(); func->set_name(p_function); - script->add_function(p_function); - script->add_node(p_function, script->get_available_id(), func); + script->add_function(p_function, fn_id); + script->add_node(fn_id, func); _update_members(); _update_graph(); - _center_on_node(p_function, script->get_function_node_id(p_function)); + _center_on_node(script->get_function_node_id(p_function)); } bool VisualScriptEditor::show_members_overview() { @@ -2827,62 +2798,46 @@ void VisualScriptEditor::_end_node_move() { undo_redo->commit_action(); } -void VisualScriptEditor::_move_node(const StringName &p_func, int p_id, const Vector2 &p_to) { - if (!script->has_function(p_func)) { +void VisualScriptEditor::_move_node(int p_id, const Vector2 &p_to) { + if (!script->has_node(p_id)) { return; } Node *node = graph->get_node(itos(p_id)); if (Object::cast_to<GraphNode>(node)) { - Object::cast_to<GraphNode>(node)->set_offset(p_to); + Object::cast_to<GraphNode>(node)->set_position_offset(p_to); } - script->set_node_position(p_func, p_id, p_to / EDSCALE); -} - -StringName VisualScriptEditor::_get_function_of_node(int p_id) const { - List<StringName> funcs; - script->get_function_list(&funcs); - for (List<StringName>::Element *E = funcs.front(); E; E = E->next()) { - if (script->has_node(E->get(), p_id)) { - return E->get(); - } - } - - return ""; // this is passed to avoid crash and is tested against later + script->set_node_position(p_id, p_to / EDSCALE); } void VisualScriptEditor::_node_moved(Vector2 p_from, Vector2 p_to, int p_id) { - StringName func = _get_function_of_node(p_id); - - undo_redo->add_do_method(this, "_move_node", func, p_id, p_to); - undo_redo->add_undo_method(this, "_move_node", func, p_id, p_from); + undo_redo->add_do_method(this, "_move_node", p_id, p_to); + undo_redo->add_undo_method(this, "_move_node", p_id, p_from); } void VisualScriptEditor::_remove_node(int p_id) { undo_redo->create_action(TTR("Remove VisualScript Node")); - StringName func = _get_function_of_node(p_id); - - undo_redo->add_do_method(script.ptr(), "remove_node", func, p_id); - undo_redo->add_undo_method(script.ptr(), "add_node", func, p_id, script->get_node(func, p_id), script->get_node_position(func, p_id)); + undo_redo->add_do_method(script.ptr(), "remove_node", p_id); + undo_redo->add_undo_method(script.ptr(), "add_node", p_id, script->get_node(p_id), script->get_node_position(p_id)); List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(func, &sequence_conns); + script->get_sequence_connection_list(&sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node); } } List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(func, &data_conns); + script->get_data_connection_list(&data_conns); for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { if (E->get().from_node == p_id || E->get().to_node == p_id) { - undo_redo->add_undo_method(script.ptr(), "data_connect", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } @@ -2892,13 +2847,13 @@ void VisualScriptEditor::_remove_node(int p_id) { undo_redo->commit_action(); } -void VisualScriptEditor::_node_ports_changed(const String &p_func, int p_id) { +void VisualScriptEditor::_node_ports_changed(int p_id) { _update_graph(p_id); } -bool VisualScriptEditor::node_has_sequence_connections(const StringName &p_func, int p_id) { +bool VisualScriptEditor::node_has_sequence_connections(int p_id) { List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(p_func, &sequence_conns); + script->get_sequence_connection_list(&sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { int from = E->get().from_node; @@ -2913,9 +2868,7 @@ bool VisualScriptEditor::node_has_sequence_connections(const StringName &p_func, } void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - StringName from_func = _get_function_of_node(p_from.to_int()); - - Ref<VisualScriptNode> from_node = script->get_node(from_func, p_from.to_int()); + Ref<VisualScriptNode> from_node = script->get_node(p_from.to_int()); ERR_FAIL_COND(!from_node.is_valid()); bool from_seq; @@ -2925,9 +2878,7 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, return; //can't connect this, it's invalid } - StringName to_func = _get_function_of_node(p_to.to_int()); - - Ref<VisualScriptNode> to_node = script->get_node(to_func, p_to.to_int()); + Ref<VisualScriptNode> to_node = script->get_node(p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); bool to_seq; @@ -2939,56 +2890,23 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, ERR_FAIL_COND(from_seq != to_seq); - // Do all the checks here - StringName func; // this the func where we store the one the nodes at the end of the resolution on having multiple nodes + // Do all the checks here. + StringName func; // This the func where we store the one the nodes at the end of the resolution on having multiple nodes. undo_redo->create_action(TTR("Connect Nodes")); - if (from_func == to_func) { - func = to_func; - } else if (from_seq) { - // this is a sequence connection - _move_nodes_with_rescan(to_func, from_func, p_to.to_int()); // this function moves the nodes from func1 to func2 - func = from_func; - } else { - if (node_has_sequence_connections(to_func, p_to.to_int())) { - if (node_has_sequence_connections(from_func, p_from.to_int())) { - ERR_PRINT("Trying to connect between different sequence node trees"); - return; - } else { - _move_nodes_with_rescan(from_func, to_func, p_from.to_int()); - func = to_func; - } - } else if (node_has_sequence_connections(from_func, p_from.to_int())) { - if (from_func == default_func) { - _move_nodes_with_rescan(from_func, to_func, p_from.to_int()); - func = to_func; - } else { - _move_nodes_with_rescan(to_func, from_func, p_to.to_int()); - func = from_func; - } - } else { - if (to_func == default_func) { - _move_nodes_with_rescan(to_func, from_func, p_to.to_int()); - func = from_func; - } else { - _move_nodes_with_rescan(from_func, to_func, p_from.to_int()); - func = to_func; - } - } - } - if (from_seq) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", func, p_from.to_int(), from_port, p_to.to_int()); - // this undo error on undo after move can't be removed without painful gymnastics - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", func, p_from.to_int(), from_port, p_to.to_int()); + undo_redo->add_do_method(script.ptr(), "sequence_connect", p_from.to_int(), from_port, p_to.to_int()); + // This undo error on undo after move can't be removed without painful gymnastics + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", p_from.to_int(), from_port, p_to.to_int()); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); } else { bool converted = false; - int conv_node = -1; Ref<VisualScriptOperator> oper = to_node; if (oper.is_valid() && oper->get_typed() == Variant::NIL) { - // it's an operator Node and if the type is already nil + // It's an operator Node and if the type is already nil if (from_node->get_output_value_port_info(from_port).type != Variant::NIL) { oper->set_typed(from_node->get_output_value_port_info(from_port).type); } @@ -2996,106 +2914,36 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, Ref<VisualScriptOperator> operf = from_node; if (operf.is_valid() && operf->get_typed() == Variant::NIL) { - // it's an operator Node and if the type is already nil + // It's an operator Node and if the type is already nil if (to_node->get_input_value_port_info(to_port).type != Variant::NIL) { operf->set_typed(to_node->get_input_value_port_info(to_port).type); } } - Variant::Type to_type = to_node->get_input_value_port_info(to_port).type; - Variant::Type from_type = from_node->get_output_value_port_info(from_port).type; - - if (to_type != Variant::NIL && from_type != Variant::NIL && to_type != from_type) { - // add a constructor node between the ports - bool exceptions = false; // true if there are any exceptions - exceptions = exceptions || (to_type == Variant::INT && from_type == Variant::FLOAT); - exceptions = exceptions || (to_type == Variant::FLOAT && from_type == Variant::INT); - if (Variant::can_convert(from_type, to_type) && !exceptions) { - MethodInfo mi; - mi.name = Variant::get_type_name(to_type); - PropertyInfo pi; - pi.name = "from"; - pi.type = from_type; - mi.arguments.push_back(pi); - mi.return_val.type = to_type; - // we know that this is allowed so create a new constructor node - Ref<VisualScriptConstructor> constructor; - constructor.instance(); - constructor->set_constructor_type(to_type); - constructor->set_constructor(mi); - // add the new constructor node - - GraphNode *gn = Object::cast_to<GraphNode>(graph->get_node(p_from)); - GraphNode *gn2 = Object::cast_to<GraphNode>(graph->get_node(p_to)); - if (gn && gn2) { - Vector2 from_node_size = gn->get_rect().get_size(); - Vector2 to_node_size = gn2->get_rect().get_size(); - Vector2 to_node_pos = script->get_node_position(func, p_to.to_int()); - Vector2 from_node_pos = script->get_node_position(func, p_from.to_int()); - Vector2 new_to_node_pos = from_node_pos; - Vector2 constructor_pos; - if ((to_node_pos.x - from_node_pos.x) < 0) { - // to is behind from node - if (to_node_pos.x > (from_node_pos.x - to_node_size.x - 240)) { - new_to_node_pos.x = from_node_pos.x - to_node_size.x - 240; // approx size of constructor node + padding - } else { - new_to_node_pos.x = to_node_pos.x; - } - new_to_node_pos.y = to_node_pos.y; - constructor_pos.x = from_node_pos.x - 210; - constructor_pos.y = to_node_pos.y; - } else { - // to is ahead of from node - if (to_node_pos.x < (from_node_size.x + from_node_pos.x + 240)) { - new_to_node_pos.x = from_node_size.x + from_node_pos.x + 240; // approx size of constructor node + padding - } else { - new_to_node_pos.x = to_node_pos.x; - } - new_to_node_pos.y = to_node_pos.y; - constructor_pos.x = from_node_size.x + from_node_pos.x + 10; - constructor_pos.y = to_node_pos.y; - } - undo_redo->add_do_method(this, "_move_node", func, p_to.to_int(), new_to_node_pos); - undo_redo->add_undo_method(this, "_move_node", func, p_to.to_int(), to_node_pos); - conv_node = script->get_available_id(); - undo_redo->add_do_method(script.ptr(), "add_node", func, conv_node, constructor, _get_available_pos(false, constructor_pos)); - undo_redo->add_undo_method(script.ptr(), "remove_node", func, conv_node); - converted = true; - } - } - } - - // disconnect current, and connect the new one - if (script->is_input_value_port_connected(func, p_to.to_int(), to_port)) { + // Disconnect current, and connect the new one + if (script->is_input_value_port_connected(p_to.to_int(), to_port)) { if (can_swap && data_disconnect_node == p_to.to_int()) { int conn_from; int conn_port; - script->get_input_value_port_connection_source(func, p_to.to_int(), to_port, &conn_from, &conn_port); - undo_redo->add_do_method(script.ptr(), "data_disconnect", func, conn_from, conn_port, p_to.to_int(), to_port); - undo_redo->add_do_method(script.ptr(), "data_connect", func, conn_from, conn_port, data_disconnect_node, data_disconnect_port); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", func, conn_from, conn_port, data_disconnect_node, data_disconnect_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", func, conn_from, conn_port, p_to.to_int(), to_port); + script->get_input_value_port_connection_source(p_to.to_int(), to_port, &conn_from, &conn_port); + undo_redo->add_do_method(script.ptr(), "data_disconnect", conn_from, conn_port, p_to.to_int(), to_port); + undo_redo->add_do_method(script.ptr(), "data_connect", conn_from, conn_port, data_disconnect_node, data_disconnect_port); + undo_redo->add_undo_method(script.ptr(), "data_disconnect", conn_from, conn_port, data_disconnect_node, data_disconnect_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", conn_from, conn_port, p_to.to_int(), to_port); can_swap = false; // swapped } else { int conn_from; int conn_port; - script->get_input_value_port_connection_source(func, p_to.to_int(), to_port, &conn_from, &conn_port); - undo_redo->add_do_method(script.ptr(), "data_disconnect", func, conn_from, conn_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", func, conn_from, conn_port, p_to.to_int(), to_port); + script->get_input_value_port_connection_source(p_to.to_int(), to_port, &conn_from, &conn_port); + undo_redo->add_do_method(script.ptr(), "data_disconnect", conn_from, conn_port, p_to.to_int(), to_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", conn_from, conn_port, p_to.to_int(), to_port); } } if (!converted) { - undo_redo->add_do_method(script.ptr(), "data_connect", func, p_from.to_int(), from_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", func, p_from.to_int(), from_port, p_to.to_int(), to_port); - } else { - // this is noice - undo_redo->add_do_method(script.ptr(), "data_connect", func, p_from.to_int(), from_port, conv_node, 0); - undo_redo->add_do_method(script.ptr(), "data_connect", func, conv_node, 0, p_to.to_int(), to_port); - // I don't think this is needed but gonna leave it here for now... until I need to finalise it all - undo_redo->add_undo_method(script.ptr(), "data_disconnect", func, p_from.to_int(), from_port, conv_node, 0); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", func, conv_node, 0, p_to.to_int(), to_port); + undo_redo->add_do_method(script.ptr(), "data_connect", p_from.to_int(), from_port, p_to.to_int(), to_port); + undo_redo->add_undo_method(script.ptr(), "data_disconnect", p_from.to_int(), from_port, p_to.to_int(), to_port); } - //update nodes in graph + // Update nodes in graph if (!converted) { undo_redo->add_do_method(this, "_update_graph", p_from.to_int()); undo_redo->add_do_method(this, "_update_graph", p_to.to_int()); @@ -3107,34 +2955,28 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, } } - undo_redo->add_do_method(this, "_update_graph_connections"); - undo_redo->add_undo_method(this, "_update_graph_connections"); - undo_redo->commit_action(); } void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - StringName func = _get_function_of_node(p_from.to_int()); - ERR_FAIL_COND(func != _get_function_of_node(p_to.to_int())); - - Ref<VisualScriptNode> from_node = script->get_node(func, p_from.to_int()); + Ref<VisualScriptNode> from_node = script->get_node(p_from.to_int()); ERR_FAIL_COND(!from_node.is_valid()); bool from_seq; int from_port; if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) { - return; //can't connect this, it's invalid + return; // Can't connect this, it's invalid. } - Ref<VisualScriptNode> to_node = script->get_node(func, p_to.to_int()); + Ref<VisualScriptNode> to_node = script->get_node(p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); bool to_seq; int to_port; if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) { - return; //can't connect this, it's invalid + return; // Can't connect this, it's invalid. } ERR_FAIL_COND(from_seq != to_seq); @@ -3142,248 +2984,27 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl undo_redo->create_action(TTR("Disconnect Nodes")); if (from_seq) { - undo_redo->add_do_method(script.ptr(), "sequence_disconnect", func, p_from.to_int(), from_port, p_to.to_int()); - undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, p_from.to_int(), from_port, p_to.to_int()); + undo_redo->add_do_method(script.ptr(), "sequence_disconnect", p_from.to_int(), from_port, p_to.to_int()); + undo_redo->add_undo_method(script.ptr(), "sequence_connect", p_from.to_int(), from_port, p_to.to_int()); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); } else { can_swap = true; data_disconnect_node = p_to.to_int(); data_disconnect_port = to_port; - undo_redo->add_do_method(script.ptr(), "data_disconnect", func, p_from.to_int(), from_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", func, p_from.to_int(), from_port, p_to.to_int(), to_port); - //update relevant nodes in the graph + undo_redo->add_do_method(script.ptr(), "data_disconnect", p_from.to_int(), from_port, p_to.to_int(), to_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", p_from.to_int(), from_port, p_to.to_int(), to_port); + // Update relevant nodes in the graph. undo_redo->add_do_method(this, "_update_graph", p_from.to_int()); undo_redo->add_do_method(this, "_update_graph", p_to.to_int()); undo_redo->add_undo_method(this, "_update_graph", p_from.to_int()); undo_redo->add_undo_method(this, "_update_graph", p_to.to_int()); } - undo_redo->add_do_method(this, "_update_graph_connections"); - undo_redo->add_undo_method(this, "_update_graph_connections"); undo_redo->commit_action(); } -void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, const StringName &p_func_to, int p_id) { - Set<int> nodes_to_move; - HashMap<int, Map<int, int>> seqconns_to_move; // from => List(outp, to) - HashMap<int, Map<int, Pair<int, int>>> dataconns_to_move; // to => List(inp_p => from, outp) - - nodes_to_move.insert(p_id); - Set<int> sequence_connections; - { - List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(p_func_from, &sequence_conns); - - HashMap<int, Map<int, int>> seqcons; // from => List(out_p => to) - - for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - int from = E->get().from_node; - int to = E->get().to_node; - int out_p = E->get().from_output; - if (!seqcons.has(from)) { - seqcons.set(from, Map<int, int>()); - } - seqcons[from].insert(out_p, to); - sequence_connections.insert(to); - sequence_connections.insert(from); - } - - int conn = p_id; - List<int> stack; - HashMap<int, Set<int>> seen; // from, outp - while (seqcons.has(conn)) { - for (auto E = seqcons[conn].front(); E; E = E->next()) { - if (seen.has(conn) && seen[conn].has(E->key())) { - if (!E->next()) { - if (stack.size() > 0) { - conn = stack.back()->get(); - stack.pop_back(); - break; - } - conn = -101; - break; - } - continue; - } - if (!seen.has(conn)) { - seen.set(conn, Set<int>()); - } - seen[conn].insert(E->key()); - stack.push_back(conn); - if (!seqconns_to_move.has(conn)) { - seqconns_to_move.set(conn, Map<int, int>()); - } - seqconns_to_move[conn].insert(E->key(), E->get()); - conn = E->get(); - nodes_to_move.insert(conn); - break; - } - if (!seqcons.has(conn) && stack.size() > 0) { - conn = stack.back()->get(); - stack.pop_back(); - } - } - } - - { - List<VisualScript::DataConnection> data_connections; - script->get_data_connection_list(p_func_from, &data_connections); - int func_from_node_id = script->get_function_node_id(p_func_from); - - HashMap<int, Map<int, Pair<int, int>>> connections; - - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - int from = E->get().from_node; - int to = E->get().to_node; - int out_p = E->get().from_port; - int in_p = E->get().to_port; - - // skip if the from_node is a function node - if (from == func_from_node_id) { - continue; - } - - if (!connections.has(to)) { - connections.set(to, Map<int, Pair<int, int>>()); - } - connections[to].insert(in_p, Pair<int, int>(from, out_p)); - } - - // go through the HashMap and do all sorts of crazy ass stuff now... - Set<int> nodes_to_be_added; - for (Set<int>::Element *F = nodes_to_move.front(); F; F = F->next()) { - HashMap<int, Set<int>> seen; - List<int> stack; - int id = F->get(); - while (connections.has(id)) { - for (auto E = connections[id].front(); E; E = E->next()) { - if (seen.has(id) && seen[id].has(E->key())) { - if (!E->next()) { - if (stack.size() > 0) { - id = stack.back()->get(); - stack.pop_back(); - break; - } - id = -11; // I assume ids can't be negative should confirm it... - break; - } - continue; - } - - if (sequence_connections.has(E->get().first)) { - if (!nodes_to_move.has(E->get().first)) { - if (stack.size() > 0) { - id = stack.back()->get(); - stack.pop_back(); - break; - } - id = -11; // I assume ids can't be negative should confirm it... - break; - } - } - - if (!seen.has(id)) { - seen.set(id, Set<int>()); - } - seen[id].insert(E->key()); - stack.push_back(id); - if (!dataconns_to_move.has(id)) { - dataconns_to_move.set(id, Map<int, Pair<int, int>>()); - } - dataconns_to_move[id].insert(E->key(), Pair<int, int>(E->get().first, E->get().second)); - id = E->get().first; - nodes_to_be_added.insert(id); - break; - } - if (!connections.has(id) && stack.size() > 0) { - id = stack.back()->get(); - stack.pop_back(); - } - } - } - for (Set<int>::Element *E = nodes_to_be_added.front(); E; E = E->next()) { - nodes_to_move.insert(E->get()); - } - } - - // * this is primarily for the sake of the having proper undo - List<VisualScript::SequenceConnection> seqext; - List<VisualScript::DataConnection> dataext; - - List<VisualScript::SequenceConnection> seq_connections; - script->get_sequence_connection_list(p_func_from, &seq_connections); - - for (List<VisualScript::SequenceConnection>::Element *E = seq_connections.front(); E; E = E->next()) { - if (!nodes_to_move.has(E->get().from_node) && nodes_to_move.has(E->get().to_node)) { - seqext.push_back(E->get()); - } else if (nodes_to_move.has(E->get().from_node) && !nodes_to_move.has(E->get().to_node)) { - seqext.push_back(E->get()); - } - } - - List<VisualScript::DataConnection> data_connections; - script->get_data_connection_list(p_func_from, &data_connections); - - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - if (!nodes_to_move.has(E->get().from_node) && nodes_to_move.has(E->get().to_node)) { - dataext.push_back(E->get()); - } else if (nodes_to_move.has(E->get().from_node) && !nodes_to_move.has(E->get().to_node)) { - dataext.push_back(E->get()); - } - } - - // undo_redo->create_action("Rescan Functions"); - - for (Set<int>::Element *E = nodes_to_move.front(); E; E = E->next()) { - int id = E->get(); - - undo_redo->add_do_method(script.ptr(), "remove_node", p_func_from, id); - undo_redo->add_do_method(script.ptr(), "add_node", p_func_to, id, script->get_node(p_func_from, id), script->get_node_position(p_func_from, id)); - - undo_redo->add_undo_method(script.ptr(), "remove_node", p_func_to, id); - undo_redo->add_undo_method(script.ptr(), "add_node", p_func_from, id, script->get_node(p_func_from, id), script->get_node_position(p_func_from, id)); - } - - List<int> skeys; - seqconns_to_move.get_key_list(&skeys); - for (List<int>::Element *E = skeys.front(); E; E = E->next()) { - int from_node = E->get(); - for (Map<int, int>::Element *F = seqconns_to_move[from_node].front(); F; F = F->next()) { - int from_port = F->key(); - int to_node = F->get(); - undo_redo->add_do_method(script.ptr(), "sequence_connect", p_func_to, from_node, from_port, to_node); - undo_redo->add_undo_method(script.ptr(), "sequence_connect", p_func_from, from_node, from_port, to_node); - } - } - - List<int> keys; - dataconns_to_move.get_key_list(&keys); - for (List<int>::Element *E = keys.front(); E; E = E->next()) { - int to_node = E->get(); // to_node - for (Map<int, Pair<int, int>>::Element *F = dataconns_to_move[E->get()].front(); F; F = F->next()) { - int inp_p = F->key(); - Pair<int, int> fro = F->get(); - - undo_redo->add_do_method(script.ptr(), "data_connect", p_func_to, fro.first, fro.second, to_node, inp_p); - undo_redo->add_undo_method(script.ptr(), "data_connect", p_func_from, fro.first, fro.second, to_node, inp_p); - } - } - - // this to have proper undo operations - for (List<VisualScript::SequenceConnection>::Element *E = seqext.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", p_func_from, E->get().from_node, E->get().from_output, E->get().to_node); - } - for (List<VisualScript::DataConnection>::Element *E = dataext.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", p_func_from, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); - } - // this doesn't need do methods as they are handled by the subsequent do calls implicitly - - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - - // undo_redo->commit_action(); -} - void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_pos) { Node *node = graph->get_node(p_from); GraphNode *gn = Object::cast_to<GraphNode>(node); @@ -3391,23 +3012,22 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro return; } - StringName func = _get_function_of_node(p_from.to_int()); - - Ref<VisualScriptNode> vsn = script->get_node(func, p_from.to_int()); + Ref<VisualScriptNode> vsn = script->get_node(p_from.to_int()); if (!vsn.is_valid()) { return; } + if (vsn->get_output_value_port_count()) - port_action_pos = p_release_pos; + port_action_pos = p_release_pos; if (p_from_slot < vsn->get_output_sequence_port_count()) { port_action_node = p_from.to_int(); port_action_output = p_from_slot; - _port_action_menu(CREATE_ACTION, func); + _port_action_menu(CREATE_ACTION); } else { port_action_output = p_from_slot - vsn->get_output_sequence_port_count(); port_action_node = p_from.to_int(); - _port_action_menu(CREATE_CALL_SET_GET, func); + _port_action_menu(CREATE_CALL_SET_GET); } } @@ -3421,9 +3041,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac visited_nodes.insert(p_port_action_node); - StringName func = _get_function_of_node(p_port_action_node); - - Ref<VisualScriptNode> node = script->get_node(func, p_port_action_node); + Ref<VisualScriptNode> node = script->get_node(p_port_action_node); if (!node.is_valid()) { return tg; @@ -3437,11 +3055,11 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac g.type = pi.type; if (g.type == Variant::NIL || g.type == Variant::OBJECT) { - //any or object input, must further guess what this is + // Any or object input, must further guess what this is. int from_node; int from_port; - if (script->get_input_value_port_connection_source(func, p_port_action_node, i, &from_node, &from_port)) { + if (script->get_input_value_port_connection_source(p_port_action_node, i, &from_node, &from_port)) { g = _guess_output_type(from_node, from_port, visited_nodes); } else { Variant defval = node->get_default_input_value(i); @@ -3463,7 +3081,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac return node->guess_output_type(in_guesses.ptrw(), p_port_action_output); } -void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) { +void VisualScriptEditor::_port_action_menu(int p_option) { Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -3486,8 +3104,8 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) n->set_base_type("Object"); } String type_string; - if (script->get_node(func, port_action_node)->get_output_value_port_count() > 0) { - type_string = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + if (script->get_node(port_action_node)->get_output_value_port_count() > 0) { + type_string = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint_string; } if (tg.type == Variant::OBJECT) { if (tg.script.is_valid()) { @@ -3502,7 +3120,7 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) } else { new_connect_node_select->select_from_basic_type(tg.type); } - // ensure that the dialog fits inside the graph + // Ensure that the dialog fits inside the graph. Vector2 pos = mouse_up_position; Size2 bounds = graph->get_global_position() + graph->get_size() - new_connect_node_select->get_size(); pos.x = pos.x > bounds.x ? bounds.x : pos.x; @@ -3512,8 +3130,8 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) case CREATE_ACTION: { VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); PropertyInfo property_info; - if (script->get_node(func, port_action_node)->get_output_value_port_count() > 0) { - property_info = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output); + if (script->get_node(port_action_node)->get_output_value_port_count() > 0) { + property_info = script->get_node(port_action_node)->get_output_value_port_info(port_action_output); } if (tg.type == Variant::OBJECT) { if (property_info.type == Variant::OBJECT && property_info.hint_string != String()) { @@ -3526,7 +3144,7 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) } else { new_connect_node_select->select_from_action(Variant::get_type_name(tg.type)); } - // ensure that the dialog fits inside the graph + // Ensure that the dialog fits inside the graph. Vector2 pos = mouse_up_position; Size2 bounds = graph->get_global_position() + graph->get_size() - new_connect_node_select->get_size(); pos.x = pos.x > bounds.x ? bounds.x : pos.x; @@ -3555,9 +3173,8 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua if (port >= value_count) { port = 0; } - StringName func = _get_function_of_node(port_action_node); - undo_redo->add_do_method(script.ptr(), "data_connect", func, port_action_node, port, new_id, 0); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", func, port_action_node, port, new_id, 0); + undo_redo->add_do_method(script.ptr(), "data_connect", port_action_node, port, new_id, 0); + undo_redo->add_undo_method(script.ptr(), "data_disconnect", port_action_node, port, new_id, 0); undo_redo->commit_action(); } @@ -3574,17 +3191,16 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri bool port_node_exists = true; - StringName func = _get_function_of_node(port_action_node); - if (func == StringName()) { - func = default_func; - port_node_exists = false; - } + // if (func == StringName()) { + // func = default_func; + // port_node_exists = false; + // } if (p_category == "visualscript") { Ref<VisualScriptNode> vnode_new = VisualScriptLanguage::singleton->create_node_from_name(p_text); Ref<VisualScriptNode> vnode_old; - if (port_node_exists) { - vnode_old = script->get_node(func, port_action_node); + if (port_node_exists && p_connecting) { + vnode_old = script->get_node(port_action_node); } int new_id = script->get_available_id(); @@ -3607,13 +3223,13 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", func, new_id, vnode_new, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode_new, ofs); if (vnode_old.is_valid() && p_connecting) { connect_seq(vnode_old, vnode_new, new_id); connect_data(vnode_old, vnode_new, new_id); } - undo_redo->add_undo_method(script.ptr(), "remove_node", func, new_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -3670,8 +3286,8 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph", new_id); undo_redo->add_undo_method(this, "_update_graph", new_id); undo_redo->commit_action(); @@ -3682,7 +3298,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri port_action_new_node = new_id; - Ref<VisualScriptNode> vsn = script->get_node(func, port_action_new_node); + Ref<VisualScriptNode> vsn = script->get_node(port_action_new_node); if (Object::cast_to<VisualScriptFunctionCall>(vsn.ptr())) { Ref<VisualScriptFunctionCall> vsfc = vsn; @@ -3696,10 +3312,9 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri vsfc->set_base_type(String("")); if (tg.gdclass != StringName()) { vsfc->set_base_type(tg.gdclass); - - } else if (script->get_node(func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + } else if (script->get_node(port_action_node).is_valid()) { + PropertyHint hint = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint; + String base_type = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint_string; if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { vsfc->set_base_type(base_type); @@ -3732,9 +3347,9 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri if (tg.gdclass != StringName()) { vsp->set_base_type(tg.gdclass); - } else if (script->get_node(func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + } else if (script->get_node(port_action_node).is_valid()) { + PropertyHint hint = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint; + String base_type = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint_string; if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { vsp->set_base_type(base_type); @@ -3762,9 +3377,9 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri if (tg.gdclass != StringName()) { vsp->set_base_type(tg.gdclass); - } else if (script->get_node(func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + } else if (script->get_node(port_action_node).is_valid()) { + PropertyHint hint = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint; + String base_type = script->get_node(port_action_node)->get_output_value_port_info(port_action_output).hint_string; if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { vsp->set_base_type(base_type); } @@ -3782,16 +3397,13 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } if (port_node_exists) { - Ref<VisualScriptNode> vnode_old = script->get_node(func, port_action_node); + Ref<VisualScriptNode> vnode_old = script->get_node(port_action_node); if (vnode_old.is_valid() && p_connecting) { connect_seq(vnode_old, vnode, port_action_new_node); connect_data(vnode_old, vnode, port_action_new_node); } } _update_graph(port_action_new_node); - if (port_node_exists) { - _update_graph_connections(); - } } void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id) { @@ -3810,29 +3422,27 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual return; } - StringName func = _get_function_of_node(port_action_node); - undo_redo->create_action(TTR("Connect Node Sequence")); int pass_port = -vnode_old->get_output_sequence_port_count() + 1; int return_port = port_action_output - 1; if (vnode_old->get_output_value_port_info(port_action_output).name == String("pass") && - !script->get_output_sequence_ports_connected(func, port_action_node).has(pass_port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", func, port_action_node, pass_port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", func, port_action_node, pass_port, new_id); + !script->get_output_sequence_ports_connected(port_action_node).has(pass_port)) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", port_action_node, pass_port, new_id); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", port_action_node, pass_port, new_id); } else if (vnode_old->get_output_value_port_info(port_action_output).name == String("return") && - !script->get_output_sequence_ports_connected(func, port_action_node).has(return_port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", func, port_action_node, return_port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", func, port_action_node, return_port, new_id); + !script->get_output_sequence_ports_connected(port_action_node).has(return_port)) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", port_action_node, return_port, new_id); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", port_action_node, return_port, new_id); } else { for (int port = 0; port < vnode_old->get_output_sequence_port_count(); port++) { int count = vnode_old->get_output_sequence_port_count(); - if (port_action_output < count && !script->get_output_sequence_ports_connected(func, port_action_node).has(port_action_output)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", func, port_action_node, port_action_output, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", func, port_action_node, port_action_output, new_id); + if (port_action_output < count && !script->get_output_sequence_ports_connected(port_action_node).has(port_action_output)) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", port_action_node, port_action_output, new_id); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", port_action_node, port_action_output, new_id); break; - } else if (!script->get_output_sequence_ports_connected(func, port_action_node).has(port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", func, port_action_node, port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", func, port_action_node, port, new_id); + } else if (!script->get_output_sequence_ports_connected(port_action_node).has(port)) { + undo_redo->add_do_method(script.ptr(), "sequence_connect", port_action_node, port, new_id); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", port_action_node, port, new_id); break; } } @@ -3867,9 +3477,9 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons Ref<VisualScriptFunction> func_node; func_node.instance(); func_node->set_name(name); - + int fn_id = script->get_available_id(); undo_redo->create_action(TTR("Add Function")); - undo_redo->add_do_method(script.ptr(), "add_function", name); + undo_redo->add_do_method(script.ptr(), "add_function", name, fn_id); for (int i = 0; i < minfo.arguments.size(); i++) { func_node->add_argument(minfo.arguments[i].type, minfo.arguments[i].name, -1, minfo.arguments[i].hint, minfo.arguments[i].hint_string); @@ -3877,14 +3487,17 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons Vector2 ofs = _get_available_pos(); - undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", fn_id, func_node, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_node", fn_id); if (minfo.return_val.type != Variant::NIL || minfo.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { Ref<VisualScriptReturn> ret_node; ret_node.instance(); ret_node->set_return_type(minfo.return_val.type); ret_node->set_enable_return_value(true); ret_node->set_name(name); - undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id() + 1, ret_node, _get_available_pos(false, ofs + Vector2(500, 0))); + int nid = script->get_available_id() + 1; + undo_redo->add_do_method(script.ptr(), "add_node", nid, ret_node, _get_available_pos(false, ofs + Vector2(500, 0))); + undo_redo->add_undo_method(script.ptr(), "remove_node", nid); } undo_redo->add_undo_method(script.ptr(), "remove_function", name); @@ -3899,21 +3512,16 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons } void VisualScriptEditor::_cancel_connect_node() { - // ensure the cancel is done + // Ensure the cancel is done. port_action_new_node = -1; } -int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const Vector2 &p_point, const StringName &p_func) { - StringName func = default_func; - if (p_func != StringName()) { - func = p_func; - } - +int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const Vector2 &p_point) { Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(p_text); int new_id = script->get_available_id(); undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", func, new_id, vnode, p_point); - undo_redo->add_undo_method(script.ptr(), "remove_node", func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, vnode, p_point); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -3921,7 +3529,7 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V } void VisualScriptEditor::_default_value_changed() { - Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(editing_id), editing_id); + Ref<VisualScriptNode> vsn = script->get_node(editing_id); if (vsn.is_null()) { return; } @@ -3936,7 +3544,7 @@ void VisualScriptEditor::_default_value_changed() { } void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_input_port) { - Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(p_id), p_id); + Ref<VisualScriptNode> vsn = script->get_node(p_id); if (vsn.is_null()) { return; } @@ -3945,8 +3553,9 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i Variant existing = vsn->get_default_input_value(p_input_port); if (pinfo.type != Variant::NIL && existing.get_type() != pinfo.type) { Callable::CallError ce; - const Variant *existingp = &existing; - existing = Variant::construct(pinfo.type, &existingp, 1, ce, false); + Variant e = existing; + const Variant *existingp = &e; + Variant::construct(pinfo.type, existing, &existingp, 1, ce); } default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_global_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y)); @@ -3954,15 +3563,15 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i if (pinfo.type == Variant::NODE_PATH) { Node *edited_scene = get_tree()->get_edited_scene_root(); - if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open) + if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open). Node *script_node = _find_script_node(edited_scene, edited_scene, script); if (script_node) { - //pick a node relative to the script, IF the script exists + // Pick a node relative to the script, IF the script exists. pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; pinfo.hint_string = script_node->get_path(); } else { - //pick a path relative to edited scene + // Pick a path relative to edited scene. pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; pinfo.hint_string = get_tree()->get_edited_scene_root()->get_path(); } @@ -4060,11 +3669,8 @@ void VisualScriptEditor::_graph_ofs_changed(const Vector2 &p_ofs) { updating_graph = true; - // Just use the default func for all the properties that need to be handled for drawing rather than adding to the Visual Script Class - if (script->has_function(default_func)) { - script->set_function_scroll(default_func, graph->get_scroll_ofs() / EDSCALE); - script->set_edited(true); - } + script->set_scroll(graph->get_scroll_ofs() / EDSCALE); + script->set_edited(true); updating_graph = false; } @@ -4072,10 +3678,7 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ if (updating_graph) { return; } - - StringName func = _get_function_of_node(p_node); - - Ref<VisualScriptComment> vsc = script->get_node(func, p_node); + Ref<VisualScriptComment> vsc = script->get_node(p_node); if (vsc.is_null()) { return; } @@ -4113,8 +3716,7 @@ void VisualScriptEditor::_menu_option(int p_what) { if (gn) { if (gn->is_selected()) { int id = String(gn->get_name()).to_int(); - StringName func = _get_function_of_node(id); - Ref<VisualScriptNode> vsn = script->get_node(func, id); + Ref<VisualScriptNode> vsn = script->get_node(id); if (vsn.is_valid()) { vsn->set_breakpoint(!vsn->is_breakpoint()); reselect.push_back(gn->get_name()); @@ -4136,58 +3738,47 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_COPY_NODES: case EDIT_CUT_NODES: { - if (!script->has_function(default_func)) { - break; - } - clipboard->nodes.clear(); clipboard->data_connections.clear(); clipboard->sequence_connections.clear(); - Set<String> funcs; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); if (gn) { if (gn->is_selected()) { - int id = String(gn->get_name()).to_int(); - StringName func = _get_function_of_node(id); - Ref<VisualScriptNode> node = script->get_node(func, id); + int id = gn->get_name().operator String().to_int(); + Ref<VisualScriptNode> node = script->get_node(id); if (Object::cast_to<VisualScriptFunction>(*node)) { EditorNode::get_singleton()->show_warning(TTR("Can't copy the function node.")); return; } if (node.is_valid()) { clipboard->nodes[id] = node->duplicate(true); - clipboard->nodes_positions[id] = script->get_node_position(func, id); - funcs.insert(String(func)); + clipboard->nodes_positions[id] = script->get_node_position(id); } } } } - if (clipboard->nodes.empty()) { + if (clipboard->nodes.is_empty()) { break; } - for (Set<String>::Element *F = funcs.front(); F; F = F->next()) { - List<VisualScript::SequenceConnection> sequence_connections; + List<VisualScript::SequenceConnection> sequence_connections; + script->get_sequence_connection_list(&sequence_connections); - script->get_sequence_connection_list(F->get(), &sequence_connections); - - for (List<VisualScript::SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { - if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->sequence_connections.insert(E->get()); - } + for (List<VisualScript::SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { + if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { + clipboard->sequence_connections.insert(E->get()); } + } - List<VisualScript::DataConnection> data_connections; - - script->get_data_connection_list(F->get(), &data_connections); + List<VisualScript::DataConnection> data_connections; + script->get_data_connection_list(&data_connections); - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->data_connections.insert(E->get()); - } + for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { + clipboard->data_connections.insert(E->get()); } } if (p_what == EDIT_CUT_NODES) { @@ -4196,11 +3787,7 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_PASTE_NODES: { - if (!script->has_function(default_func)) { - break; - } - - if (clipboard->nodes.empty()) { + if (clipboard->nodes.is_empty()) { EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!")); break; } @@ -4215,15 +3802,11 @@ void VisualScriptEditor::_menu_option(int p_what) { Set<Vector2> existing_positions; { - List<StringName> functions; - script->get_function_list(&functions); - for (List<StringName>::Element *F = functions.front(); F; F = F->next()) { - List<int> nodes; - script->get_node_list(F->get(), &nodes); - for (List<int>::Element *E = nodes.front(); E; E = E->next()) { - Vector2 pos = script->get_node_position(F->get(), E->get()).snapped(Vector2(2, 2)); - existing_positions.insert(pos); - } + List<int> nodes; + script->get_node_list(&nodes); + for (List<int>::Element *E = nodes.front(); E; E = E->next()) { + Vector2 pos = script->get_node_position(E->get()).snapped(Vector2(2, 2)); + existing_positions.insert(pos); } } @@ -4241,18 +3824,18 @@ void VisualScriptEditor::_menu_option(int p_what) { paste_pos += Vector2(20, 20) * EDSCALE; } - undo_redo->add_do_method(script.ptr(), "add_node", default_func, new_id, node, paste_pos); - undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); + undo_redo->add_do_method(script.ptr(), "add_node", new_id, node, paste_pos); + undo_redo->add_undo_method(script.ptr(), "remove_node", new_id); } for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", default_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", default_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); + undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); + undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); } for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "data_connect", default_func, remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", default_func, remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); + undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); } undo_redo->add_do_method(this, "_update_graph"); @@ -4269,7 +3852,7 @@ void VisualScriptEditor::_menu_option(int p_what) { } } break; case EDIT_CREATE_FUNCTION: { - StringName function = ""; + // Create Function. Map<int, Ref<VisualScriptNode>> nodes; Set<int> selections; for (int i = 0; i < graph->get_child_count(); i++) { @@ -4277,20 +3860,14 @@ void VisualScriptEditor::_menu_option(int p_what) { if (gn) { if (gn->is_selected()) { int id = String(gn->get_name()).to_int(); - StringName func = _get_function_of_node(id); - Ref<VisualScriptNode> node = script->get_node(func, id); + Ref<VisualScriptNode> node = script->get_node(id); if (Object::cast_to<VisualScriptFunction>(*node)) { EditorNode::get_singleton()->show_warning(TTR("Can't create function with a function node.")); return; } if (node.is_valid()) { - if (func != function && function != StringName("")) { - EditorNode::get_singleton()->show_warning(TTR("Can't create function of nodes from nodes of multiple functions.")); - return; - } nodes.insert(id, node); selections.insert(id); - function = func; } } } @@ -4309,7 +3886,7 @@ void VisualScriptEditor::_menu_option(int p_what) { int start_node = -1; Set<int> end_nodes; if (nodes.size() == 1) { - Ref<VisualScriptNode> nd = script->get_node(function, nodes.front()->key()); + Ref<VisualScriptNode> nd = script->get_node(nodes.front()->key()); if (nd.is_valid() && nd->has_input_sequence_port()) { start_node = nodes.front()->key(); } else { @@ -4318,29 +3895,29 @@ void VisualScriptEditor::_menu_option(int p_what) { } } else { List<VisualScript::SequenceConnection> seqs; - script->get_sequence_connection_list(function, &seqs); + script->get_sequence_connection_list(&seqs); if (seqs.size() == 0) { - // in case there are no sequence connections - // select the top most node cause that's probably how - // the user wants to connect the nodes + // In case there are no sequence connections, + // select the top most node cause that's probably how, + // the user wants to connect the nodes. int top_nd = -1; Vector2 top; for (Map<int, Ref<VisualScriptNode>>::Element *E = nodes.front(); E; E = E->next()) { - Ref<VisualScriptNode> nd = script->get_node(function, E->key()); + Ref<VisualScriptNode> nd = script->get_node(E->key()); if (nd.is_valid() && nd->has_input_sequence_port()) { if (top_nd < 0) { top_nd = E->key(); - top = script->get_node_position(function, top_nd); + top = script->get_node_position(top_nd); } - Vector2 pos = script->get_node_position(function, E->key()); + Vector2 pos = script->get_node_position(E->key()); if (top.y > pos.y) { top_nd = E->key(); top = pos; } } } - Ref<VisualScriptNode> nd = script->get_node(function, top_nd); + Ref<VisualScriptNode> nd = script->get_node(top_nd); if (nd.is_valid() && nd->has_input_sequence_port()) { start_node = top_nd; } else { @@ -4348,7 +3925,7 @@ void VisualScriptEditor::_menu_option(int p_what) { return; } } else { - // pick the node with input sequence + // Pick the node with input sequence. Set<int> nodes_from; Set<int> nodes_to; for (List<VisualScript::SequenceConnection>::Element *E = seqs.front(); E; E = E->next()) { @@ -4369,13 +3946,13 @@ void VisualScriptEditor::_menu_option(int p_what) { nodes_to.insert(E->get().to_node); } - // to use to add return nodes + // To use to add return nodes. _get_ends(start_node, seqs, selections, end_nodes); if (start_node == -1) { - // if we still don't have a start node then - // run through the nodes and select the first tree node - // ie node without any input sequence but output sequence + // If we still don't have a start node then, + // run through the nodes and select the first tree node, + // ie node without any input sequence but output sequence. for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) { if (!nodes_to.has(E->get())) { start_node = E->get(); @@ -4386,20 +3963,20 @@ void VisualScriptEditor::_menu_option(int p_what) { } if (start_node == -1) { - return; // this should not happen, but just in case something goes wrong + return; // This should not happen, but just in case something goes wrong. } List<Variant::Type> inputs; // input types List<Pair<int, int>> input_connections; { List<VisualScript::DataConnection> dats; - script->get_data_connection_list(function, &dats); + script->get_data_connection_list(&dats); for (List<VisualScript::DataConnection>::Element *E = dats.front(); E; E = E->next()) { if (nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) { datamove.insert(E->get()); } else if (!nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) { - // add all these as inputs for the Function - Ref<VisualScriptNode> node = script->get_node(function, E->get().to_node); + // Add all these as inputs for the Function. + Ref<VisualScriptNode> node = script->get_node(E->get().to_node); if (node.is_valid()) { dataext.insert(E->get()); PropertyInfo pi = node->get_input_value_port_info(E->get().to_port); @@ -4411,59 +3988,55 @@ void VisualScriptEditor::_menu_option(int p_what) { } } } - - String new_fn = _validate_name("new_function"); - - Vector2 ofs = _get_available_pos(false, script->get_node_position(function, start_node) - Vector2(80, 150)); - - Ref<VisualScriptFunction> func_node; - func_node.instance(); - func_node->set_name(new_fn); - - undo_redo->create_action(TTR("Create Function")); - - undo_redo->add_do_method(script.ptr(), "add_function", new_fn); int fn_id = script->get_available_id(); - undo_redo->add_do_method(script.ptr(), "add_node", new_fn, fn_id, func_node, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_function", new_fn); - undo_redo->add_do_method(this, "_update_members"); - undo_redo->add_undo_method(this, "_update_members"); - undo_redo->add_do_method(this, "emit_signal", "edited_script_changed"); - undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); - - // Move the nodes + { + String new_fn = _validate_name("new_function"); - for (Map<int, Ref<VisualScriptNode>>::Element *E = nodes.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "remove_node", function, E->key()); - undo_redo->add_do_method(script.ptr(), "add_node", new_fn, E->key(), E->get(), script->get_node_position(function, E->key())); + Vector2 ofs = _get_available_pos(false, script->get_node_position(start_node) - Vector2(80, 150)); - // undo_redo->add_undo_method(script.ptr(), "remove_node", new_fn, E->key()); not needed cause we already remove the function :P - undo_redo->add_undo_method(script.ptr(), "add_node", function, E->key(), E->get(), script->get_node_position(function, E->key())); - } + Ref<VisualScriptFunction> func_node; + func_node.instance(); + func_node->set_name(new_fn); - for (Set<VisualScript::SequenceConnection>::Element *E = seqmove.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", new_fn, E->get().from_node, E->get().from_output, E->get().to_node); - undo_redo->add_undo_method(script.ptr(), "sequence_connect", function, E->get().from_node, E->get().from_output, E->get().to_node); - } + undo_redo->create_action(TTR("Create Function")); - for (Set<VisualScript::DataConnection>::Element *E = datamove.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "data_connect", new_fn, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", function, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(script.ptr(), "add_function", new_fn, fn_id); + undo_redo->add_do_method(script.ptr(), "add_node", fn_id, func_node, ofs); + undo_redo->add_undo_method(script.ptr(), "remove_function", new_fn); + undo_redo->add_undo_method(script.ptr(), "remove_node", fn_id); + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->add_do_method(this, "emit_signal", "edited_script_changed"); + undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); + // Might make the system more intelligent by checking port from info. + int i = 0; + List<Pair<int, int>>::Element *F = input_connections.front(); + for (List<Variant::Type>::Element *E = inputs.front(); E && F; E = E->next(), F = F->next()) { + func_node->add_argument(E->get(), "arg_" + String::num_int64(i), i); + undo_redo->add_do_method(script.ptr(), "data_connect", fn_id, i, F->get().first, F->get().second); + i++; // increment i + } + // Ensure Preview Selection is of newly created function node. + if (selections.size()) { + EditorNode::get_singleton()->push_item(func_node.ptr()); + } } + // Move the nodes. - // Add undo for external connections as well so that it's easier to revert back and forth - // these didn't require do methods as it's already handled internally by other do calls + // Handles reconnection of sequence connections on undo, start here in case of issues. for (Set<VisualScript::SequenceConnection>::Element *E = seqext.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", function, E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_do_method(script.ptr(), "sequence_disconnect", E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node); } for (Set<VisualScript::DataConnection>::Element *E = dataext.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", function, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(script.ptr(), "data_disconnect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } - // I don't really think we need support for non sequenced functions at this moment - undo_redo->add_do_method(script.ptr(), "sequence_connect", new_fn, fn_id, 0, start_node); + // I don't really think we need support for non sequenced functions at this moment. + undo_redo->add_do_method(script.ptr(), "sequence_connect", fn_id, 0, start_node); - // end nodes are mapped to the return nodes with data connections if possible + // Could fail with the new changes, start here when searching for bugs in create function shortcut. int m = 1; for (Set<int>::Element *G = end_nodes.front(); G; G = G->next()) { Ref<VisualScriptReturn> ret_node; @@ -4471,36 +4044,27 @@ void VisualScriptEditor::_menu_option(int p_what) { int ret_id = fn_id + (m++); selections.insert(ret_id); - Vector2 ofsi = _get_available_pos(false, script->get_node_position(function, G->get()) + Vector2(80, -100)); - undo_redo->add_do_method(script.ptr(), "add_node", new_fn, ret_id, ret_node, ofsi); - undo_redo->add_undo_method(script.ptr(), "remove_node", new_fn, ret_id); + Vector2 ofsi = _get_available_pos(false, script->get_node_position(G->get()) + Vector2(80, -100)); + undo_redo->add_do_method(script.ptr(), "add_node", ret_id, ret_node, ofsi); + undo_redo->add_undo_method(script.ptr(), "remove_node", ret_id); - undo_redo->add_do_method(script.ptr(), "sequence_connect", new_fn, G->get(), 0, ret_id); - // add data outputs from each of the end_nodes - Ref<VisualScriptNode> vsn = script->get_node(function, G->get()); + undo_redo->add_do_method(script.ptr(), "sequence_connect", G->get(), 0, ret_id); + // Add data outputs from each of the end_nodes. + Ref<VisualScriptNode> vsn = script->get_node(G->get()); if (vsn.is_valid() && vsn->get_output_value_port_count() > 0) { ret_node->set_enable_return_value(true); - // use the zeroth data port cause that's the likely one that is planned to be used + // Use the zeroth data port cause that's the likely one that is planned to be used. ret_node->set_return_type(vsn->get_output_value_port_info(0).type); - undo_redo->add_do_method(script.ptr(), "data_connect", new_fn, G->get(), 0, ret_id, 0); + undo_redo->add_do_method(script.ptr(), "data_connect", G->get(), 0, ret_id, 0); } } - // * might make the system more intelligent by checking port from info. - int i = 0; - List<Pair<int, int>>::Element *F = input_connections.front(); - for (List<Variant::Type>::Element *E = inputs.front(); E && F; E = E->next(), F = F->next()) { - func_node->add_argument(E->get(), "arg_" + String::num_int64(i), i); - undo_redo->add_do_method(script.ptr(), "data_connect", new_fn, fn_id, i, F->get().first, F->get().second); - i++; // increment i - } - undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); - // make sure all Nodes get marked for selection so that they can be moved together + // Make sure all Nodes get marked for selection so that they can be moved together. selections.insert(fn_id); for (int k = 0; k < graph->get_child_count(); k++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(k)); @@ -4510,11 +4074,6 @@ void VisualScriptEditor::_menu_option(int p_what) { } } - // Ensure Preview Selection is of newly created function node - if (selections.size()) { - EditorNode::get_singleton()->push_item(func_node.ptr()); - } - } break; case REFRESH_GRAPH: { _update_graph(); @@ -4522,16 +4081,16 @@ void VisualScriptEditor::_menu_option(int p_what) { } } -// this is likely going to be very slow and I am not sure if I should keep it -// but I hope that it will not be a problem considering that we won't be creating functions so frequently -// and cyclic connections would be a problem but hopefully we won't let them get to this point +// This is likely going to be very slow and I am not sure if I should keep it, +// but I hope that it will not be a problem considering that we won't be creating functions so frequently, +// and cyclic connections would be a problem but hopefully we won't let them get to this point. void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes) { for (const List<VisualScript::SequenceConnection>::Element *E = p_seqs.front(); E; E = E->next()) { int from = E->get().from_node; int to = E->get().to_node; if (from == p_node && p_selected.has(to)) { - // this is an interior connection move forward to the to node + // This is an interior connection move forward to the to node. _get_ends(to, p_seqs, p_selected, r_end_nodes); } else if (from == p_node && !p_selected.has(to)) { r_end_nodes.insert(from); @@ -4591,34 +4150,29 @@ void VisualScriptEditor::_member_option(int p_option) { switch (member_type) { case MEMBER_FUNCTION: { if (p_option == MEMBER_REMOVE) { - //delete the function + // Delete the function. String name = member_name; - + List<String> lst; + int fn_node = script->get_function_node_id(name); undo_redo->create_action(TTR("Remove Function")); undo_redo->add_do_method(script.ptr(), "remove_function", name); - undo_redo->add_undo_method(script.ptr(), "add_function", name); - List<int> nodes; - script->get_node_list(name, &nodes); - for (List<int>::Element *E = nodes.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "add_node", name, E->get(), script->get_node(name, E->get()), script->get_node_position(name, E->get())); - } - - List<VisualScript::SequenceConnection> seq_connections; - - script->get_sequence_connection_list(name, &seq_connections); - - for (List<VisualScript::SequenceConnection>::Element *E = seq_connections.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", name, E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_do_method(script.ptr(), "remove_node", fn_node); + undo_redo->add_undo_method(script.ptr(), "add_function", name, fn_node); + undo_redo->add_undo_method(script.ptr(), "add_node", fn_node, script->get_node(fn_node), script->get_node_position(fn_node)); + List<VisualScript::SequenceConnection> seqcons; + script->get_sequence_connection_list(&seqcons); + for (const List<VisualScript::SequenceConnection>::Element *E = seqcons.front(); E; E = E->next()) { + if (E->get().from_node == fn_node) { + undo_redo->add_undo_method(script.ptr(), "sequence_connect", fn_node, E->get().from_output, E->get().to_node); + } } - - List<VisualScript::DataConnection> data_connections; - - script->get_data_connection_list(name, &data_connections); - - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", name, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + List<VisualScript::DataConnection> datcons; + script->get_data_connection_list(&datcons); + for (const List<VisualScript::DataConnection>::Element *E = datcons.front(); E; E = E->next()) { + if (E->get().from_node == fn_node) { + undo_redo->add_undo_method(script.ptr(), "data_connect", fn_node, E->get().from_port, E->get().to_node, E->get().to_port); + } } - undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); undo_redo->add_do_method(this, "_update_graph"); @@ -4711,6 +4265,7 @@ VisualScriptEditor::VisualScriptEditor() { saved_position = Vector2(0, 0); edit_menu = memnew(MenuButton); + edit_menu->set_shortcut_context(this); edit_menu->set_text(TTR("Edit")); edit_menu->set_switch_on_hover(true); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES); @@ -4767,14 +4322,16 @@ VisualScriptEditor::VisualScriptEditor() { graph = memnew(GraphEdit); add_child(graph); graph->set_v_size_flags(Control::SIZE_EXPAND_FILL); - graph->set_anchors_and_margins_preset(Control::PRESET_WIDE); + graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE); graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected)); - graph->connect("_begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); - graph->connect("_end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move)); + graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); + graph->connect("end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move)); graph->connect("delete_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_delete)); graph->connect("duplicate_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_duplicate)); graph->connect("gui_input", callable_mp(this, &VisualScriptEditor::_graph_gui_input)); graph->set_drag_forwarding(this); + float graph_minimap_opacity = EditorSettings::get_singleton()->get("editors/visual_editors/minimap_opacity"); + graph->set_minimap_opacity(graph_minimap_opacity); graph->hide(); graph->connect("scroll_offset_changed", callable_mp(this, &VisualScriptEditor::_graph_ofs_changed)); @@ -4839,8 +4396,8 @@ VisualScriptEditor::VisualScriptEditor() { function_create_dialog = memnew(ConfirmationDialog); function_create_dialog->set_title(TTR("Create Function")); function_create_dialog->add_child(function_vb); - function_create_dialog->get_ok()->set_text(TTR("Create")); - function_create_dialog->get_ok()->connect("pressed", callable_mp(this, &VisualScriptEditor::_create_function)); + function_create_dialog->get_ok_button()->set_text(TTR("Create")); + function_create_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualScriptEditor::_create_function)); add_child(function_create_dialog); select_func_text = memnew(Label); @@ -4851,9 +4408,9 @@ VisualScriptEditor::VisualScriptEditor() { add_child(select_func_text); hint_text = memnew(Label); - hint_text->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -100); - hint_text->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); - hint_text->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); + hint_text->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -100); + hint_text->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0); + hint_text->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0); hint_text->set_align(Label::ALIGN_CENTER); hint_text->set_valign(Label::VALIGN_CENTER); graph->add_child(hint_text); @@ -4883,7 +4440,7 @@ VisualScriptEditor::VisualScriptEditor() { graph->connect("connection_to_empty", callable_mp(this, &VisualScriptEditor::_graph_connect_to_empty)); edit_signal_dialog = memnew(AcceptDialog); - edit_signal_dialog->get_ok()->set_text(TTR("Close")); + edit_signal_dialog->get_ok_button()->set_text(TTR("Close")); add_child(edit_signal_dialog); signal_editor = memnew(VisualScriptEditorSignalEdit); @@ -4893,7 +4450,7 @@ VisualScriptEditor::VisualScriptEditor() { edit_signal_edit->edit(signal_editor); edit_variable_dialog = memnew(AcceptDialog); - edit_variable_dialog->get_ok()->set_text(TTR("Close")); + edit_variable_dialog->get_ok_button()->set_text(TTR("Close")); add_child(edit_variable_dialog); variable_editor = memnew(VisualScriptEditorVariableEdit); @@ -4912,7 +4469,6 @@ VisualScriptEditor::VisualScriptEditor() { updating_members = false; set_process_input(true); - set_process_unhandled_input(true); default_value_edit = memnew(CustomPropertyEditor); add_child(default_value_edit); @@ -4926,7 +4482,7 @@ VisualScriptEditor::VisualScriptEditor() { new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); new_connect_node_select->connect("selected", callable_mp(this, &VisualScriptEditor::_selected_connect_node)); - new_connect_node_select->get_cancel()->connect("pressed", callable_mp(this, &VisualScriptEditor::_cancel_connect_node)); + new_connect_node_select->get_cancel_button()->connect("pressed", callable_mp(this, &VisualScriptEditor::_cancel_connect_node)); new_virtual_method_select = memnew(VisualScriptPropertySelector); add_child(new_virtual_method_select); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 0c5665cee8..bb6f194286 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,7 +64,6 @@ class VisualScriptEditor : public ScriptEditorBase { }; enum PortAction { - CREATE_CALL_SET_GET, CREATE_ACTION, }; @@ -137,8 +136,6 @@ class VisualScriptEditor : public ScriptEditorBase { }; HashMap<StringName, Ref<StyleBox>> node_styles; - StringName edited_func; - StringName default_func; void _update_graph_connections(); void _update_graph(int p_only_id = -1); @@ -146,6 +143,7 @@ class VisualScriptEditor : public ScriptEditorBase { bool updating_members; void _update_members(); + String _sanitized_variant_text(const StringName &property_name); StringName selected; @@ -176,7 +174,7 @@ class VisualScriptEditor : public ScriptEditorBase { Vector2 mouse_up_position; - void _port_action_menu(int p_option, const StringName &p_func); + void _port_action_menu(int p_option); void connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id); @@ -184,13 +182,13 @@ class VisualScriptEditor : public ScriptEditorBase { void connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id); void _cancel_connect_node(); - int _create_new_node_from_name(const String &p_text, const Vector2 &p_point, const StringName &p_func = StringName()); + int _create_new_node_from_name(const String &p_text, const Vector2 &p_point); void _selected_new_virtual_method(const String &p_text, const String &p_category, const bool p_connecting); int error_line; void _node_selected(Node *p_node); - void _center_on_node(const StringName &p_func, int p_id); + void _center_on_node(int p_id); void _node_filter_changed(const String &p_text); void _change_base_type_callback(); @@ -201,7 +199,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _begin_node_move(); void _end_node_move(); - void _move_node(const StringName &p_func, int p_id, const Vector2 &p_to); + void _move_node(int p_id, const Vector2 &p_to); void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes); @@ -211,7 +209,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _graph_disconnected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot); void _graph_connect_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_pos); - void _node_ports_changed(const String &p_func, int p_id); + void _node_ports_changed(int p_id); void _node_create(); void _update_available_nodes(); @@ -228,10 +226,8 @@ class VisualScriptEditor : public ScriptEditorBase { void _port_name_focus_out(const Node *p_name_box, int p_id, int p_port, bool is_input); Vector2 _get_available_pos(bool centered = true, Vector2 ofs = Vector2()) const; - StringName _get_function_of_node(int p_id) const; - void _move_nodes_with_rescan(const StringName &p_func_from, const StringName &p_func_to, int p_id); - bool node_has_sequence_connections(const StringName &p_func, int p_id); + bool node_has_sequence_connections(int p_id); void _generic_search(String p_base_type = "", Vector2 pos = Vector2(), bool node_centered = false); @@ -312,7 +308,7 @@ public: virtual void ensure_focus() override; virtual void tag_saved_version() override; virtual void reload(bool p_soft) override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; virtual void update_settings() override; virtual bool show_members_overview() override; diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 2ac7793b8c..9596fda95c 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -187,7 +187,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { while (true) { #define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++]) - CharType cchar = GET_CHAR(); + char32_t cchar = GET_CHAR(); if (cchar == 0) { r_token.type = TK_EOF; return OK; @@ -329,7 +329,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { case '"': { String str; while (true) { - CharType ch = GET_CHAR(); + char32_t ch = GET_CHAR(); if (ch == 0) { _set_error("Unterminated String"); @@ -340,13 +340,13 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } else if (ch == '\\') { //escaped characters... - CharType next = GET_CHAR(); + char32_t next = GET_CHAR(); if (next == 0) { _set_error("Unterminated String"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -367,7 +367,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { case 'u': { // hex number for (int j = 0; j < 4; j++) { - CharType c = GET_CHAR(); + char32_t c = GET_CHAR(); if (c == 0) { _set_error("Unterminated String"); @@ -379,7 +379,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType v; + char32_t v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -431,7 +431,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { #define READING_DONE 4 int reading = READING_INT; - CharType c = cchar; + char32_t c = cchar; bool exp_sign = false; bool exp_beg = false; bool is_float = false; @@ -1341,7 +1341,7 @@ public: } bool valid; - r_ret = base.get_named(index->name, &valid); + r_ret = base.get_named(index->name, valid); if (!valid) { r_error_str = "Invalid index '" + String(index->name) + "' for base of type " + Variant::get_type_name(base.get_type()) + "."; return true; @@ -1405,7 +1405,7 @@ public: argp.write[i] = &arr[i]; } - r_ret = Variant::construct(constructor->data_type, (const Variant **)argp.ptr(), argp.size(), ce); + Variant::construct(constructor->data_type, r_ret, (const Variant **)argp.ptr(), argp.size(), ce); if (ce.error != Callable::CallError::CALL_OK) { r_error_str = "Invalid arguments to construct '" + Variant::get_type_name(constructor->data_type) + "'."; @@ -1463,7 +1463,7 @@ public: argp.write[i] = &arr[i]; } - r_ret = base.call(call->method, (const Variant **)argp.ptr(), argp.size(), ce); + base.call(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce); if (ce.error != Callable::CallError::CALL_OK) { r_error_str = "On call to '" + String(call->method) + "':"; diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h index 2b3b25842d..7fe665769d 100644 --- a/modules/visual_script/visual_script_expression.h +++ b/modules/visual_script/visual_script_expression.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 3ed20fab35..0049e254c4 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "visual_script_flow_control.h" +#include "core/config/project_settings.h" #include "core/io/resource_loader.h" #include "core/os/keyboard.h" -#include "core/project_settings.h" ////////////////////////////////////////// ////////////////RETURN//////////////////// diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 1d0d6d103b..46a72bb92d 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index f13377f3c8..d016b938de 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "visual_script_func_nodes.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/io/resource_loader.h" #include "core/os/os.h" #include "scene/main/node.h" @@ -42,7 +42,7 @@ ////////////////////////////////////////// int VisualScriptFunctionCall::get_output_sequence_port_count() const { - if ((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function))) { + if ((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_builtin_method_const(basic_type, function))) { return 0; } else { return 1; @@ -50,7 +50,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const { } bool VisualScriptFunctionCall::has_input_sequence_port() const { - return !((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function))); + return !((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_builtin_method_const(basic_type, function))); } #ifdef TOOLS_ENABLED @@ -130,7 +130,11 @@ StringName VisualScriptFunctionCall::_get_base_type() const { int VisualScriptFunctionCall::get_input_value_port_count() const { if (call_mode == CALL_MODE_BASIC_TYPE) { - Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function); + Vector<Variant::Type> types; + int argc = Variant::get_builtin_method_argument_count(basic_type, function); + for (int i = 0; i < argc; i++) { + types.push_back(Variant::get_builtin_method_argument_type(basic_type, function, i)); + } return types.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1; } else { @@ -147,8 +151,7 @@ int VisualScriptFunctionCall::get_input_value_port_count() const { int VisualScriptFunctionCall::get_output_value_port_count() const { if (call_mode == CALL_MODE_BASIC_TYPE) { - bool returns = false; - Variant::get_method_return_type(basic_type, function, &returns); + bool returns = Variant::has_builtin_method_return_value(basic_type, function); return returns ? 1 : 0; } else { @@ -195,10 +198,7 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons #ifdef DEBUG_METHODS_ENABLED if (call_mode == CALL_MODE_BASIC_TYPE) { - Vector<StringName> names = Variant::get_method_argument_names(basic_type, function); - Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function); - return PropertyInfo(types[p_idx], names[p_idx]); - + return PropertyInfo(Variant::get_builtin_method_argument_type(basic_type, function, p_idx), Variant::get_builtin_method_argument_name(basic_type, function, p_idx)); } else { MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { @@ -220,7 +220,7 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con #ifdef DEBUG_METHODS_ENABLED if (call_mode == CALL_MODE_BASIC_TYPE) { - return PropertyInfo(Variant::get_method_return_type(basic_type, function), ""); + return PropertyInfo(Variant::get_builtin_method_return_type(basic_type, function), ""); } else { if (call_mode == CALL_MODE_INSTANCE) { if (p_idx == 0) { @@ -234,7 +234,6 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con /*MethodBind *mb = ClassDB::get_method(_get_base_type(),function); if (mb) { - ret = mb->get_argument_info(-1); } else {*/ @@ -419,7 +418,7 @@ void VisualScriptFunctionCall::set_function(const StringName &p_type) { function = p_type; if (call_mode == CALL_MODE_BASIC_TYPE) { - use_default_args = Variant::get_method_default_arguments(basic_type, function).size(); + use_default_args = Variant::get_builtin_method_default_arguments(basic_type, function).size(); } else { //update all caches @@ -606,7 +605,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const int mc = 0; if (call_mode == CALL_MODE_BASIC_TYPE) { - mc = Variant::get_method_default_arguments(basic_type, function).size(); + mc = Variant::get_builtin_method_default_arguments(basic_type, function).size(); } else { MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { @@ -805,19 +804,21 @@ public: } else if (returns) { if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) { if (returns >= 2) { - *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error); + v.call(function, p_inputs + 1, input_args, *p_outputs[1], r_error); } else if (returns == 1) { - v.call(function, p_inputs + 1, input_args, r_error); + Variant ret; + v.call(function, p_inputs + 1, input_args, ret, r_error); } else { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE"; return 0; } } else { - *p_outputs[0] = v.call(function, p_inputs + 1, input_args, r_error); + v.call(function, p_inputs + 1, input_args, *p_outputs[0], r_error); } } else { - v.call(function, p_inputs + 1, input_args, r_error); + Variant ret; + v.call(function, p_inputs + 1, input_args, ret, r_error); } if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) { @@ -976,7 +977,7 @@ void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const { if (index != StringName()) { Variant v; Callable::CallError ce; - v = Variant::construct(pinfo.type, nullptr, 0, ce); + Variant::construct(pinfo.type, v, nullptr, 0, ce); Variant i = v.get(index); pinfo.type = i.get_type(); } @@ -1117,7 +1118,7 @@ void VisualScriptPropertySet::_update_cache() { Variant v; Callable::CallError ce; - v = Variant::construct(basic_type, nullptr, 0, ce); + Variant::construct(basic_type, v, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); @@ -1336,7 +1337,8 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { if (property.name == "index") { Callable::CallError ce; - Variant v = Variant::construct(type_cache.type, nullptr, 0, ce); + Variant v; + Variant::construct(type_cache.type, v, nullptr, 0, ce); List<PropertyInfo> plist; v.get_property_list(&plist); String options = ""; @@ -1449,11 +1451,11 @@ public: _FORCE_INLINE_ void _process_get(Variant &source, const Variant &p_argument, bool &valid) { if (index != StringName() && assign_op == VisualScriptPropertySet::ASSIGN_OP_NONE) { - source.set_named(index, p_argument, &valid); + source.set_named(index, p_argument, valid); } else { Variant value; if (index != StringName()) { - value = source.get_named(index, &valid); + value = source.get_named(index, valid); } else { value = source; } @@ -1497,7 +1499,7 @@ public: } if (index != StringName()) { - source.set_named(index, value, &valid); + source.set_named(index, value, valid); } else { source = value; } @@ -1562,12 +1564,12 @@ public: bool valid; if (needs_get) { - Variant value = v.get_named(property, &valid); + Variant value = v.get_named(property, valid); _process_get(value, *p_inputs[1], valid); - v.set_named(property, value, &valid); + v.set_named(property, value, valid); } else { - v.set_named(property, *p_inputs[1], &valid); + v.set_named(property, *p_inputs[1], valid); } if (!valid) { @@ -1786,7 +1788,7 @@ void VisualScriptPropertyGet::_update_cache() { Variant v; Callable::CallError ce; - v = Variant::construct(basic_type, nullptr, 0, ce); + Variant::construct(basic_type, v, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); @@ -2012,7 +2014,8 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { if (property.name == "index") { Callable::CallError ce; - Variant v = Variant::construct(type_cache, nullptr, 0, ce); + Variant v; + Variant::construct(type_cache, v, nullptr, 0, ce); List<PropertyInfo> plist; v.get_property_list(&plist); String options = ""; @@ -2088,6 +2091,7 @@ void VisualScriptPropertyGet::_bind_methods() { BIND_ENUM_CONSTANT(CALL_MODE_SELF); BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH); BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE); + BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE); } class VisualScriptNodeInstancePropertyGet : public VisualScriptNodeInstance { @@ -2110,7 +2114,7 @@ public: *p_outputs[0] = object->get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) { @@ -2139,7 +2143,7 @@ public: *p_outputs[0] = another->get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) { @@ -2155,7 +2159,7 @@ public: *p_outputs[0] = v.get(property, &valid); if (index != StringName()) { - *p_outputs[0] = p_outputs[0]->get_named(index); + *p_outputs[0] = p_outputs[0]->get_named(index, valid); } if (!valid) { @@ -2367,7 +2371,8 @@ void register_visual_script_func_nodes() { Variant::Type t = Variant::Type(i); String type_name = Variant::get_type_name(t); Callable::CallError ce; - Variant vt = Variant::construct(t, nullptr, 0, ce); + Variant vt; + Variant::construct(t, vt, nullptr, 0, ce); List<MethodInfo> ml; vt.get_method_list(&ml); diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 8372df561f..2ff9b7a981 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 87aa64211e..ae2b548f21 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,11 @@ #include "visual_script_nodes.h" -#include "core/engine.h" -#include "core/global_constants.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/core_constants.h" #include "core/input/input.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" @@ -828,7 +828,6 @@ PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { { Variant::NIL, Variant::NIL }, //OP_NEGATE, { Variant::NIL, Variant::NIL }, //OP_POSITIVE, { Variant::INT, Variant::INT }, //OP_MODULE, - { Variant::STRING, Variant::STRING }, //OP_STRING_CONCAT, //bitwise { Variant::INT, Variant::INT }, //OP_SHIFT_LEFT, { Variant::INT, Variant::INT }, //OP_SHIFT_RIGHT, @@ -873,7 +872,6 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { Variant::NIL, //OP_NEGATE, Variant::NIL, //OP_POSITIVE, Variant::INT, //OP_MODULE, - Variant::STRING, //OP_STRING_CONCAT, //bitwise Variant::INT, //OP_SHIFT_LEFT, Variant::INT, //OP_SHIFT_RIGHT, @@ -933,36 +931,36 @@ static const char *op_names[] = { }; String VisualScriptOperator::get_caption() const { - static const wchar_t *op_names[] = { + static const char32_t *op_names[] = { //comparison - L"A = B", //OP_EQUAL, - L"A \u2260 B", //OP_NOT_EQUAL, - L"A < B", //OP_LESS, - L"A \u2264 B", //OP_LESS_EQUAL, - L"A > B", //OP_GREATER, - L"A \u2265 B", //OP_GREATER_EQUAL, + U"A = B", //OP_EQUAL, + U"A \u2260 B", //OP_NOT_EQUAL, + U"A < B", //OP_LESS, + U"A \u2264 B", //OP_LESS_EQUAL, + U"A > B", //OP_GREATER, + U"A \u2265 B", //OP_GREATER_EQUAL, //mathematic - L"A + B", //OP_ADD, - L"A - B", //OP_SUBTRACT, - L"A \u00D7 B", //OP_MULTIPLY, - L"A \u00F7 B", //OP_DIVIDE, - L"\u00AC A", //OP_NEGATE, - L"+ A", //OP_POSITIVE, - L"A mod B", //OP_MODULE, - L"A .. B", //OP_STRING_CONCAT, + U"A + B", //OP_ADD, + U"A - B", //OP_SUBTRACT, + U"A \u00D7 B", //OP_MULTIPLY, + U"A \u00F7 B", //OP_DIVIDE, + U"\u00AC A", //OP_NEGATE, + U"+ A", //OP_POSITIVE, + U"A mod B", //OP_MODULE, + U"A .. B", //OP_STRING_CONCAT, //bitwise - L"A << B", //OP_SHIFT_LEFT, - L"A >> B", //OP_SHIFT_RIGHT, - L"A & B", //OP_BIT_AND, - L"A | B", //OP_BIT_OR, - L"A ^ B", //OP_BIT_XOR, - L"~A", //OP_BIT_NEGATE, + U"A << B", //OP_SHIFT_LEFT, + U"A >> B", //OP_SHIFT_RIGHT, + U"A & B", //OP_BIT_AND, + U"A | B", //OP_BIT_OR, + U"A ^ B", //OP_BIT_XOR, + U"~A", //OP_BIT_NEGATE, //logic - L"A and B", //OP_AND, - L"A or B", //OP_OR, - L"A xor B", //OP_XOR, - L"not A", //OP_NOT, - L"A in B", //OP_IN, + U"A and B", //OP_AND, + U"A or B", //OP_OR, + U"A xor B", //OP_XOR, + U"not A", //OP_NOT, + U"A in B", //OP_IN, }; return op_names[op]; @@ -1433,7 +1431,7 @@ void VisualScriptConstant::set_constant_type(Variant::Type p_type) { type = p_type; Callable::CallError ce; - value = Variant::construct(type, nullptr, 0, ce); + Variant::construct(type, value, nullptr, 0, ce); ports_changed_notify(); _change_notify(); } @@ -1706,8 +1704,10 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { bool valid; + // *p_output[0] points to the same place as *p_inputs[2] so we need a temp to store the value before the change in the next line + Variant temp = *p_inputs[2]; *p_outputs[0] = *p_inputs[0]; - p_outputs[0]->set(*p_inputs[1], *p_inputs[2], &valid); + p_outputs[0]->set(*p_inputs[1], temp, &valid); if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -1754,7 +1754,7 @@ PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) co } PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) const { - String name = GlobalConstants::get_global_constant_name(index); + String name = CoreConstants::get_global_constant_name(index); return PropertyInfo(Variant::INT, name); } @@ -1778,7 +1778,7 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = GlobalConstants::get_global_constant_value(index); + *p_outputs[0] = CoreConstants::get_global_constant_value(index); return 0; } }; @@ -1795,11 +1795,11 @@ void VisualScriptGlobalConstant::_bind_methods() { String cc; - for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) { + for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { if (i > 0) { cc += ","; } - cc += GlobalConstants::get_global_constant_name(i); + cc += CoreConstants::get_global_constant_name(i); } ADD_PROPERTY(PropertyInfo(Variant::INT, "constant", PROPERTY_HINT_ENUM, cc), "set_global_constant", "get_global_constant"); } @@ -3255,7 +3255,7 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { Callable::CallError ce; - *p_outputs[0] = Variant::construct(type, p_inputs, argcount, ce); + Variant::construct(type, *p_outputs[0], p_inputs, argcount, ce); if (ce.error != Callable::CallError::CALL_OK) { r_error_str = "Invalid arguments for constructor"; } @@ -3727,7 +3727,7 @@ void VisualScriptDeconstruct::_update_elements() { elements.clear(); Variant v; Callable::CallError ce; - v = Variant::construct(type, nullptr, 0, ce); + Variant::construct(type, v, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); @@ -3879,7 +3879,6 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/math/negate", create_op_node<Variant::OP_NEGATE>); VisualScriptLanguage::singleton->add_register_func("operators/math/positive", create_op_node<Variant::OP_POSITIVE>); VisualScriptLanguage::singleton->add_register_func("operators/math/remainder", create_op_node<Variant::OP_MODULE>); - VisualScriptLanguage::singleton->add_register_func("operators/math/string_concat", create_op_node<Variant::OP_STRING_CONCAT>); //bitwise VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_left", create_op_node<Variant::OP_SHIFT_LEFT>); VisualScriptLanguage::singleton->add_register_func("operators/bitwise/shift_right", create_op_node<Variant::OP_SHIFT_RIGHT>); diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index b6061f8838..ae5e04d096 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index 3c44faab90..862cac5c67 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,6 +31,7 @@ #include "visual_script_property_selector.h" #include "core/os/keyboard.h" +#include "editor/doc_tools.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "modules/visual_script/visual_script.h" @@ -196,7 +197,7 @@ void VisualScriptPropertySelector::_update_search() { if (type != Variant::NIL) { Variant v; Callable::CallError ce; - v = Variant::construct(type, nullptr, 0, ce); + Variant::construct(type, v, nullptr, 0, ce); v.get_method_list(&methods); } else { Object *obj = ObjectDB::get_instance(script); @@ -309,7 +310,7 @@ void VisualScriptPropertySelector::_update_search() { found = true; } - get_ok()->set_disabled(root->get_children() == nullptr); + get_ok_button()->set_disabled(root->get_children() == nullptr); } void VisualScriptPropertySelector::create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text) { @@ -357,7 +358,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt continue; } - bool in_modifier = p_modifiers.empty(); + bool in_modifier = p_modifiers.is_empty(); for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) { if (E->get().findn(F->get()) != -1) { in_modifier = true; @@ -437,7 +438,7 @@ void VisualScriptPropertySelector::_item_selected() { class_type = base_type; } - DocData *dd = EditorHelp::get_doc_data(); + DocTools *dd = EditorHelp::get_doc_data(); String text; String at_class = class_type; @@ -704,8 +705,8 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() { search_box->connect("gui_input", callable_mp(this, &VisualScriptPropertySelector::_sbox_input)); search_options = memnew(Tree); vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_text(TTR("Open")); - get_ok()->set_disabled(true); + get_ok_button()->set_text(TTR("Open")); + get_ok_button()->set_disabled(true); register_text_enter(search_box); set_hide_on_ok(false); search_options->connect("item_activated", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); diff --git a/modules/visual_script/visual_script_property_selector.h b/modules/visual_script/visual_script_property_selector.h index cc49b2863d..7a87f3d3ee 100644 --- a/modules/visual_script/visual_script_property_selector.h +++ b/modules/visual_script/visual_script_property_selector.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index dd07cc45a7..6c9af4e600 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h index 7a72211027..cc7ce0a1c6 100644 --- a/modules/visual_script/visual_script_yield_nodes.h +++ b/modules/visual_script/visual_script_yield_nodes.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |