diff options
Diffstat (limited to 'modules/visual_script')
71 files changed, 3676 insertions, 1652 deletions
diff --git a/modules/visual_script/SCsub b/modules/visual_script/SCsub index 96ee911ba0..3c3d2caa57 100644 --- a/modules/visual_script/SCsub +++ b/modules/visual_script/SCsub @@ -6,5 +6,3 @@ Import('env_modules') env_vs = env_modules.Clone() env_vs.add_source_files(env.modules_sources, "*.cpp") - -Export('env') diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py index 07a0450734..087a13a200 100644 --- a/modules/visual_script/config.py +++ b/modules/visual_script/config.py @@ -6,10 +6,12 @@ def configure(env): def get_doc_classes(): return [ + "@VisualScript", "VisualScriptBasicTypeConstant", "VisualScriptBuiltinFunc", "VisualScriptClassConstant", "VisualScriptComment", + "VisualScriptComposeArray", "VisualScriptCondition", "VisualScriptConstant", "VisualScriptConstructor", @@ -27,6 +29,7 @@ def get_doc_classes(): "VisualScriptIndexSet", "VisualScriptInputAction", "VisualScriptIterator", + "VisualScriptLists", "VisualScriptLocalVarSet", "VisualScriptLocalVar", "VisualScriptMathConstant", diff --git a/modules/visual_script/doc_classes/@VisualScript.xml b/modules/visual_script/doc_classes/@VisualScript.xml new file mode 100644 index 0000000000..8d9408e6d4 --- /dev/null +++ b/modules/visual_script/doc_classes/@VisualScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="@VisualScript" category="Core" version="3.2"> + <brief_description> + Built-in visual script functions. + </brief_description> + <description> + A list of built-in visual script functions, see [VisualScriptBuiltinFunc] and [VisualScript]. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml index 28764aca40..0d95075152 100644 --- a/modules/visual_script/doc_classes/VisualScript.xml +++ b/modules/visual_script/doc_classes/VisualScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScript" inherits="Script" category="Core" version="3.1"> +<class name="VisualScript" inherits="Script" category="Core" version="3.2"> <brief_description> A script implemented in the Visual Script programming environment. </brief_description> @@ -9,10 +9,8 @@ You are most likely to use this class via the Visual Script editor or when writing plugins for it. </description> <tutorials> - <link>http://docs.godotengine.org/en/3.0/getting_started/scripting/visual_script/index.html</link> + <link>https://docs.godotengine.org/en/latest/getting_started/scripting/visual_script/index.html</link> </tutorials> - <demos> - </demos> <methods> <method name="add_custom_signal"> <return type="void"> @@ -254,7 +252,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Returns the info for a given variable as a dictionary. The information includes its name, type, hint and usage. + Returns the information for a given variable as a dictionary. The information includes its name, type, hint and usage. </description> </method> <method name="has_custom_signal" qualifiers="const"> diff --git a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml index 793291eca2..6dc54dbc03 100644 --- a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml @@ -1,19 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node representing a constant from the base types. </brief_description> <description> - A Visual Script node representing a constant from base types, such as [Vector3.AXIS_X]. + A Visual Script node representing a constant from base types, such as [constant Vector3.AXIS_X]. </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type"> + <member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type" default="0"> The type to get the constant from. </member> <member name="constant" type="String" setter="set_basic_type_constant" getter="get_basic_type_constant"> diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index 399ba8ef5d..b5b452ee47 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node used to call built-in functions. </brief_description> @@ -9,12 +9,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="function" type="int" setter="set_func" getter="get_func" enum="VisualScriptBuiltinFunc.BuiltinFunc"> + <member name="function" type="int" setter="set_func" getter="get_func" enum="VisualScriptBuiltinFunc.BuiltinFunc" default="0"> The function to be executed. </member> </members> @@ -104,108 +102,125 @@ </constant> <constant name="MATH_RANGE_LERP" value="28" enum="BuiltinFunc"> </constant> - <constant name="MATH_DECTIME" value="29" enum="BuiltinFunc"> - Return the result of 'value' decreased by 'step' * 'amount'. + <constant name="MATH_MOVE_TOWARD" value="29" enum="BuiltinFunc"> + Moves the number toward a value, based on the third input. </constant> - <constant name="MATH_RANDOMIZE" value="30" enum="BuiltinFunc"> + <constant name="MATH_DECTIME" value="30" enum="BuiltinFunc"> + Return the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code]. + </constant> + <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="31" enum="BuiltinFunc"> + <constant name="MATH_RAND" 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="32" enum="BuiltinFunc"> + <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="33" enum="BuiltinFunc"> + <constant name="MATH_RANDOM" value="34" enum="BuiltinFunc"> Return a random floating-point value between the two inputs. </constant> - <constant name="MATH_SEED" value="34" enum="BuiltinFunc"> + <constant name="MATH_SEED" value="35" enum="BuiltinFunc"> Set the seed for the random number generator. </constant> - <constant name="MATH_RANDSEED" value="35" enum="BuiltinFunc"> + <constant name="MATH_RANDSEED" value="36" enum="BuiltinFunc"> Return a random value from the given seed, along with the new seed. </constant> - <constant name="MATH_DEG2RAD" value="36" enum="BuiltinFunc"> + <constant name="MATH_DEG2RAD" value="37" enum="BuiltinFunc"> Convert the input from degrees to radians. </constant> - <constant name="MATH_RAD2DEG" value="37" enum="BuiltinFunc"> + <constant name="MATH_RAD2DEG" value="38" enum="BuiltinFunc"> Convert the input from radians to degrees. </constant> - <constant name="MATH_LINEAR2DB" value="38" enum="BuiltinFunc"> + <constant name="MATH_LINEAR2DB" value="39" enum="BuiltinFunc"> Convert the input from linear volume to decibel volume. </constant> - <constant name="MATH_DB2LINEAR" value="39" enum="BuiltinFunc"> + <constant name="MATH_DB2LINEAR" value="40" enum="BuiltinFunc"> Convert the input from decibel volume to linear volume. </constant> - <constant name="MATH_POLAR2CARTESIAN" value="40" 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 name="MATH_POLAR2CARTESIAN" value="41" 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="41" 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 name="MATH_CARTESIAN2POLAR" value="42" 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="42" enum="BuiltinFunc"> + <constant name="MATH_WRAP" value="43" enum="BuiltinFunc"> </constant> - <constant name="MATH_WRAPF" value="43" enum="BuiltinFunc"> + <constant name="MATH_WRAPF" value="44" enum="BuiltinFunc"> </constant> - <constant name="LOGIC_MAX" value="44" enum="BuiltinFunc"> + <constant name="LOGIC_MAX" value="45" enum="BuiltinFunc"> Return the greater of the two numbers, also known as their maximum. </constant> - <constant name="LOGIC_MIN" value="45" enum="BuiltinFunc"> + <constant name="LOGIC_MIN" value="46" enum="BuiltinFunc"> Return the lesser of the two numbers, also known as their minimum. </constant> - <constant name="LOGIC_CLAMP" value="46" enum="BuiltinFunc"> - Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to `min(max(input, range_low), range_high)` + <constant name="LOGIC_CLAMP" value="47" 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="47" enum="BuiltinFunc"> + <constant name="LOGIC_NEAREST_PO2" value="48" enum="BuiltinFunc"> Return the nearest power of 2 to the input. </constant> - <constant name="OBJ_WEAKREF" value="48" enum="BuiltinFunc"> + <constant name="OBJ_WEAKREF" value="49" enum="BuiltinFunc"> Create a [WeakRef] from the input. </constant> - <constant name="FUNC_FUNCREF" value="49" enum="BuiltinFunc"> + <constant name="FUNC_FUNCREF" value="50" enum="BuiltinFunc"> Create a [FuncRef] from the input. </constant> - <constant name="TYPE_CONVERT" value="50" enum="BuiltinFunc"> + <constant name="TYPE_CONVERT" value="51" enum="BuiltinFunc"> Convert between types. </constant> - <constant name="TYPE_OF" value="51" enum="BuiltinFunc"> + <constant name="TYPE_OF" value="52" enum="BuiltinFunc"> Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned. </constant> - <constant name="TYPE_EXISTS" value="52" enum="BuiltinFunc"> + <constant name="TYPE_EXISTS" value="53" enum="BuiltinFunc"> Checks if a type is registered in the [ClassDB]. </constant> - <constant name="TEXT_CHAR" value="53" enum="BuiltinFunc"> + <constant name="TEXT_CHAR" value="54" enum="BuiltinFunc"> Return a character with the given ascii value. </constant> - <constant name="TEXT_STR" value="54" enum="BuiltinFunc"> + <constant name="TEXT_STR" value="55" enum="BuiltinFunc"> Convert the input to a string. </constant> - <constant name="TEXT_PRINT" value="55" enum="BuiltinFunc"> + <constant name="TEXT_PRINT" value="56" enum="BuiltinFunc"> Print the given string to the output window. </constant> - <constant name="TEXT_PRINTERR" value="56" enum="BuiltinFunc"> + <constant name="TEXT_PRINTERR" value="57" enum="BuiltinFunc"> Print the given string to the standard error output. </constant> - <constant name="TEXT_PRINTRAW" value="57" enum="BuiltinFunc"> + <constant name="TEXT_PRINTRAW" value="58" enum="BuiltinFunc"> Print the given string to the standard output, without adding a newline. </constant> - <constant name="VAR_TO_STR" value="58" enum="BuiltinFunc"> + <constant name="VAR_TO_STR" value="59" enum="BuiltinFunc"> Serialize a [Variant] to a string. </constant> - <constant name="STR_TO_VAR" value="59" enum="BuiltinFunc"> - Deserialize a [Variant] from a string serialized using [VAR_TO_STR]. + <constant name="STR_TO_VAR" value="60" enum="BuiltinFunc"> + Deserialize a [Variant] from a string serialized using [constant VAR_TO_STR]. </constant> - <constant name="VAR_TO_BYTES" value="60" enum="BuiltinFunc"> + <constant name="VAR_TO_BYTES" value="61" enum="BuiltinFunc"> Serialize a [Variant] to a [PoolByteArray]. </constant> - <constant name="BYTES_TO_VAR" value="61" enum="BuiltinFunc"> - Deserialize a [Variant] from a [PoolByteArray] serialized using [VAR_TO_BYTES]. + <constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc"> + Deserialize a [Variant] from a [PoolByteArray] serialized using [constant VAR_TO_BYTES]. + </constant> + <constant name="COLORN" value="63" enum="BuiltinFunc"> + Return the [Color] with the given name and alpha ranging from 0 to 1 + [b]Note:[/b] Names are defined in [code]color_names.inc[/code]. + </constant> + <constant name="MATH_SMOOTHSTEP" value="64" enum="BuiltinFunc"> + Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula: + [codeblock] + var t = clamp((weight - from) / (to - from), 0.0, 1.0) + return t * t * (3.0 - 2.0 * t) + [/codeblock] + </constant> + <constant name="MATH_POSMOD" value="65" enum="BuiltinFunc"> + </constant> + <constant name="MATH_LERP_ANGLE" value="66" enum="BuiltinFunc"> </constant> - <constant name="COLORN" value="62" enum="BuiltinFunc"> - Return the [Color] with the given name and alpha ranging from 0 to 1. Note: names are defined in color_names.inc. + <constant name="TEXT_ORD" value="67" enum="BuiltinFunc"> </constant> - <constant name="FUNC_MAX" value="63" enum="BuiltinFunc"> - The maximum value the [member function] property can have. + <constant name="FUNC_MAX" value="68" enum="BuiltinFunc"> + Represents the size of the [enum BuiltinFunc] enum. </constant> </constants> </class> diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml index 2e3a5b33c0..49ea7850ef 100644 --- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Gets a constant from a given class. </brief_description> <description> - This node returns a constant from a given class, such as [@GlobalScope.TYPE_INT]. See the given class' documentation for available constants. + This node returns a constant from a given class, such as [constant TYPE_INT]. See the given class' documentation for available constants. [b]Input Ports:[/b] none [b]Output Ports:[/b] @@ -12,15 +12,13 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> The constant's parent class. </member> - <member name="constant" type="String" setter="set_class_constant" getter="get_class_constant"> + <member name="constant" type="String" setter="set_class_constant" getter="get_class_constant" default=""""> The constant to return. See the given class for its available constants. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml index a4a890ea8a..2538bc8356 100644 --- a/modules/visual_script/doc_classes/VisualScriptComment.xml +++ b/modules/visual_script/doc_classes/VisualScriptComment.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node used to annotate the script. </brief_description> @@ -9,18 +9,16 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="description" type="String" setter="set_description" getter="get_description"> + <member name="description" type="String" setter="set_description" getter="get_description" default=""""> The text inside the comment node. </member> - <member name="size" type="Vector2" setter="set_size" getter="get_size"> + <member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2( 150, 150 )"> The comment node's size (in pixels). </member> - <member name="title" type="String" setter="set_title" getter="get_title"> + <member name="title" type="String" setter="set_title" getter="get_title" default=""Comment""> The comment node's title. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptComposeArray.xml b/modules/visual_script/doc_classes/VisualScriptComposeArray.xml new file mode 100644 index 0000000000..92efbc51d1 --- /dev/null +++ b/modules/visual_script/doc_classes/VisualScriptComposeArray.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualScriptComposeArray" inherits="VisualScriptLists" category="Core" version="3.2"> + <brief_description> + A Visual Script Node used to create array from a list of items. + </brief_description> + <description> + A Visual Script Node used to compose array from the list of elements provided with custom in-graph UI hard coded in the VisualScript Editor. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml index 353898c93a..12d85429cf 100644 --- a/modules/visual_script/doc_classes/VisualScriptCondition.xml +++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node which branches the flow. </brief_description> <description> - A Visual Script node that checks a [bool] input port. If [code]true[/code] it will exit via the “true” sequence port. If [code]false[/code] it will exit via the "false" sequence port. After exiting either, it exits via the “done” port. Sequence ports may be left disconnected. + A Visual Script node that checks a [bool] input port. If [code]true[/code], it will exit via the "true" sequence port. If [code]false[/code], it will exit via the "false" sequence port. After exiting either, it exits via the "done" port. Sequence ports may be left disconnected. [b]Input Ports:[/b] - Sequence: [code]if (cond) is[/code] - Data (boolean): [code]cond[/code] @@ -15,8 +15,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml index ed633c4135..eb12fc3731 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Gets a contant's value. </brief_description> @@ -12,12 +12,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="type" type="int" setter="set_constant_type" getter="get_constant_type" enum="Variant.Type"> + <member name="type" type="int" setter="set_constant_type" getter="get_constant_type" enum="Variant.Type" default="0"> The constant's type. </member> <member name="value" type="Variant" setter="set_constant_value" getter="get_constant_value"> diff --git a/modules/visual_script/doc_classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml index 14c44c6970..8da5055d83 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstructor.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node which calls a base type constructor. </brief_description> @@ -8,8 +8,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="get_constructor" qualifiers="const"> <return type="Dictionary"> diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml index b8e77a1b0f..b079653591 100644 --- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A scripted Visual Script node. </brief_description> @@ -8,8 +8,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="_get_caption" qualifiers="virtual"> <return type="String"> @@ -47,7 +45,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Return the specified input port's type. See the TYPE_* enum in [@GlobalScope]. + Return the specified input port's type. See the [code]TYPE_*[/code] enum in [@GlobalScope]. </description> </method> <method name="_get_output_sequence_port_count" qualifiers="virtual"> @@ -88,7 +86,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Return the specified output's type. See the TYPE_* enum in [@GlobalScope]. + Return the specified output's type. See the [code]TYPE_*[/code] enum in [@GlobalScope]. </description> </method> <method name="_get_text" qualifiers="virtual"> @@ -125,13 +123,11 @@ </argument> <description> Execute the custom node's logic, returning the index of the output sequence port to use or a [String] when there is an error. - The [code]inputs[/code] array contains the values of the input ports. [code]outputs[/code] is an array whose indices should be set to the respective outputs. - The [code]start_mode[/code] is usually [code]START_MODE_BEGIN_SEQUENCE[/code], unless you have used the STEP_* constants. + The [code]start_mode[/code] is usually [constant START_MODE_BEGIN_SEQUENCE], unless you have used the [code]STEP_*[/code] constants. [code]working_mem[/code] is an array which can be used to persist information between runs of the custom node. - - When returning, you can mask the returned value with one of the STEP_* constants. + When returning, you can mask the returned value with one of the [code]STEP_*[/code] constants. </description> </method> </methods> @@ -147,7 +143,7 @@ </constant> <constant name="STEP_PUSH_STACK_BIT" value="16777216"> Hint used by [method _step] to tell that control should return to it when there is no other node left to execute. - This is used by [VisualScriptCondition] to redirect the sequence to the "Done" port after the true/false branch has finished execution. + This is used by [VisualScriptCondition] to redirect the sequence to the "Done" port after the [code]true[/code]/[code]false[/code] branch has finished execution. </constant> <constant name="STEP_GO_BACK_BIT" value="33554432"> Hint used by [method _step] to tell that control should return back, either hitting a previous STEP_PUSH_STACK_BIT or exiting the function. diff --git a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml index d3158df357..c8543287b4 100644 --- a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml +++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node which deconstructs a base type instance into its parts. </brief_description> @@ -8,12 +8,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="type" type="int" setter="set_deconstruct_type" getter="get_deconstruct_type" enum="Variant.Type"> + <member name="type" type="int" setter="set_deconstruct_type" getter="get_deconstruct_type" enum="Variant.Type" default="0"> The type to deconstruct. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml index fc49cfc07b..add2eb2275 100644 --- a/modules/visual_script/doc_classes/VisualScriptEditor.xml +++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.1"> +<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="add_custom_node"> <return type="void"> diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml index 4bb05525bd..1a567905a9 100644 --- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Emits a specified signal. </brief_description> @@ -12,12 +12,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="signal" type="String" setter="set_signal" getter="get_signal"> + <member name="signal" type="String" setter="set_signal" getter="get_signal" default=""""> The signal to emit. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml index 93d7ce3516..05bd87ec22 100644 --- a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml +++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> A Visual Script node returning a singleton from [@GlobalScope] </brief_description> @@ -8,12 +8,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="constant" type="String" setter="set_singleton" getter="get_singleton"> + <member name="constant" type="String" setter="set_singleton" getter="get_singleton" default=""""> The singleton's name. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml index 343e83cb55..eb6cdbb302 100644 --- a/modules/visual_script/doc_classes/VisualScriptExpression.xml +++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml index ec8e955cf7..152b48ca89 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunction.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml index f6116cf539..f7f86e8c80 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml @@ -1,35 +1,33 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> <member name="base_script" type="String" setter="set_base_script" getter="get_base_script"> </member> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> </member> <member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type"> </member> - <member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptFunctionCall.CallMode"> + <member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptFunctionCall.CallMode" default="0"> </member> - <member name="function" type="String" setter="set_function" getter="get_function"> + <member name="function" type="String" setter="set_function" getter="get_function" default=""""> </member> <member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path"> </member> - <member name="rpc_call_mode" type="int" setter="set_rpc_call_mode" getter="get_rpc_call_mode" enum="VisualScriptFunctionCall.RPCCallMode"> + <member name="rpc_call_mode" type="int" setter="set_rpc_call_mode" getter="get_rpc_call_mode" enum="VisualScriptFunctionCall.RPCCallMode" default="0"> </member> <member name="singleton" type="String" setter="set_singleton" getter="get_singleton"> </member> <member name="use_default_args" type="int" setter="set_use_default_args" getter="get_use_default_args"> </member> - <member name="validate" type="bool" setter="set_validate" getter="get_validate"> + <member name="validate" type="bool" setter="set_validate" getter="get_validate" default="true"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml index c75dd0cdbc..a8e820e6ea 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.1"> +<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="connect_to_signal"> <return type="void"> diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml index 9d43204f02..6c70dc7dc4 100644 --- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml @@ -1,17 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="constant" type="int" setter="set_global_constant" getter="get_global_constant"> + <member name="constant" type="int" setter="set_global_constant" getter="get_global_constant" default="0"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml index 73c1f47e1a..ba0dc1a3d0 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml index 652c29a9ac..09a8f2c8ad 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml index ab4c23012b..8c942813b2 100644 --- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml +++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml @@ -1,19 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="action" type="String" setter="set_action_name" getter="get_action_name"> + <member name="action" type="String" setter="set_action_name" getter="get_action_name" default=""""> </member> - <member name="mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="VisualScriptInputAction.Mode"> + <member name="mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="VisualScriptInputAction.Mode" default="0"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml index 7090621bd7..782bbfae20 100644 --- a/modules/visual_script/doc_classes/VisualScriptIterator.xml +++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Steps through items in a given input. </brief_description> @@ -15,8 +15,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptLists.xml b/modules/visual_script/doc_classes/VisualScriptLists.xml new file mode 100644 index 0000000000..8cf3eb1d38 --- /dev/null +++ b/modules/visual_script/doc_classes/VisualScriptLists.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualScriptLists" inherits="VisualScriptNode" category="Core" version="3.2"> + <brief_description> + 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. + </description> + <tutorials> + </tutorials> + <methods> + <method name="add_input_data_port"> + <return type="void"> + </return> + <argument index="0" name="type" type="int" enum="Variant.Type"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <argument index="2" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="add_output_data_port"> + <return type="void"> + </return> + <argument index="0" name="type" type="int" enum="Variant.Type"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <argument index="2" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="remove_input_data_port"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="remove_output_data_port"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_input_data_port_name"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_input_data_port_type"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="type" type="int" enum="Variant.Type"> + </argument> + <description> + </description> + </method> + <method name="set_output_data_port_name"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_output_data_port_type"> + <return type="void"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="type" type="int" enum="Variant.Type"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml index 5c8ee6453c..8c21c3f0bc 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Gets a local variable's value. </brief_description> @@ -12,15 +12,13 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type"> + <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type" default="0"> The local variable's type. </member> - <member name="var_name" type="String" setter="set_var_name" getter="get_var_name"> + <member name="var_name" type="String" setter="set_var_name" getter="get_var_name" default=""new_local""> The local variable's name. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml index f2e6c48907..a981432cdb 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Changes a local variable's value. </brief_description> @@ -14,15 +14,13 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type"> + <member name="type" type="int" setter="set_var_type" getter="get_var_type" enum="Variant.Type" default="0"> The local variable's type. </member> - <member name="var_name" type="String" setter="set_var_name" getter="get_var_name"> + <member name="var_name" type="String" setter="set_var_name" getter="get_var_name" default=""new_local""> The local variable's name. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml index d456e880b7..3be392aef5 100644 --- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Commonly used mathematical constants. </brief_description> @@ -12,12 +12,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="constant" type="int" setter="set_math_constant" getter="get_math_constant" enum="VisualScriptMathConstant.MathConstant"> + <member name="constant" type="int" setter="set_math_constant" getter="get_math_constant" enum="VisualScriptMathConstant.MathConstant" default="0"> The math constant. </member> </members> @@ -47,6 +45,7 @@ Not a number: [code]nan[/code] </constant> <constant name="MATH_CONSTANT_MAX" value="8" enum="MathConstant"> + Represents the size of the [enum MathConstant] enum. </constant> </constants> </class> diff --git a/modules/visual_script/doc_classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml index 941a0cd91a..89fb5c81f8 100644 --- a/modules/visual_script/doc_classes/VisualScriptNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.1"> +<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.2"> <brief_description> A node which is part of a [VisualScript]. </brief_description> @@ -8,8 +8,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="get_default_input_value" qualifiers="const"> <return type="Variant"> diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml index e60d50c977..80449ac521 100644 --- a/modules/visual_script/doc_classes/VisualScriptOperator.xml +++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> @@ -11,14 +11,12 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="operator" type="int" setter="set_operator" getter="get_operator" enum="Variant.Operator"> + <member name="operator" type="int" setter="set_operator" getter="get_operator" enum="Variant.Operator" default="6"> </member> - <member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type"> + <member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type" default="0"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml index 5a2886ccac..b3b39691c9 100644 --- a/modules/visual_script/doc_classes/VisualScriptPreload.xml +++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Creates a new [Resource] or loads one from the filesystem. </brief_description> @@ -12,8 +12,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml index 60cc8fdd4f..af1e8e68e8 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml @@ -1,19 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> <member name="base_script" type="String" setter="set_base_script" getter="get_base_script"> </member> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> </member> <member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type"> </member> @@ -21,9 +19,9 @@ </member> <member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path"> </member> - <member name="property" type="String" setter="set_property" getter="get_property"> + <member name="property" type="String" setter="set_property" getter="get_property" default=""""> </member> - <member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertyGet.CallMode"> + <member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertyGet.CallMode" default="0"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml index 8f29e9d152..380c196caf 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -1,21 +1,19 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="assign_op" type="int" setter="set_assign_op" getter="get_assign_op" enum="VisualScriptPropertySet.AssignOp"> + <member name="assign_op" type="int" setter="set_assign_op" getter="get_assign_op" enum="VisualScriptPropertySet.AssignOp" default="0"> </member> <member name="base_script" type="String" setter="set_base_script" getter="get_base_script"> </member> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> </member> <member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type"> </member> @@ -23,9 +21,9 @@ </member> <member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path"> </member> - <member name="property" type="String" setter="set_property" getter="get_property"> + <member name="property" type="String" setter="set_property" getter="get_property" default=""""> </member> - <member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertySet.CallMode"> + <member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertySet.CallMode" default="0"> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml index f6300e03f0..da37bbbb2c 100644 --- a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml +++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml @@ -1,17 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="path" type="String" setter="set_resource_path" getter="get_resource_path"> + <member name="path" type="String" setter="set_resource_path" getter="get_resource_path" default=""""> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml index 6095520eff..9a81c671d4 100644 --- a/modules/visual_script/doc_classes/VisualScriptReturn.xml +++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Exits a function and returns an optional value. </brief_description> @@ -13,15 +13,13 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="return_enabled" type="bool" setter="set_enable_return_value" getter="is_return_value_enabled"> - If [code]true[/code] the [code]return[/code] input port is available. + <member name="return_enabled" type="bool" setter="set_enable_return_value" getter="is_return_value_enabled" default="false"> + If [code]true[/code], the [code]return[/code] input port is available. </member> - <member name="return_type" type="int" setter="set_return_type" getter="get_return_type" enum="Variant.Type"> + <member name="return_type" type="int" setter="set_return_type" getter="get_return_type" enum="Variant.Type" default="0"> The return value's data type. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml index 7704eaba04..99f4acbd27 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Node reference. </brief_description> @@ -12,12 +12,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="node_path" type="NodePath" setter="set_node_path" getter="get_node_path"> + <member name="node_path" type="NodePath" setter="set_node_path" getter="get_node_path" default="NodePath(".")"> The node's path in the scene tree. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml index 2c2af9262d..84718ba119 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml index 0731fc77e1..e6a6cd5a48 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelect.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Chooses between two input values. </brief_description> @@ -14,12 +14,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type"> + <member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type" default="0"> The input variables' type. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml index 61a73e104c..231e7d8f0d 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelf.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Outputs a reference to the current instance. </brief_description> @@ -12,8 +12,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml index c71e068045..2ceceb199f 100644 --- a/modules/visual_script/doc_classes/VisualScriptSequence.xml +++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Executes a series of Sequence ports. </brief_description> @@ -14,12 +14,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="steps" type="int" setter="set_steps" getter="get_steps"> + <member name="steps" type="int" setter="set_steps" getter="get_steps" default="1"> The number of steps in the sequence. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml index 46aeebab9c..51b0093209 100644 --- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml @@ -1,13 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> <method name="_subcall" qualifiers="virtual"> <return type="Variant"> diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml index a00811a29b..3e3b88ebe0 100644 --- a/modules/visual_script/doc_classes/VisualScriptSwitch.xml +++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Branches program flow based on a given input's value. </brief_description> <description> - Branches the flow based on an input's value. Use "Case Count" in the Inspector to set the number of branches and each comparison's optional type. + Branches the flow based on an input's value. Use [b]Case Count[/b] in the Inspector to set the number of branches and each comparison's optional type. [b]Input Ports:[/b] - Sequence: [code]'input' is[/code] - Data (variant): [code]=[/code] @@ -17,8 +17,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml index 0bdc4ce89d..999a190a9a 100644 --- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml +++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml @@ -1,19 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="base_script" type="String" setter="set_base_script" getter="get_base_script"> + <member name="base_script" type="String" setter="set_base_script" getter="get_base_script" default=""""> </member> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> </member> </members> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml index 06178a399d..40e461294b 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Gets a variable's value. </brief_description> @@ -12,12 +12,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="var_name" type="String" setter="set_variable" getter="get_variable"> + <member name="var_name" type="String" setter="set_variable" getter="get_variable" default=""""> The variable's name. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml index 5969f25060..6c53ad61b4 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Changes a variable's value. </brief_description> @@ -13,12 +13,10 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="var_name" type="String" setter="set_variable" getter="get_variable"> + <member name="var_name" type="String" setter="set_variable" getter="get_variable" default=""""> The variable's name. </member> </members> diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml index b9e7f6a553..77211fa088 100644 --- a/modules/visual_script/doc_classes/VisualScriptWhile.xml +++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> Conditional loop. </brief_description> @@ -14,8 +14,6 @@ </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <constants> diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml index c4698f746a..c506e6db01 100644 --- a/modules/visual_script/doc_classes/VisualScriptYield.xml +++ b/modules/visual_script/doc_classes/VisualScriptYield.xml @@ -1,17 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="mode" type="int" setter="set_yield_mode" getter="get_yield_mode" enum="VisualScriptYield.YieldMode"> + <member name="mode" type="int" setter="set_yield_mode" getter="get_yield_mode" enum="VisualScriptYield.YieldMode" default="1"> </member> <member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time"> </member> diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml index b67e4ab1b8..b9d7aedaab 100644 --- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml @@ -1,23 +1,21 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1"> +<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.2"> <brief_description> </brief_description> <description> </description> <tutorials> </tutorials> - <demos> - </demos> <methods> </methods> <members> - <member name="base_type" type="String" setter="set_base_type" getter="get_base_type"> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""Object""> </member> - <member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptYieldSignal.CallMode"> + <member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptYieldSignal.CallMode" default="0"> </member> <member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path"> </member> - <member name="signal" type="String" setter="set_signal" getter="get_signal"> + <member name="signal" type="String" setter="set_signal" getter="get_signal" default=""""> </member> </members> <constants> diff --git a/modules/visual_script/icons/icon_visual_script.svg b/modules/visual_script/icons/icon_visual_script.svg new file mode 100644 index 0000000000..f6475d590e --- /dev/null +++ b/modules/visual_script/icons/icon_visual_script.svg @@ -0,0 +1,6 @@ +<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> diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 6e081817f1..49272345fe 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -56,6 +56,8 @@ void register_visual_script_types() { ClassDB::register_virtual_class<VisualScriptNode>(); ClassDB::register_class<VisualScriptFunctionState>(); ClassDB::register_class<VisualScriptFunction>(); + ClassDB::register_virtual_class<VisualScriptLists>(); + ClassDB::register_class<VisualScriptComposeArray>(); ClassDB::register_class<VisualScriptOperator>(); ClassDB::register_class<VisualScriptVariableSet>(); ClassDB::register_class<VisualScriptVariableGet>(); diff --git a/modules/visual_script/register_types.h b/modules/visual_script/register_types.h index 27b3bd649a..05b3164b3c 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 ff97c21fd9..0cacd0f0b5 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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,6 +30,7 @@ #include "visual_script.h" +#include "core/core_string_names.h" #include "core/os/os.h" #include "core/project_settings.h" #include "scene/main/node.h" @@ -45,23 +46,7 @@ bool VisualScriptNode::is_breakpoint() const { return breakpoint; } -void VisualScriptNode::_notification(int p_what) { - - if (p_what == NOTIFICATION_POSTINITIALIZE) { - - int dvc = get_input_value_port_count(); - for (int i = 0; i < dvc; i++) { - Variant::Type expected = get_input_value_port_info(i).type; - Variant::CallError ce; - default_input_values.push_back(Variant::construct(expected, NULL, 0, ce, false)); - } - } -} - void VisualScriptNode::ports_changed_notify() { - - 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 - emit_signal("ports_changed"); } @@ -90,8 +75,7 @@ void VisualScriptNode::_set_default_input_values(Array p_values) { } void VisualScriptNode::validate_input_default_values() { - - default_input_values.resize(get_input_value_port_count()); + 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 for (int i = 0; i < get_input_value_port_count(); i++) { @@ -117,8 +101,10 @@ void VisualScriptNode::validate_input_default_values() { Array VisualScriptNode::_get_default_input_values() const { //validate on save, since on load there is little info about this + Array values = default_input_values; + values.resize(get_input_value_port_count()); - return default_input_values; + return values; } String VisualScriptNode::get_text() const { @@ -279,11 +265,7 @@ void VisualScript::_node_ports_changed(int p_id) { Function &func = functions[function]; Ref<VisualScriptNode> vsn = func.nodes[p_id].node; - if (OS::get_singleton()->get_main_loop() && - Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()) && - Engine::get_singleton()->is_editor_hint()) { - vsn->validate_input_default_values(); //force validate default values when editing on editor - } + vsn->validate_input_default_values(); //must revalidate all the functions @@ -346,8 +328,7 @@ void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<Visual if (Object::cast_to<VisualScriptFunction>(*p_node)) { //the function indeed - ERR_EXPLAIN("A function node already has been set here."); - ERR_FAIL_COND(func.function_id >= 0); + ERR_FAIL_COND_MSG(func.function_id >= 0, "A function node has already been set here."); func.function_id = p_id; } @@ -359,6 +340,7 @@ void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<Visual Ref<VisualScriptNode> vsn = p_node; vsn->connect("ports_changed", this, "_node_ports_changed", varray(p_id)); vsn->scripts_used.insert(this); + vsn->validate_input_default_values(); // Validate when fully loaded func.nodes[p_id] = nd; } @@ -596,6 +578,10 @@ void VisualScript::get_data_connection_list(const StringName &p_func, List<DataC } } +void VisualScript::set_tool_enabled(bool p_enabled) { + is_tool_script = p_enabled; +} + void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) { ERR_FAIL_COND(instances.size()); @@ -912,7 +898,7 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { #ifdef TOOLS_ENABLED - if (!ScriptServer::is_scripting_enabled()) { + if (!ScriptServer::is_scripting_enabled() && !is_tool_script) { PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this)); placeholders.insert(sins); @@ -976,7 +962,11 @@ Error VisualScript::reload(bool p_keep_state) { bool VisualScript::is_tool() const { - return false; + return is_tool_script; +} + +bool VisualScript::is_valid() const { + return true; //always valid } ScriptLanguage *VisualScript::get_language() const { @@ -1024,17 +1014,16 @@ void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node; if (func.is_valid()) { - for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arg; arg.name = func->get_argument_name(i); arg.type = func->get_argument_type(i); mi.arguments.push_back(arg); } + + p_list->push_back(mi); } } - - p_list->push_back(mi); } } @@ -1147,6 +1136,9 @@ 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]; @@ -1159,11 +1151,42 @@ void VisualScript::_set_data(const Dictionary &p_data) { Array nodes = func["nodes"]; - for (int i = 0; i < nodes.size(); i += 3) { + if (!d.has("vs_unify") && nodes.size() > 0) { + Vector2 top_left = nodes[1]; + Vector2 bottom_right = nodes[1]; - add_node(name, nodes[i], nodes[i + 2], nodes[i + 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]); + } + } Array sequence_connections = func["sequence_connections"]; for (int j = 0; j < sequence_connections.size(); j += 3) { @@ -1178,6 +1201,11 @@ void VisualScript::_set_data(const Dictionary &p_data) { data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]); } } + + if (d.has("is_tool_script")) + is_tool_script = d["is_tool_script"]; + else + is_tool_script = false; } Dictionary VisualScript::_get_data() const { @@ -1259,6 +1287,8 @@ Dictionary VisualScript::_get_data() const { } d["functions"] = funcs; + d["is_tool_script"] = is_tool_script; + d["vs_unify"] = true; return d; } @@ -1333,6 +1363,10 @@ VisualScript::VisualScript() { base_type = "Object"; } +StringName VisualScript::get_default_func() const { + return StringName("f_312843592"); +} + Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_func, int from_node) { List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>); get_sequence_connection_list(edited_func, sc); @@ -1406,6 +1440,10 @@ 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; + } + MethodInfo mi; mi.name = E->key(); if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) { @@ -1424,8 +1462,6 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { if (!vsf->is_sequenced()) { //assumed constant if not sequenced mi.flags |= METHOD_FLAG_CONST; } - - //vsf->Get_ for now at least it does not return.. } } @@ -1434,6 +1470,9 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { } bool VisualScriptInstance::has_method(const StringName &p_method) const { + if (p_method == script->get_default_func()) + return false; + return script->functions.has(p_method); } @@ -1500,7 +1539,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p Variant **output_args = (Variant **)(input_args + max_input_args); int flow_max = f->flow_stack_size; int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL; - int *pass_stack = flow_stack + flow_max; + int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL; String error_str; @@ -1705,7 +1744,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p 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 (output < 0 || output >= node->sequence_output_count) { + if (output >= node->sequence_output_count) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("Node returned an invalid sequence output: ") + itos(output); error = true; @@ -1918,7 +1957,7 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p Variant **output_args = (Variant **)(input_args + max_input_args); int flow_max = f->flow_stack_size; int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL; - int *pass_stack = flow_stack + flow_max; + int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL; for (int i = 0; i < f->node_count; i++) { sequence_bits[i] = false; //all starts as false @@ -1930,8 +1969,7 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p if (!E) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; - ERR_EXPLAIN("No VisualScriptFunction node in function!"); - ERR_FAIL_V(Variant()); + ERR_FAIL_V_MSG(Variant(), "No VisualScriptFunction node in function."); } VisualScriptNodeInstance *node = E->get(); @@ -1979,6 +2017,26 @@ void VisualScriptInstance::notification(int p_notification) { call(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); //do as call } +String VisualScriptInstance::to_string(bool *r_valid) { + if (has_method(CoreStringNames::get_singleton()->_to_string)) { + Variant::CallError ce; + Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce); + if (ce.error == Variant::CallError::CALL_OK) { + if (ret.get_type() != Variant::STRING) { + if (r_valid) + *r_valid = false; + ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); + } + if (r_valid) + *r_valid = true; + return ret.operator String(); + } + } + if (r_valid) + *r_valid = false; + return String(); +} + Ref<Script> VisualScriptInstance::get_script() const { return script; @@ -1986,6 +2044,9 @@ Ref<Script> VisualScriptInstance::get_script() const { MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const { + if (p_method == script->get_default_func()) + return MultiplayerAPI::RPC_MODE_DISABLED; + const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method); if (!E) { return MultiplayerAPI::RPC_MODE_DISABLED; @@ -2034,11 +2095,14 @@ 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; - //no hacer que todo exporte, solo las que queres! } 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; @@ -2075,6 +2139,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o 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); @@ -2254,15 +2319,10 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int ERR_FAIL_COND_V(function == StringName(), Variant()); #ifdef DEBUG_ENABLED - if (instance_id && !ObjectDB::get_instance(instance_id)) { - ERR_EXPLAIN("Resumed after yield, but class instance is gone"); - ERR_FAIL_V(Variant()); - } - if (script_id && !ObjectDB::get_instance(script_id)) { - ERR_EXPLAIN("Resumed after yield, but script is gone"); - ERR_FAIL_V(Variant()); - } + ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); + ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); + #endif r_error.error = Variant::CallError::CALL_OK; @@ -2321,15 +2381,10 @@ Variant VisualScriptFunctionState::resume(Array p_args) { ERR_FAIL_COND_V(function == StringName(), Variant()); #ifdef DEBUG_ENABLED - if (instance_id && !ObjectDB::get_instance(instance_id)) { - ERR_EXPLAIN("Resumed after yield, but class instance is gone"); - ERR_FAIL_V(Variant()); - } - if (script_id && !ObjectDB::get_instance(script_id)) { - ERR_EXPLAIN("Resumed after yield, but script is gone"); - ERR_FAIL_V(Variant()); - } + ERR_FAIL_COND_V_MSG(instance_id && !ObjectDB::get_instance(instance_id), Variant(), "Resumed after yield, but class instance is gone."); + ERR_FAIL_COND_V_MSG(script_id && !ObjectDB::get_instance(script_id), Variant(), "Resumed after yield, but script is gone."); + #endif Variant::CallError r_error; @@ -2455,7 +2510,7 @@ bool VisualScriptLanguage::debug_break_parse(const String &p_file, int p_node, c _debug_parse_err_node = p_node; _debug_parse_err_file = p_file; _debug_error = p_error; - ScriptDebugger::get_singleton()->debug(this, false); + ScriptDebugger::get_singleton()->debug(this, false, true); return true; } else { return false; @@ -2469,7 +2524,7 @@ bool VisualScriptLanguage::debug_break(const String &p_error, bool p_allow_conti _debug_parse_err_node = -1; _debug_parse_err_file = ""; _debug_error = p_error; - ScriptDebugger::get_singleton()->debug(this, p_allow_continue); + ScriptDebugger::get_singleton()->debug(this, p_allow_continue, true); return true; } else { return false; @@ -2621,8 +2676,6 @@ void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Varian } String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { - if (_debug_parse_err_node >= 0) - return ""; return ""; } @@ -2697,11 +2750,11 @@ VisualScriptLanguage::VisualScriptLanguage() { _debug_parse_err_file = ""; _debug_call_stack_pos = 0; int dmcs = GLOBAL_DEF("debug/settings/visual_script/max_call_stack", 1024); + 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 (ScriptDebugger::get_singleton()) { //debugging enabled! _debug_max_call_stack = dmcs; - if (_debug_max_call_stack < 1024) - _debug_max_call_stack = 1024; _call_stack = memnew_arr(CallLevel, _debug_max_call_stack + 1); } else { diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index ea99ce4970..a035f6d42d 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -39,7 +39,7 @@ class VisualScriptNodeInstance; class VisualScript; class VisualScriptNode : public Resource { - GDCLASS(VisualScriptNode, Resource) + GDCLASS(VisualScriptNode, Resource); friend class VisualScript; @@ -54,7 +54,6 @@ class VisualScriptNode : public Resource { void validate_input_default_values(); protected: - void _notification(int p_what); void ports_changed_notify(); static void _bind_methods(); @@ -166,7 +165,7 @@ public: class VisualScript : public Script { - GDCLASS(VisualScript, Script) + GDCLASS(VisualScript, Script); RES_BASE_EXTENSION("vs"); @@ -240,6 +239,7 @@ private: PropertyInfo info; Variant default_value; bool _export; + // add getter & setter options here }; Map<StringName, Function> functions; @@ -248,6 +248,8 @@ private: Map<Object *, VisualScriptInstance *> instances; + bool is_tool_script; + #ifdef TOOLS_ENABLED Set<PlaceHolderScriptInstance *> placeholders; //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); @@ -266,6 +268,8 @@ protected: static void _bind_methods(); public: + // TODO: Remove it in future when breaking changes are acceptable + StringName get_default_func() const; void add_function(const StringName &p_name); bool has_function(const StringName &p_name) const; void remove_function(const StringName &p_name); @@ -274,6 +278,7 @@ public: 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); @@ -340,6 +345,7 @@ public: virtual Error reload(bool p_keep_state = false); virtual bool is_tool() const; + virtual bool is_valid() const; virtual ScriptLanguage *get_language() const; @@ -404,6 +410,7 @@ public: virtual bool has_method(const StringName &p_method) const; virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); virtual void notification(int p_notification); + String to_string(bool *r_valid); bool set_variable(const StringName &p_variable, const Variant &p_value) { diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 60bc54afe4..3fdceacebb 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -68,6 +68,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "lerp", "inverse_lerp", "range_lerp", + "move_toward", "dectime", "randomize", "randi", @@ -102,6 +103,10 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "var2bytes", "bytes2var", "color_named", + "smoothstep", + "posmod", + "lerp_angle", + "ord", }; VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String &p_string) { @@ -177,19 +182,21 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { case OBJ_WEAKREF: case TYPE_OF: case TEXT_CHAR: + case TEXT_ORD: case TEXT_STR: case TEXT_PRINT: case TEXT_PRINTERR: case TEXT_PRINTRAW: case VAR_TO_STR: case STR_TO_VAR: - case VAR_TO_BYTES: - case BYTES_TO_VAR: case TYPE_EXISTS: return 1; + case VAR_TO_BYTES: + case BYTES_TO_VAR: case MATH_ATAN2: case MATH_FMOD: case MATH_FPOSMOD: + case MATH_POSMOD: case MATH_POW: case MATH_EASE: case MATH_STEPIFY: @@ -203,7 +210,10 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { case COLORN: return 2; case MATH_LERP: + case MATH_LERP_ANGLE: case MATH_INVERSE_LERP: + case MATH_SMOOTHSTEP: + case MATH_MOVE_TOWARD: case MATH_DECTIME: case MATH_WRAP: case MATH_WRAPF: @@ -257,7 +267,16 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case MATH_ASIN: case MATH_ACOS: case MATH_ATAN: - case MATH_SQRT: { + case MATH_SQRT: + case MATH_FLOOR: + case MATH_CEIL: + case MATH_ROUND: + case MATH_ABS: + case MATH_SIGN: + case MATH_LOG: + case MATH_EXP: + case MATH_ISNAN: + case MATH_ISINF: { return PropertyInfo(Variant::REAL, "s"); } break; case MATH_ATAN2: { @@ -267,32 +286,25 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::REAL, "x"); } break; case MATH_FMOD: - case MATH_FPOSMOD: { + case MATH_FPOSMOD: + case LOGIC_MAX: + case LOGIC_MIN: { if (p_idx == 0) - return PropertyInfo(Variant::REAL, "x"); + return PropertyInfo(Variant::REAL, "a"); else - return PropertyInfo(Variant::REAL, "y"); + return PropertyInfo(Variant::REAL, "b"); } break; - case MATH_FLOOR: - case MATH_CEIL: - case MATH_ROUND: - case MATH_ABS: - case MATH_SIGN: { - return PropertyInfo(Variant::REAL, "s"); - + case MATH_POSMOD: { + if (p_idx == 0) + return PropertyInfo(Variant::INT, "a"); + else + return PropertyInfo(Variant::INT, "b"); } break; - case MATH_POW: { if (p_idx == 0) - return PropertyInfo(Variant::REAL, "x"); + return PropertyInfo(Variant::REAL, "base"); else - return PropertyInfo(Variant::REAL, "y"); - } break; - case MATH_LOG: - case MATH_EXP: - case MATH_ISNAN: - case MATH_ISINF: { - return PropertyInfo(Variant::REAL, "s"); + return PropertyInfo(Variant::REAL, "exp"); } break; case MATH_EASE: { if (p_idx == 0) @@ -309,15 +321,10 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const else return PropertyInfo(Variant::REAL, "steps"); } break; - case MATH_LERP: { - if (p_idx == 0) - return PropertyInfo(Variant::REAL, "from"); - else if (p_idx == 1) - return PropertyInfo(Variant::REAL, "to"); - else - return PropertyInfo(Variant::REAL, "weight"); - } break; - case MATH_INVERSE_LERP: { + case MATH_LERP: + case MATH_LERP_ANGLE: + case MATH_INVERSE_LERP: + case MATH_SMOOTHSTEP: { if (p_idx == 0) return PropertyInfo(Variant::REAL, "from"); else if (p_idx == 1) @@ -337,6 +344,14 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const else return PropertyInfo(Variant::REAL, "ostop"); } break; + case MATH_MOVE_TOWARD: { + if (p_idx == 0) + return PropertyInfo(Variant::REAL, "from"); + else if (p_idx == 1) + return PropertyInfo(Variant::REAL, "to"); + else + return PropertyInfo(Variant::REAL, "delta"); + } break; case MATH_DECTIME: { if (p_idx == 0) return PropertyInfo(Variant::REAL, "value"); @@ -345,12 +360,8 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const else return PropertyInfo(Variant::REAL, "step"); } break; - case MATH_RANDOMIZE: { - - } break; - case MATH_RAND: { - - } break; + case MATH_RANDOMIZE: + case MATH_RAND: case MATH_RANDF: { } break; @@ -360,9 +371,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const else return PropertyInfo(Variant::REAL, "to"); } break; - case MATH_SEED: { - return PropertyInfo(Variant::INT, "seed"); - } break; + case MATH_SEED: case MATH_RANDSEED: { return PropertyInfo(Variant::INT, "seed"); } break; @@ -398,26 +407,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const else return PropertyInfo(Variant::INT, "max"); } break; - case MATH_WRAPF: { - if (p_idx == 0) - return PropertyInfo(Variant::REAL, "value"); - else if (p_idx == 1) - return PropertyInfo(Variant::REAL, "min"); - else - return PropertyInfo(Variant::REAL, "max"); - } break; - case LOGIC_MAX: { - if (p_idx == 0) - return PropertyInfo(Variant::REAL, "a"); - else - return PropertyInfo(Variant::REAL, "b"); - } break; - case LOGIC_MIN: { - if (p_idx == 0) - return PropertyInfo(Variant::REAL, "a"); - else - return PropertyInfo(Variant::REAL, "b"); - } break; + case MATH_WRAPF: case LOGIC_CLAMP: { if (p_idx == 0) return PropertyInfo(Variant::REAL, "value"); @@ -430,20 +420,15 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::INT, "value"); } break; 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"); else @@ -451,60 +436,46 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const } break; case TYPE_OF: { return PropertyInfo(Variant::NIL, "what"); - } break; case TYPE_EXISTS: { - return PropertyInfo(Variant::STRING, "type"); - + } break; + case TEXT_ORD: { + return PropertyInfo(Variant::STRING, "character"); } break; case TEXT_CHAR: { - return PropertyInfo(Variant::INT, "ascii"); - - } break; - case TEXT_STR: { - - return PropertyInfo(Variant::NIL, "value"); - - } break; - case TEXT_PRINT: { - - return PropertyInfo(Variant::NIL, "value"); - - } break; - case TEXT_PRINTERR: { - return PropertyInfo(Variant::NIL, "value"); - } break; + case TEXT_STR: + case TEXT_PRINT: + case TEXT_PRINTERR: case TEXT_PRINTRAW: { - return PropertyInfo(Variant::NIL, "value"); - - } break; - case VAR_TO_STR: { - return PropertyInfo(Variant::NIL, "var"); - } break; case STR_TO_VAR: { return PropertyInfo(Variant::STRING, "string"); } break; + case VAR_TO_STR: case VAR_TO_BYTES: { - return PropertyInfo(Variant::NIL, "var"); + if (p_idx == 0) + return PropertyInfo(Variant::NIL, "var"); + else + return PropertyInfo(Variant::BOOL, "full_objects"); } break; case BYTES_TO_VAR: { - return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"); + if (p_idx == 0) + return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"); + else + return PropertyInfo(Variant::BOOL, "allow_objects"); } break; case COLORN: { - if (p_idx == 0) return PropertyInfo(Variant::STRING, "name"); else return PropertyInfo(Variant::REAL, "alpha"); - } break; case FUNC_MAX: { } @@ -535,6 +506,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case MATH_CEIL: { t = Variant::REAL; } break; + case MATH_POSMOD: case MATH_ROUND: { t = Variant::INT; } break; @@ -561,8 +533,11 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case MATH_STEPIFY: case MATH_LERP: + case MATH_LERP_ANGLE: case MATH_INVERSE_LERP: case MATH_RANGE_LERP: + case MATH_SMOOTHSTEP: + case MATH_MOVE_TOWARD: case MATH_DECTIME: { t = Variant::REAL; @@ -624,6 +599,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case TYPE_CONVERT: { } break; + case TEXT_ORD: case TYPE_OF: { t = Variant::INT; @@ -655,11 +631,15 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case VAR_TO_BYTES: { - t = Variant::POOL_BYTE_ARRAY; + if (p_idx == 0) + t = Variant::POOL_BYTE_ARRAY; + else + t = Variant::BOOL; } break; case BYTES_TO_VAR: { - + if (p_idx == 1) + t = Variant::BOOL; } break; case COLORN: { t = Variant::COLOR; @@ -774,6 +754,12 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(1); *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; + case VisualScriptBuiltinFunc::MATH_POSMOD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); + } break; case VisualScriptBuiltinFunc::MATH_FLOOR: { VALIDATE_ARG_NUM(0); @@ -873,6 +859,13 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(2); *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; + case VisualScriptBuiltinFunc::MATH_LERP_ANGLE: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; case VisualScriptBuiltinFunc::MATH_INVERSE_LERP: { VALIDATE_ARG_NUM(0); @@ -889,6 +882,19 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(4); *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); } break; + case VisualScriptBuiltinFunc::MATH_SMOOTHSTEP: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_MOVE_TOWARD: { + + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); + } break; case VisualScriptBuiltinFunc::MATH_DECTIME: { VALIDATE_ARG_NUM(0); @@ -1132,6 +1138,30 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = String(result); } break; + case VisualScriptBuiltinFunc::TEXT_ORD: { + + if (p_inputs[0]->get_type() != Variant::STRING) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::STRING; + + return; + } + + String str = p_inputs[0]->operator String(); + + if (str.length() != 1) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::STRING; + *r_return = "Expected a string of length 1 (a character)."; + + return; + } + + *r_return = str.get(0); + + } break; case VisualScriptBuiltinFunc::TEXT_STR: { String str = *p_inputs[0]; @@ -1192,9 +1222,16 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::VAR_TO_BYTES: { + if (p_inputs[1]->get_type() != Variant::BOOL) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = Variant::BOOL; + return; + } PoolByteArray barr; int len; - Error err = encode_variant(*p_inputs[0], NULL, len); + bool full_objects = *p_inputs[1]; + Error err = encode_variant(*p_inputs[0], NULL, len, full_objects); if (err) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1206,7 +1243,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in barr.resize(len); { PoolByteArray::Write w = barr.write(); - encode_variant(*p_inputs[0], w.ptr(), len); + encode_variant(*p_inputs[0], w.ptr(), len, full_objects); } *r_return = barr; } break; @@ -1216,15 +1253,21 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::POOL_BYTE_ARRAY; - + return; + } + if (p_inputs[1]->get_type() != Variant::BOOL) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = Variant::BOOL; return; } PoolByteArray varr = *p_inputs[0]; + bool allow_objects = *p_inputs[1]; Variant ret; { PoolByteArray::Read r = varr.read(); - Error err = decode_variant(ret, r.ptr(), varr.size(), NULL); + Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects); if (err != OK) { r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -1247,7 +1290,8 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = String(color); } break; - default: {} + default: { + } } } @@ -1322,6 +1366,7 @@ void VisualScriptBuiltinFunc::_bind_methods() { 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); @@ -1356,6 +1401,10 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(VAR_TO_BYTES); BIND_ENUM_CONSTANT(BYTES_TO_VAR); BIND_ENUM_CONSTANT(COLORN); + BIND_ENUM_CONSTANT(MATH_SMOOTHSTEP); + BIND_ENUM_CONSTANT(MATH_POSMOD); + BIND_ENUM_CONSTANT(MATH_LERP_ANGLE); + BIND_ENUM_CONSTANT(TEXT_ORD); BIND_ENUM_CONSTANT(FUNC_MAX); } @@ -1393,6 +1442,7 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/sqrt", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SQRT>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/fmod", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FMOD>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/fposmod", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FPOSMOD>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/posmod", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POSMOD>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/floor", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_FLOOR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/ceil", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CEIL>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/round", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_ROUND>); @@ -1408,8 +1458,11 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/decimals", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_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/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>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/range_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANGE_LERP>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/smoothstep", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SMOOTHSTEP>); + 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>); @@ -1438,6 +1491,7 @@ void register_visual_script_builtin_func_node() { 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>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/char", create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_CHAR>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/ord", create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_ORD>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/str", create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/print", create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/printerr", create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index 3345762b9f..998a6cbc6a 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -35,7 +35,8 @@ class VisualScriptBuiltinFunc : public VisualScriptNode { - GDCLASS(VisualScriptBuiltinFunc, VisualScriptNode) + GDCLASS(VisualScriptBuiltinFunc, VisualScriptNode); + public: enum BuiltinFunc { MATH_SIN, @@ -67,6 +68,7 @@ public: MATH_LERP, MATH_INVERSE_LERP, MATH_RANGE_LERP, + MATH_MOVE_TOWARD, MATH_DECTIME, MATH_RANDOMIZE, MATH_RAND, @@ -101,6 +103,10 @@ public: VAR_TO_BYTES, BYTES_TO_VAR, COLORN, + MATH_SMOOTHSTEP, + MATH_POSMOD, + MATH_LERP_ANGLE, + TEXT_ORD, FUNC_MAX }; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 1027c74f34..093901ad07 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -37,6 +37,7 @@ #include "core/variant.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" +#include "scene/main/viewport.h" #include "visual_script_expression.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" @@ -45,7 +46,7 @@ #ifdef TOOLS_ENABLED class VisualScriptEditorSignalEdit : public Object { - GDCLASS(VisualScriptEditorSignalEdit, Object) + GDCLASS(VisualScriptEditorSignalEdit, Object); StringName sig; @@ -185,7 +186,7 @@ public: class VisualScriptEditorVariableEdit : public Object { - GDCLASS(VisualScriptEditorVariableEdit, Object) + GDCLASS(VisualScriptEditorVariableEdit, Object); StringName var; @@ -340,74 +341,74 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { Color color; if (dark_theme) switch (p_type) { - case Variant::NIL: color = Color::html("#69ecbd"); break; - - case Variant::BOOL: color = Color::html("#8da6f0"); break; - case Variant::INT: color = Color::html("#7dc6ef"); break; - case Variant::REAL: color = Color::html("#61daf4"); break; - case Variant::STRING: color = Color::html("#6ba7ec"); break; - - case Variant::VECTOR2: color = Color::html("#bd91f1"); break; - case Variant::RECT2: color = Color::html("#f191a5"); break; - case Variant::VECTOR3: color = Color::html("#d67dee"); break; - case Variant::TRANSFORM2D: color = Color::html("#c4ec69"); break; - case Variant::PLANE: color = Color::html("#f77070"); break; - case Variant::QUAT: color = Color::html("#ec69a3"); break; - case Variant::AABB: color = Color::html("#ee7991"); break; - case Variant::BASIS: color = Color::html("#e3ec69"); break; - case Variant::TRANSFORM: color = Color::html("#f6a86e"); break; - - case Variant::COLOR: color = Color::html("#9dff70"); break; - case Variant::NODE_PATH: color = Color::html("#6993ec"); break; - case Variant::_RID: color = Color::html("#69ec9a"); break; - case Variant::OBJECT: color = Color::html("#79f3e8"); break; - case Variant::DICTIONARY: color = Color::html("#77edb1"); break; - - case Variant::ARRAY: color = Color::html("#e0e0e0"); break; - case Variant::POOL_BYTE_ARRAY: color = Color::html("#aaf4c8"); break; - case Variant::POOL_INT_ARRAY: color = Color::html("#afdcf5"); break; - case Variant::POOL_REAL_ARRAY: color = Color::html("#97e7f8"); break; - case Variant::POOL_STRING_ARRAY: color = Color::html("#9dc4f2"); break; - case Variant::POOL_VECTOR2_ARRAY: color = Color::html("#d1b3f5"); break; - case Variant::POOL_VECTOR3_ARRAY: color = Color::html("#df9bf2"); break; - case Variant::POOL_COLOR_ARRAY: color = Color::html("#e9ff97"); break; + case Variant::NIL: color = Color(0.41, 0.93, 0.74); break; + + case Variant::BOOL: color = Color(0.55, 0.65, 0.94); break; + case Variant::INT: color = Color(0.49, 0.78, 0.94); break; + case Variant::REAL: color = Color(0.38, 0.85, 0.96); break; + case Variant::STRING: color = Color(0.42, 0.65, 0.93); break; + + case Variant::VECTOR2: color = Color(0.74, 0.57, 0.95); break; + case Variant::RECT2: color = Color(0.95, 0.57, 0.65); break; + case Variant::VECTOR3: color = Color(0.84, 0.49, 0.93); break; + case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break; + case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break; + case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break; + case Variant::AABB: color = Color(0.93, 0.47, 0.57); break; + case Variant::BASIS: color = Color(0.89, 0.93, 0.41); break; + case Variant::TRANSFORM: color = Color(0.96, 0.66, 0.43); break; + + case Variant::COLOR: color = Color(0.62, 1.0, 0.44); break; + case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; + case Variant::_RID: color = Color(0.41, 0.93, 0.6); break; + case Variant::OBJECT: color = Color(0.47, 0.95, 0.91); break; + case Variant::DICTIONARY: color = Color(0.47, 0.93, 0.69); break; + + case Variant::ARRAY: color = Color(0.88, 0.88, 0.88); break; + case Variant::POOL_BYTE_ARRAY: color = Color(0.67, 0.96, 0.78); break; + case Variant::POOL_INT_ARRAY: color = Color(0.69, 0.86, 0.96); break; + case Variant::POOL_REAL_ARRAY: color = Color(0.59, 0.91, 0.97); break; + case Variant::POOL_STRING_ARRAY: color = Color(0.62, 0.77, 0.95); break; + case Variant::POOL_VECTOR2_ARRAY: color = Color(0.82, 0.7, 0.96); break; + case Variant::POOL_VECTOR3_ARRAY: color = Color(0.87, 0.61, 0.95); break; + case Variant::POOL_COLOR_ARRAY: color = Color(0.91, 1.0, 0.59); break; default: color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.7, 0.7); } else switch (p_type) { - case Variant::NIL: color = Color::html("#25e3a0"); break; - - case Variant::BOOL: color = Color::html("#6d8eeb"); break; - case Variant::INT: color = Color::html("#4fb2e9"); break; - case Variant::REAL: color = Color::html("#27ccf0"); break; - case Variant::STRING: color = Color::html("#4690e7"); break; - - case Variant::VECTOR2: color = Color::html("#ad76ee"); break; - case Variant::RECT2: color = Color::html("#ee758e"); break; - case Variant::VECTOR3: color = Color::html("#dc6aed"); break; - case Variant::TRANSFORM2D: color = Color::html("#96ce1a"); break; - case Variant::PLANE: color = Color::html("#f77070"); break; - case Variant::QUAT: color = Color::html("#ec69a3"); break; - case Variant::AABB: color = Color::html("#ee7991"); break; - case Variant::BASIS: color = Color::html("#b2bb19"); break; - case Variant::TRANSFORM: color = Color::html("#f49047"); break; - - case Variant::COLOR: color = Color::html("#3cbf00"); break; - case Variant::NODE_PATH: color = Color::html("#6993ec"); break; - case Variant::_RID: color = Color::html("#2ce573"); break; - case Variant::OBJECT: color = Color::html("#12d5c3"); break; - case Variant::DICTIONARY: color = Color::html("#57e99f"); break; - - case Variant::ARRAY: color = Color::html("#737373"); break; - case Variant::POOL_BYTE_ARRAY: color = Color::html("#61ea98"); break; - case Variant::POOL_INT_ARRAY: color = Color::html("#61baeb"); break; - case Variant::POOL_REAL_ARRAY: color = Color::html("#40d3f2"); break; - case Variant::POOL_STRING_ARRAY: color = Color::html("#609fea"); break; - case Variant::POOL_VECTOR2_ARRAY: color = Color::html("#9d5dea"); break; - case Variant::POOL_VECTOR3_ARRAY: color = Color::html("#ca5aea"); break; - case Variant::POOL_COLOR_ARRAY: color = Color::html("#92ba00"); break; + case Variant::NIL: color = Color(0.15, 0.89, 0.63); break; + + case Variant::BOOL: color = Color(0.43, 0.56, 0.92); break; + case Variant::INT: color = Color(0.31, 0.7, 0.91); break; + case Variant::REAL: color = Color(0.15, 0.8, 0.94); break; + case Variant::STRING: color = Color(0.27, 0.56, 0.91); break; + + case Variant::VECTOR2: color = Color(0.68, 0.46, 0.93); break; + case Variant::RECT2: color = Color(0.93, 0.46, 0.56); break; + case Variant::VECTOR3: color = Color(0.86, 0.42, 0.93); break; + case Variant::TRANSFORM2D: color = Color(0.59, 0.81, 0.1); break; + case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break; + case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break; + case Variant::AABB: color = Color(0.93, 0.47, 0.57); break; + case Variant::BASIS: color = Color(0.7, 0.73, 0.1); break; + case Variant::TRANSFORM: color = Color(0.96, 0.56, 0.28); break; + + case Variant::COLOR: color = Color(0.24, 0.75, 0.0); break; + case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; + case Variant::_RID: color = Color(0.17, 0.9, 0.45); break; + case Variant::OBJECT: color = Color(0.07, 0.84, 0.76); break; + case Variant::DICTIONARY: color = Color(0.34, 0.91, 0.62); break; + + case Variant::ARRAY: color = Color(0.45, 0.45, 0.45); break; + case Variant::POOL_BYTE_ARRAY: color = Color(0.38, 0.92, 0.6); break; + case Variant::POOL_INT_ARRAY: color = Color(0.38, 0.73, 0.92); break; + case Variant::POOL_REAL_ARRAY: color = Color(0.25, 0.83, 0.95); break; + case Variant::POOL_STRING_ARRAY: color = Color(0.38, 0.62, 0.92); break; + case Variant::POOL_VECTOR2_ARRAY: color = Color(0.62, 0.36, 0.92); break; + case Variant::POOL_VECTOR3_ARRAY: color = Color(0.79, 0.35, 0.92); break; + case Variant::POOL_COLOR_ARRAY: color = Color(0.57, 0.73, 0.0); break; default: color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.3, 0.3); @@ -420,31 +421,42 @@ void VisualScriptEditor::_update_graph_connections() { graph->clear_connections(); - List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(edited_func, &sequence_conns); - - for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { + List<StringName> funcs; + script->get_function_list(&funcs); - graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0); + if (funcs.size() <= 0) { + updating_graph = false; + return; } - List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(edited_func, &data_conns); - - for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { + for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { - VisualScript::DataConnection dc = E->get(); + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(F->get(), &sequence_conns); - Ref<VisualScriptNode> from_node = script->get_node(edited_func, E->get().from_node); - Ref<VisualScriptNode> to_node = script->get_node(edited_func, E->get().to_node); + for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - if (to_node->has_input_sequence_port()) { - dc.to_port++; + graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0); } - dc.from_port += from_node->get_output_sequence_port_count(); + List<VisualScript::DataConnection> data_conns; + script->get_data_connection_list(F->get(), &data_conns); + + 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); + + if (to_node->has_input_sequence_port()) { + dc.to_port++; + } + + 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); + } } } @@ -473,7 +485,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } } - if (!script->has_function(edited_func)) { + List<StringName> funcs; + script->get_function_list(&funcs); + + if (funcs.size() <= 0) { graph->hide(); select_func_text->show(); updating_graph = false; @@ -515,256 +530,394 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Ref<Texture> seq_port = Control::get_icon("VisualShaderPort", "EditorIcons"); - List<int> ids; - script->get_node_list(edited_func, &ids); - StringName editor_icons = "EditorIcons"; + for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions - for (List<int>::Element *E = ids.front(); E; E = E->next()) { + List<int> ids; + script->get_node_list(F->get(), &ids); + StringName editor_icons = "EditorIcons"; - if (p_only_id >= 0 && p_only_id != E->get()) - continue; + for (List<int>::Element *E = ids.front(); E; E = E->next()) { - Ref<VisualScriptNode> node = script->get_node(edited_func, E->get()); - Vector2 pos = script->get_node_position(edited_func, E->get()); + if (p_only_id >= 0 && p_only_id != E->get()) + continue; - 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); - } + Ref<VisualScriptNode> node = script->get_node(F->get(), E->get()); + Vector2 pos = script->get_node_position(F->get(), E->get()); - gnode->set_meta("__vnode", node); - gnode->set_name(itos(E->get())); - gnode->connect("dragged", this, "_node_moved", varray(E->get())); - gnode->connect("close_request", this, "_remove_node", varray(E->get()), CONNECT_DEFERRED); + 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); + } - if (E->get() != script->get_function_node_id(edited_func)) { - //function can't be erased - gnode->set_show_close_button(true); - } + gnode->set_meta("__vnode", node); + gnode->set_name(itos(E->get())); + gnode->connect("dragged", this, "_node_moved", varray(E->get())); + gnode->connect("close_request", this, "_remove_node", varray(E->get()), CONNECT_DEFERRED); - bool has_gnode_text = false; + if (E->get() != script->get_function_node_id(F->get())) { + //function can't be erased + gnode->set_show_close_button(true); + } - 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_font_override("font", get_font("source", "EditorFonts")); - gnode->add_child(line_edit); - line_edit->connect("text_changed", this, "_expression_text_changed", varray(E->get())); - } else { - String text = node->get_text(); - if (!text.empty()) { + bool has_gnode_text = false; + + 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("Add Input Port"); + hbnc->add_child(btn); + btn->connect("pressed", this, "_add_input_port", varray(E->get())); + } + 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("Add Output Port"); + hbnc->add_child(btn); + btn->connect("pressed", this, "_add_output_port", varray(E->get())); + } + gnode->add_child(hbnc); + } else if (Object::cast_to<VisualScriptExpression>(node.ptr())) { has_gnode_text = true; - Label *label = memnew(Label); - label->set_text(text); - gnode->add_child(label); + LineEdit *line_edit = memnew(LineEdit); + line_edit->set_text(node->get_text()); + line_edit->set_expand_to_text_length(true); + line_edit->add_font_override("font", get_font("source", "EditorFonts")); + gnode->add_child(line_edit); + line_edit->connect("text_changed", this, "_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); + } } - } - - 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", this, "_comment_node_resized", varray(E->get())); - } - - 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(MARGIN_TOP); - c.a = 1; - if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); - mono_color.a = 0.85; - c = mono_color; + 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", this, "_comment_node_resized", varray(E->get())); } - gnode->add_color_override("title_color", c); - c.a = 0.7; - gnode->add_color_override("close_color", c); - gnode->add_style_override("frame", sbf); - } - - const Color mono_color = get_color("mono_color", "Editor"); - - 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. - - // 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); + 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(); + c.a = 1; + if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { + Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); + mono_color.a = 0.85; + c = mono_color; + } + gnode->add_color_override("title_color", c); + c.a = 0.7; + gnode->add_color_override("close_color", c); + gnode->add_color_override("resizer_color", c); + gnode->add_style_override("frame", sbf); } - 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; + const Color mono_color = get_color("mono_color", "Editor"); - if (!single_seq_output) { + int slot_idx = 0; - 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++) { + 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. - 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 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++; } - } - for (int i = 0; i < MAX(node->get_output_value_port_count(), MAX(mixed_seq_ports, node->get_input_value_port_count())); i++) { + int mixed_seq_ports = 0; - bool left_ok = false; - Variant::Type left_type = Variant::NIL; - String left_name; + if (!single_seq_output) { - 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 (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++; + } + } } - bool right_ok = false; - Variant::Type right_type = Variant::NIL; - String right_name; + for (int i = 0; i < MAX(node->get_output_value_port_count(), MAX(mixed_seq_ports, node->get_input_value_port_count())); i++) { - 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; - } + bool left_ok = false; + Variant::Type left_type = Variant::NIL; + String left_name; - HBoxContainer *hbc = memnew(HBoxContainer); + 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 (left_ok) { + bool right_ok = false; + Variant::Type right_type = Variant::NIL; + String right_name; - Ref<Texture> 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 (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<Texture> 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); + } - hbc->add_child(memnew(Label(left_name))); + 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", this, "_update_node_size", varray(E->get())); + name_box->connect("focus_exited", this, "_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(edited_func, E->get(), i)) { + 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", this, "_change_port_type", varray(E->get(), i, true), CONNECT_DEFERRED); + } - 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 - Variant::CallError ce; - const Variant *existingp = &value; - value = Variant::construct(left_type, &existingp, 1, ce, false); + Button *rmbtn = memnew(Button); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + hbc->add_child(rmbtn); + rmbtn->connect("pressed", this, "_remove_input_port", varray(E->get(), i), CONNECT_DEFERRED); + } else { + hbc->add_child(memnew(Label(left_name))); } - if (left_type == Variant::COLOR) { - button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", this, "_draw_color_over_button", varray(button, value)); - } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { + 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 + Variant::CallError ce; + const Variant *existingp = &value; + value = Variant::construct(left_type, &existingp, 1, ce, false); + } - 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); + if (left_type == Variant::COLOR) { + button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); + button->connect("draw", this, "_draw_color_over_button", varray(button, value)); + } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { - } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) { + 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); - button->set_text(pi.hint_string.get_slice(",", value)); - } else { + } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) { - button->set_text(value); + button->set_text(pi.hint_string.get_slice(",", value)); + } else { + + button->set_text(value); + } + button->connect("pressed", this, "_default_value_edited", varray(button, E->get(), i)); + hbc2->add_child(button); } - button->connect("pressed", this, "_default_value_edited", varray(button, E->get(), i)); - hbc->add_child(button); + } else { + Control *c = memnew(Control); + c->set_custom_minimum_size(Size2(10, 0) * EDSCALE); + hbc->add_child(c); } - } else { - Control *c = memnew(Control); - c->set_custom_minimum_size(Size2(10, 0) * EDSCALE); - hbc->add_child(c); - } - hbc->add_spacer(); + hbc->add_spacer(); + hbc2->add_spacer(); - if (i < mixed_seq_ports) { + 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); - } + 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 (right_ok) { + if (right_ok) { + + if (is_vslist) { + Button *rmbtn = memnew(Button); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + hbc->add_child(rmbtn); + rmbtn->connect("pressed", this, "_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", this, "_change_port_type", varray(E->get(), i, false), CONNECT_DEFERRED); + } - hbc->add_child(memnew(Label(right_name))); + 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", this, "_update_node_size", varray(E->get())); + name_box->connect("focus_exited", this, "_port_name_focus_out", varray(name_box, E->get(), i, false)); + } else { + hbc->add_child(memnew(Label(right_name))); + } + } else { + hbc->add_child(memnew(Label(right_name))); + } - Ref<Texture> t; - if (right_type >= 0 && right_type < Variant::VARIANT_MAX) { - t = type_icons[right_type]; + Ref<Texture> 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 (t.is_valid()) { - TextureRect *tf = memnew(TextureRect); - tf->set_texture(t); - tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - hbc->add_child(tf); + + gnode->add_child(vbc); + + bool dark_theme = get_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<Texture>(), 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++; } - gnode->add_child(hbc); + graph->add_child(gnode); - bool dark_theme = get_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<Texture>(), 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)); + if (gnode->is_comment()) { + graph->move_child(gnode, 0); } - - slot_idx++; } + } + _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); + updating_graph = false; +} - graph->add_child(gnode); +void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, bool is_input) { - if (gnode->is_comment()) { - graph->move_child(gnode, 0); - } + StringName func = _get_function_of_node(p_id); + + Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + if (!vsn.is_valid()) + return; + + undo_redo->create_action("Change Port Type"); + if (is_input) { + undo_redo->add_do_method(vsn.ptr(), "set_input_data_port_type", p_port, Variant::Type(p_select)); + undo_redo->add_undo_method(vsn.ptr(), "set_input_data_port_type", p_port, vsn->get_input_value_port_info(p_port).type); + } else { + undo_redo->add_do_method(vsn.ptr(), "set_output_data_port_type", p_port, Variant::Type(p_select)); + undo_redo->add_undo_method(vsn.ptr(), "set_output_data_port_type", p_port, vsn->get_output_value_port_info(p_port).type); } + undo_redo->commit_action(); +} - _update_graph_connections(); - graph->call_deferred("set_scroll_ofs", script->get_function_scroll(edited_func) * EDSCALE); //may need to adapt a bit, let it do so - updating_graph = false; +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 +} +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); + if (!vsn.is_valid()) + return; + + String text; + + if (Object::cast_to<LineEdit>(p_name_box)) + text = Object::cast_to<LineEdit>(p_name_box)->get_text(); + else + return; + + undo_redo->create_action("Change Port Name"); + if (is_input) { + undo_redo->add_do_method(vsn.ptr(), "set_input_data_port_name", p_port, text); + undo_redo->add_undo_method(vsn.ptr(), "set_input_data_port_name", p_port, vsn->get_input_value_port_info(p_port).name); + } else { + undo_redo->add_do_method(vsn.ptr(), "set_output_data_port_name", p_port, text); + undo_redo->add_undo_method(vsn.ptr(), "set_output_data_port_name", p_port, vsn->get_output_value_port_info(p_port).name); + } + undo_redo->commit_action(); } void VisualScriptEditor::_update_members() { + ERR_FAIL_COND(!script.is_valid()); updating_members = true; @@ -774,18 +927,23 @@ void VisualScriptEditor::_update_members() { TreeItem *functions = members->create_item(root); functions->set_selectable(0, false); functions->set_text(0, TTR("Functions:")); - functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1); - functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0); + functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function.")); + functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function.")); functions->set_custom_color(0, Control::get_color("mono_color", "Editor")); List<StringName> func_names; script->get_function_list(&func_names); 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); - ti->set_editable(0, true); ti->set_metadata(0, E->get()); + ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); if (selected == E->get()) ti->select(0); } @@ -793,7 +951,7 @@ void VisualScriptEditor::_update_members() { TreeItem *variables = members->create_item(root); variables->set_selectable(0, false); variables->set_text(0, TTR("Variables:")); - variables->add_button(0, Control::get_icon("Add", "EditorIcons")); + variables->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable.")); variables->set_custom_color(0, Control::get_color("mono_color", "Editor")); Ref<Texture> type_icons[Variant::VARIANT_MAX] = { @@ -846,7 +1004,7 @@ void VisualScriptEditor::_update_members() { TreeItem *_signals = members->create_item(root); _signals->set_selectable(0, false); _signals->set_text(0, TTR("Signals:")); - _signals->add_button(0, Control::get_icon("Add", "EditorIcons")); + _signals->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal.")); _signals->set_custom_color(0, Control::get_color("mono_color", "Editor")); List<StringName> signal_names; @@ -885,15 +1043,15 @@ void VisualScriptEditor::_member_selected() { if (ti->get_parent() == members->get_root()->get_children()) { - if (edited_func != selected) { - - revert_on_drag = edited_func; - edited_func = selected; - _update_members(); - _update_graph(); +#ifdef OSX_ENABLED + bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META); +#else + bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); +#endif + if (held_ctrl) { + ERR_FAIL_COND(!script->has_function(selected)); + _center_on_node(selected, script->get_function_node_id(selected)); } - - return; //or crash because it will become invalid } } @@ -933,9 +1091,6 @@ void VisualScriptEditor::_member_edited() { if (ti->get_parent() == root->get_children()) { - if (edited_func == selected) { - edited_func = new_name; - } selected = new_name; int node_id = script->get_function_node_id(name); @@ -947,10 +1102,27 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_do_method(script.ptr(), "rename_function", name, new_name); undo_redo->add_undo_method(script.ptr(), "rename_function", new_name, name); if (func.is_valid()) { - undo_redo->add_do_method(func.ptr(), "set_name", new_name); 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); + } + } + } + undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); undo_redo->add_do_method(this, "_update_graph"); @@ -959,8 +1131,6 @@ void VisualScriptEditor::_member_edited() { undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); - // _update_graph(); - return; //or crash because it will become invalid } @@ -995,6 +1165,112 @@ void VisualScriptEditor::_member_edited() { } } +void VisualScriptEditor::_create_function_dialog() { + function_create_dialog->popup_centered(); + func_name_box->set_text(""); + func_name_box->grab_focus(); + for (int i = 0; i < func_input_vbox->get_child_count(); i++) { + Node *nd = func_input_vbox->get_child(i); + nd->queue_delete(); + } +} + +void VisualScriptEditor::_create_function() { + String name = _validate_name((func_name_box->get_text() == "") ? "new_func" : func_name_box->get_text()); + selected = name; + Vector2 ofs = _get_available_pos(); + + Ref<VisualScriptFunction> func_node; + func_node.instance(); + func_node->set_name(name); + + for (int i = 0; i < func_input_vbox->get_child_count(); i++) { + OptionButton *opbtn = Object::cast_to<OptionButton>(func_input_vbox->get_child(i)->get_child(3)); + LineEdit *lne = Object::cast_to<LineEdit>(func_input_vbox->get_child(i)->get_child(1)); + if (!opbtn || !lne) + continue; + Variant::Type arg_type = Variant::Type(opbtn->get_selected()); + String arg_name = lne->get_text(); + func_node->add_argument(arg_type, arg_name); + } + + 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_undo_method(script.ptr(), "remove_function", name); + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); + 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(); + + _update_graph(); +} + +void VisualScriptEditor::_add_node_dialog() { + _generic_search(script->get_instance_base_type(), graph->get_global_position() + Vector2(55, 80), true); +} + +void VisualScriptEditor::_add_func_input() { + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->set_h_size_flags(SIZE_EXPAND_FILL); + + Label *name_label = memnew(Label); + name_label->set_text(TTR("Name:")); + hbox->add_child(name_label); + + LineEdit *name_box = memnew(LineEdit); + name_box->set_h_size_flags(SIZE_EXPAND_FILL); + name_box->set_text("input"); + name_box->connect("focus_entered", this, "_deselect_input_names"); + hbox->add_child(name_box); + + Label *type_label = memnew(Label); + type_label->set_text(TTR("Type:")); + hbox->add_child(type_label); + + OptionButton *type_box = memnew(OptionButton); + type_box->set_custom_minimum_size(Size2(120 * EDSCALE, 0)); + for (int i = Variant::NIL; i < Variant::VARIANT_MAX; i++) + type_box->add_item(Variant::get_type_name(Variant::Type(i))); + type_box->select(1); + hbox->add_child(type_box); + + Button *delete_button = memnew(Button); + delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + delete_button->set_tooltip(vformat(TTR("Delete input port"))); + hbox->add_child(delete_button); + + for (int i = 0; i < func_input_vbox->get_child_count(); i++) { + LineEdit *line_edit = (LineEdit *)func_input_vbox->get_child(i)->get_child(1); + line_edit->deselect(); + } + + func_input_vbox->add_child(hbox); + hbox->set_meta("id", hbox->get_position_in_parent()); + + delete_button->connect("pressed", this, "_remove_func_input", varray(hbox)); + + name_box->select_all(); + name_box->grab_focus(); +} + +void VisualScriptEditor::_remove_func_input(Node *p_node) { + func_input_vbox->remove_child(p_node); + p_node->queue_delete(); +} + +void VisualScriptEditor::_deselect_input_names() { + int cn = func_input_vbox->get_child_count(); + for (int i = 0; i < cn; i++) { + LineEdit *lne = Object::cast_to<LineEdit>(func_input_vbox->get_child(i)->get_child(1)); + if (lne) + lne->deselect(); + } +} + void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_button) { TreeItem *ti = Object::cast_to<TreeItem>(p_item); @@ -1007,7 +1283,6 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt //add function, this one uses menu if (p_button == 1) { - new_virtual_method_select->select_method_from_base_type(script->get_instance_base_type(), String(), true); return; @@ -1015,7 +1290,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt String name = _validate_name("new_function"); selected = name; - edited_func = selected; + Vector2 ofs = _get_available_pos(); Ref<VisualScriptFunction> func_node; func_node.instance(); @@ -1023,7 +1298,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt 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); + undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node, ofs); undo_redo->add_undo_method(script.ptr(), "remove_function", name); undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); @@ -1070,133 +1345,193 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt undo_redo->commit_action(); return; //or crash because it will become invalid } + } else if (ti->get_parent() == root->get_children()) { + selected = ti->get_text(0); + function_name_edit->set_position(Input::get_singleton()->get_mouse_position() - Vector2(60, -10)); + function_name_edit->popup(); + function_name_box->set_text(selected); + function_name_box->select_all(); } } -void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id) { +void VisualScriptEditor::_add_input_port(int p_id) { - Ref<VisualScriptExpression> vse = script->get_node(edited_func, p_id); - if (!vse.is_valid()) + StringName func = _get_function_of_node(p_id); + + Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + if (!vsn.is_valid()) return; updating_graph = true; - undo_redo->create_action(TTR("Change Expression"), UndoRedo::MERGE_ENDS); - undo_redo->add_do_property(vse.ptr(), "expression", p_text); - undo_redo->add_undo_property(vse.ptr(), "expression", vse->get("expression")); + undo_redo->create_action(TTR("Add Input Port"), UndoRedo::MERGE_ENDS); + undo_redo->add_do_method(vsn.ptr(), "add_input_data_port", Variant::NIL, "arg", -1); undo_redo->add_do_method(this, "_update_graph", p_id); + + undo_redo->add_undo_method(vsn.ptr(), "remove_input_data_port", vsn->get_input_value_port_count()); undo_redo->add_undo_method(this, "_update_graph", p_id); + + updating_graph = false; + undo_redo->commit_action(); +} - 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 +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); + if (!vsn.is_valid()) + return; + + updating_graph = true; + + undo_redo->create_action(TTR("Add Output Port"), UndoRedo::MERGE_ENDS); + undo_redo->add_do_method(vsn.ptr(), "add_output_data_port", Variant::NIL, "arg", -1); + undo_redo->add_do_method(this, "_update_graph", p_id); + + undo_redo->add_undo_method(vsn.ptr(), "remove_output_data_port", vsn->get_output_value_port_count()); + undo_redo->add_undo_method(this, "_update_graph", p_id); updating_graph = false; + + undo_redo->commit_action(); } -void VisualScriptEditor::_available_node_doubleclicked() { +void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { - TreeItem *item = nodes->get_selected(); + StringName func = _get_function_of_node(p_id); - if (!item) + Ref<VisualScriptLists> vsn = script->get_node(func, p_id); + if (!vsn.is_valid()) return; - String which = item->get_metadata(0); - if (which == String()) + updating_graph = true; + + 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); + + 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(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(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); + undo_redo->add_undo_method(this, "_update_graph", p_id); + + updating_graph = false; + + undo_redo->commit_action(); +} + +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); + if (!vsn.is_valid()) return; - Vector2 ofs = graph->get_scroll_ofs() + graph->get_size() * 0.5; + updating_graph = true; - if (graph->is_using_snap()) { - int snap = graph->get_snap(); - ofs = ofs.snapped(Vector2(snap, snap)); - } + undo_redo->create_action(TTR("Remove Output Port"), UndoRedo::MERGE_ENDS); - ofs /= EDSCALE; + List<VisualScript::DataConnection> data_connections; + script->get_data_connection_list(func, &data_connections); - while (true) { - bool exists = false; - List<int> existing; - script->get_node_list(edited_func, &existing); - for (List<int>::Element *E = existing.front(); E; E = E->next()) { - Point2 pos = script->get_node_position(edited_func, E->get()); - if (pos.distance_to(ofs) < 15) { - ofs += Vector2(graph->get_snap(), graph->get_snap()); - exists = true; - break; - } + 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 + if (!conn_map.has(E->get().to_node)) + conn_map.set(E->get().to_node, Set<int>()); + conn_map[E->get().to_node].insert(E->get().to_port); } + } - if (exists) - continue; - break; + undo_redo->add_do_method(vsn.ptr(), "remove_output_data_port", p_port); + undo_redo->add_do_method(this, "_update_graph", p_id); + + List<int> keys; + 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()); + } } - Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(which); - int new_id = script->get_available_id(); + undo_redo->add_undo_method(vsn.ptr(), "add_output_data_port", vsn->get_output_value_port_info(p_port).type, vsn->get_output_value_port_info(p_port).name, p_port); + undo_redo->add_undo_method(this, "_update_graph", p_id); - undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); + updating_graph = false; - Node *node = graph->get_node(itos(new_id)); - if (node) { - graph->set_selected(node); - _node_selected(node); - } + undo_redo->commit_action(); } -void VisualScriptEditor::_update_available_nodes() { +void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id) { - nodes->clear(); + StringName func = _get_function_of_node(p_id); - TreeItem *root = nodes->create_item(); + Ref<VisualScriptExpression> vse = script->get_node(func, p_id); + if (!vse.is_valid()) + return; - Map<String, TreeItem *> path_cache; + updating_graph = true; - String filter = node_filter->get_text(); + undo_redo->create_action(TTR("Change Expression"), UndoRedo::MERGE_ENDS); + undo_redo->add_do_property(vse.ptr(), "expression", p_text); + undo_redo->add_undo_property(vse.ptr(), "expression", vse->get("expression")); + undo_redo->add_do_method(this, "_update_graph", p_id); + undo_redo->add_undo_method(this, "_update_graph", p_id); + undo_redo->commit_action(); - List<String> fnodes; - VisualScriptLanguage::singleton->get_registered_node_names(&fnodes); + 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 - for (List<String>::Element *E = fnodes.front(); E; E = E->next()) { + updating_graph = false; +} - Vector<String> path = E->get().split("/"); +Vector2 VisualScriptEditor::_get_available_pos(bool centered, Vector2 ofs) const { + if (centered) + ofs = graph->get_scroll_ofs() + graph->get_size() * 0.5; - if (filter != String() && path.size() && path[path.size() - 1].findn(filter) == -1) - continue; + if (graph->is_using_snap()) { + int snap = graph->get_snap(); + ofs = ofs.snapped(Vector2(snap, snap)); + } + + ofs /= EDSCALE; - String sp; - TreeItem *parent = root; - - for (int i = 0; i < path.size() - 1; i++) { - - if (i > 0) - sp += ","; - sp += path[i]; - if (!path_cache.has(sp)) { - TreeItem *pathn = nodes->create_item(parent); - pathn->set_selectable(0, false); - pathn->set_text(0, path[i].capitalize()); - path_cache[sp] = pathn; - parent = pathn; - if (filter == String()) { - pathn->set_collapsed(true); //should remember state + 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; } - } else { - parent = path_cache[sp]; } } - - TreeItem *item = nodes->create_item(parent); - item->set_text(0, path[path.size() - 1].capitalize()); - item->set_selectable(0, true); - item->set_metadata(0, E->get()); + if (exists) + continue; + break; } + + return ofs; } String VisualScriptEditor::_validate_name(const String &p_name) const { @@ -1222,6 +1557,8 @@ String VisualScriptEditor::_validate_name(const String &p_name) const { void VisualScriptEditor::_on_nodes_delete() { + // delete all the selected nodes + List<int> to_erase; for (int i = 0; i < graph->get_child_count(); i++) { @@ -1240,26 +1577,30 @@ void VisualScriptEditor::_on_nodes_delete() { for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { - undo_redo->add_do_method(script.ptr(), "remove_node", edited_func, F->get()); - undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, F->get(), script->get_node(edited_func, F->get()), script->get_node_position(edited_func, F->get())); + 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)); List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(edited_func, &sequence_conns); + script->get_sequence_connection_list(func, &sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_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(), "sequence_connect", edited_func, E->get().from_node, E->get().from_output, E->get().to_node); + 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); } } List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(edited_func, &data_conns); + script->get_data_connection_list(func, &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", edited_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", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } } @@ -1271,13 +1612,16 @@ void VisualScriptEditor::_on_nodes_delete() { void VisualScriptEditor::_on_nodes_duplicate() { - List<int> to_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)); if (gn) { if (gn->is_selected() && gn->is_close_button_visible()) { - to_duplicate.push_back(gn->get_name().operator String().to_int()); + int id = gn->get_name().operator String().to_int(); + to_duplicate.insert(id); + funcs.push_back(_get_function_of_node(id)); } } } @@ -1289,18 +1633,42 @@ void VisualScriptEditor::_on_nodes_duplicate() { int idc = script->get_available_id() + 1; Set<int> to_select; + HashMap<int, int> remap; - for (List<int>::Element *F = to_duplicate.front(); F; F = F->next()) { + for (Set<int>::Element *F = to_duplicate.front(); F; F = F->next()) { - Ref<VisualScriptNode> node = script->get_node(edited_func, F->get()); + // duplicate from the specifc 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()); Ref<VisualScriptNode> dupe = node->duplicate(true); int new_id = idc++; + remap.set(F->get(), new_id); + to_select.insert(new_id); - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, dupe, script->get_node_position(edited_func, F->get()) + Vector2(20, 20)); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, 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); + } + + 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::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); + } + } } + undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -1315,21 +1683,45 @@ void VisualScriptEditor::_on_nodes_duplicate() { } if (to_select.size()) { - EditorNode::get_singleton()->push_item(script->get_node(edited_func, to_select.front()->get()).ptr()); + EditorNode::get_singleton()->push_item(script->get_node(default_func, to_select.front()->get()).ptr()); } } -void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { +void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool node_centered) { + if (node_centered) + port_action_pos = graph->get_size() / 2.0f; + else + port_action_pos = graph->get_viewport()->get_mouse_position() - graph->get_global_position(); + + new_connect_node_select->select_from_visual_script(p_base_type, false, false); // neither connecting nor reset text - Ref<InputEventMouseButton> mb = p_event; + // 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; - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - revert_on_drag = String(); //so we can still drag functions + if (pos != Vector2()) + new_connect_node_select->set_position(pos); +} + +void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { + // GUI input for VS Editor Plugin + Ref<InputEventMouseButton> key = p_event; + + if (key.is_valid() && !key->is_pressed()) { + mouse_up_position = Input::get_singleton()->get_mouse_position(); } } -void VisualScriptEditor::_generic_search() { - new_connect_node_select->select_from_visual_script(String(""), false); +void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> key = p_event; + + if (key.is_valid() && key->is_pressed() && key->get_button_mask() == BUTTON_RIGHT) { + saved_position = graph->get_local_mouse_position(); + + Point2 gpos = Input::get_singleton()->get_mouse_position(); + _generic_search(script->get_instance_base_type(), gpos); + } } void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { @@ -1359,29 +1751,83 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { } } } + + Ref<InputEventMouseButton> btn = 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))); + } } -Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { +void VisualScriptEditor::_rename_function(const String &name, const String &new_name) { - if (p_from == nodes) { + if (!new_name.is_valid_identifier()) { - TreeItem *it = nodes->get_item_at_position(p_point); - if (!it) - return Variant(); - String type = it->get_metadata(0); - if (type == String()) - return Variant(); + EditorNode::get_singleton()->show_warning(TTR("Name is not a valid identifier:") + " " + new_name); + return; + } - Dictionary dd; - dd["type"] = "visual_script_node_drag"; - dd["node_type"] = type; + if (script->has_function(new_name) || script->has_variable(new_name) || script->has_custom_signal(new_name)) { - Label *label = memnew(Label); - label->set_text(it->get_text(0)); - set_drag_preview(label); - return dd; + EditorNode::get_singleton()->show_warning(TTR("Name already in use by another func/var/signal:") + " " + new_name); + return; } + 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); + } + undo_redo->create_action(TTR("Rename Function")); + undo_redo->add_do_method(script.ptr(), "rename_function", name, new_name); + undo_redo->add_undo_method(script.ptr(), "rename_function", new_name, name); + if (func.is_valid()) { + undo_redo->add_do_method(func.ptr(), "set_name", new_name); + 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); + } + } + } + + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); + 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(); +} + +void VisualScriptEditor::_fn_name_box_input(const Ref<InputEvent> &p_event) { + + if (!function_name_edit->is_visible()) + return; + + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_pressed() && key->get_scancode() == KEY_ENTER) { + function_name_edit->hide(); + _rename_function(selected, function_name_box->get_text()); + function_name_box->clear(); + } +} + +Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (p_from == members) { TreeItem *it = members->get_item_at_position(p_point); @@ -1400,11 +1846,6 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f dd["type"] = "visual_script_function_drag"; dd["function"] = type; - if (revert_on_drag != String()) { - edited_func = revert_on_drag; //revert so function does not change - revert_on_drag = String(); - _update_graph(); - } } else if (it->get_parent() == root->get_children()->get_next()) { dd["type"] = "visual_script_variable_drag"; @@ -1524,15 +1965,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da ofs /= EDSCALE; - Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(d["node_type"]); - int new_id = script->get_available_id(); - - undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); + int new_id = _create_new_node_from_name(d["node_type"], ofs, default_func); Node *node = graph->get_node(itos(new_id)); if (node) { @@ -1573,8 +2006,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", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -1603,11 +2036,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", edited_func, new_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", default_func, 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", edited_func, new_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -1636,8 +2069,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", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -1666,8 +2099,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", edited_func, new_id, prnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -1707,8 +2140,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", edited_func, new_id, prnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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); new_ids.push_back(new_id); new_id++; ofs += Vector2(20, 20) * EDSCALE; @@ -1734,7 +2167,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); if (!sn) { - EditorNode::get_singleton()->show_warning("Can't drop nodes because script '" + get_name() + "' is not used in this scene."); + EditorNode::get_singleton()->show_warning(TTR("Can't drop nodes because script '" + get_name() + "' is not used in this scene.")); return; } @@ -1776,21 +2209,20 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da scene_node.instance(); scene_node->set_node_path(sn->get_path_to(node)); n = scene_node; - } else { + // ! Doesn't work properly Ref<VisualScriptFunctionCall> call; call.instance(); call->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH); call->set_base_path(sn->get_path_to(node)); call->set_base_type(node->get_class()); n = call; - - method_select->select_from_instance(node); + method_select->select_from_instance(node, "", true, node->get_class()); selecting_method_id = base_id; } - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, base_id, n, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, 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); base_id++; ofs += Vector2(25, 25); @@ -1805,7 +2237,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); if (!sn && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { - EditorNode::get_singleton()->show_warning("Can't drop properties because script '" + get_name() + "' is not used in this scene.\nDrop holding 'Shift' to just copy the signature."); + EditorNode::get_singleton()->show_warning(TTR("Can't drop properties because script '" + get_name() + "' is not used in this scene.\nDrop holding 'Shift' to just copy the signature.")); return; } @@ -1861,13 +2293,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", edited_func, base_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", default_func, 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", edited_func, base_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, base_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -1908,12 +2340,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", edited_func, base_id, vnode, ofs); + undo_redo->add_do_method(script.ptr(), "add_node", default_func, 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", edited_func, base_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", default_func, base_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); @@ -1922,9 +2354,9 @@ 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) { +void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) { - Ref<VisualScriptFunctionCall> vsfc = script->get_node(edited_func, selecting_method_id); + Ref<VisualScriptFunctionCall> vsfc = script->get_node(default_func, selecting_method_id); if (!vsfc.is_valid()) return; vsfc->set_function(p_method); @@ -1940,7 +2372,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud) { +void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud) { Array ud = p_ud; ERR_FAIL_COND(ud.size() != 2); @@ -1981,8 +2413,16 @@ void VisualScriptEditor::set_edited_resource(const RES &p_res) { script->connect("node_ports_changed", this, "_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(); - _update_available_nodes(); } Vector<String> VisualScriptEditor::get_functions() { @@ -2027,7 +2467,7 @@ bool VisualScriptEditor::is_unsaved() { Variant VisualScriptEditor::get_edit_state() { Dictionary d; - d["function"] = edited_func; + d["function"] = default_func; d["scroll"] = graph->get_scroll_ofs(); d["zoom"] = graph->get_zoom(); d["using_snap"] = graph->is_using_snap(); @@ -2039,8 +2479,7 @@ void VisualScriptEditor::set_edit_state(const Variant &p_state) { Dictionary d = p_state; if (d.has("function")) { - edited_func = p_state; - selected = edited_func; + selected = default_func; } _update_graph(); @@ -2060,16 +2499,24 @@ void VisualScriptEditor::set_edit_state(const Variant &p_state) { } } -void VisualScriptEditor::_center_on_node(int p_id) { +void VisualScriptEditor::_center_on_node(const StringName &p_func, int p_id) { Node *n = graph->get_node(itos(p_id)); GraphNode *gn = Object::cast_to<GraphNode>(n); + + // clear selection + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gnd = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gnd) + gnd->set_selected(false); + } + if (gn) { gn->set_selected(true); Vector2 new_scroll = gn->get_offset() - graph->get_size() * 0.5 + gn->get_size() * 0.5; graph->set_scroll_ofs(new_scroll); - script->set_function_scroll(edited_func, new_scroll / EDSCALE); - script->set_edited(true); //so it's saved + script->set_function_scroll(p_func, new_scroll / EDSCALE); + script->set_edited(true); } } @@ -2086,21 +2533,29 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { if (script->has_node(E->get(), p_line)) { - edited_func = E->get(); - selected = edited_func; _update_graph(); _update_members(); - call_deferred("call_deferred", "_center_on_node", p_line); //editor might be just created and size might not exist yet - + call_deferred("call_deferred", "_center_on_node", E->get(), p_line); //editor might be just created and size might not exist yet return; } } } +void VisualScriptEditor::set_executing_line(int p_line) { + // todo: add a way to show which node is executing right now. +} + +void VisualScriptEditor::clear_executing_line() { + // todo: add a way to show which node is executing right now. +} + void VisualScriptEditor::trim_trailing_whitespace() { } +void VisualScriptEditor::insert_final_newline() { +} + void VisualScriptEditor::convert_indent_to_spaces() { } @@ -2116,6 +2571,7 @@ void VisualScriptEditor::tag_saved_version() { } void VisualScriptEditor::reload(bool p_soft) { + _update_graph(); } void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { @@ -2139,10 +2595,9 @@ void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { void VisualScriptEditor::add_callback(const String &p_function, PoolStringArray p_args) { if (script->has_function(p_function)) { - edited_func = p_function; - selected = edited_func; _update_members(); _update_graph(); + _center_on_node(p_function, script->get_function_node_id(p_function)); return; } @@ -2173,13 +2628,10 @@ void VisualScriptEditor::add_callback(const String &p_function, PoolStringArray script->add_function(p_function); script->add_node(p_function, script->get_available_id(), func); - edited_func = p_function; - selected = edited_func; _update_members(); _update_graph(); - graph->call_deferred("set_scroll_ofs", script->get_function_scroll(edited_func)); //for first time it might need to be later - //undo_redo->clear_history(); + _center_on_node(p_function, script->get_function_node_id(p_function)); } bool VisualScriptEditor::show_members_overview() { @@ -2208,12 +2660,16 @@ Control *VisualScriptEditor::get_edit_menu() { void VisualScriptEditor::_change_base_type() { - select_base_type->popup_create(true); + select_base_type->popup_create(true, true); +} + +void VisualScriptEditor::_toggle_tool_script() { + script->set_tool_enabled(!script->is_tool()); } void VisualScriptEditor::clear_edit_menu() { memdelete(edit_menu); - memdelete(left_vsplit); + memdelete(members_section); } void VisualScriptEditor::_change_base_type_callback() { @@ -2277,46 +2733,66 @@ void VisualScriptEditor::_end_node_move() { undo_redo->commit_action(); } -void VisualScriptEditor::_move_node(String func, int p_id, const Vector2 &p_to) { +void VisualScriptEditor::_move_node(const StringName &p_func, int p_id, const Vector2 &p_to) { + + if (!script->has_function(p_func)) + return; + + Node *node = graph->get_node(itos(p_id)); + + if (Object::cast_to<GraphNode>(node)) + Object::cast_to<GraphNode>(node)->set_offset(p_to); + + script->set_node_position(p_func, p_id, p_to / EDSCALE); +} + +StringName VisualScriptEditor::_get_function_of_node(int p_id) const { - if (func == String(edited_func)) { - Node *node = graph->get_node(itos(p_id)); - if (Object::cast_to<GraphNode>(node)) - Object::cast_to<GraphNode>(node)->set_offset(p_to); + 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(); + } } - script->set_node_position(edited_func, p_id, p_to / EDSCALE); + + return ""; // this is passed to avoid crash and is tested against later } void VisualScriptEditor::_node_moved(Vector2 p_from, Vector2 p_to, int p_id) { - undo_redo->add_do_method(this, "_move_node", String(edited_func), p_id, p_to); - undo_redo->add_undo_method(this, "_move_node", String(edited_func), p_id, p_from); + 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); } void VisualScriptEditor::_remove_node(int p_id) { undo_redo->create_action(TTR("Remove VisualScript Node")); - undo_redo->add_do_method(script.ptr(), "remove_node", edited_func, p_id); - undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, p_id, script->get_node(edited_func, p_id), script->get_node_position(edited_func, p_id)); + 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)); List<VisualScript::SequenceConnection> sequence_conns; - script->get_sequence_connection_list(edited_func, &sequence_conns); + script->get_sequence_connection_list(func, &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", edited_func, E->get().from_node, E->get().from_output, E->get().to_node); + undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, E->get().from_node, E->get().from_output, E->get().to_node); } } List<VisualScript::DataConnection> data_conns; - script->get_data_connection_list(edited_func, &data_conns); + script->get_data_connection_list(func, &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", edited_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", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } @@ -2328,15 +2804,29 @@ void VisualScriptEditor::_remove_node(int p_id) { void VisualScriptEditor::_node_ports_changed(const String &p_func, int p_id) { - if (p_func != String(edited_func)) - return; - _update_graph(p_id); } +bool VisualScriptEditor::node_has_sequence_connections(const StringName &p_func, int p_id) { + List<VisualScript::SequenceConnection> sequence_conns; + script->get_sequence_connection_list(p_func, &sequence_conns); + + 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; + + if (to == p_id || from == p_id) + return true; + } + + return false; +} + void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - Ref<VisualScriptNode> from_node = script->get_node(edited_func, p_from.to_int()); + StringName from_func = _get_function_of_node(p_from.to_int()); + + Ref<VisualScriptNode> from_node = script->get_node(from_func, p_from.to_int()); ERR_FAIL_COND(!from_node.is_valid()); bool from_seq; @@ -2345,7 +2835,9 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) return; //can't connect this, it's invalid - Ref<VisualScriptNode> to_node = script->get_node(edited_func, p_to.to_int()); + StringName to_func = _get_function_of_node(p_to.to_int()); + + Ref<VisualScriptNode> to_node = script->get_node(to_func, p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); bool to_seq; @@ -2356,29 +2848,170 @@ 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 + 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", edited_func, p_from.to_int(), from_port, p_to.to_int()); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int()); + 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()); } 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 + 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); + } + } - // disconnect current, and connect the new one - if (script->is_input_value_port_connected(edited_func, p_to.to_int(), to_port)) { - int conn_from; - int conn_port; - script->get_input_value_port_connection_source(edited_func, p_to.to_int(), to_port, &conn_from, &conn_port); - undo_redo->add_do_method(script.ptr(), "data_disconnect", edited_func, conn_from, conn_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", edited_func, conn_from, conn_port, p_to.to_int(), to_port); + 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 + 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); + } } - undo_redo->add_do_method(script.ptr(), "data_connect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port); - //update nodes in sgraph - 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()); + 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::REAL); + exceptions = exceptions || (to_type == Variant::REAL && 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 construtor 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 construtor 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)) { + 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); + 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); + } + } + 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); + } + //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()); + undo_redo->add_undo_method(this, "_update_graph", p_from.to_int()); + undo_redo->add_undo_method(this, "_update_graph", p_to.to_int()); + } else { + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); + } } undo_redo->add_do_method(this, "_update_graph_connections"); @@ -2389,7 +3022,10 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - Ref<VisualScriptNode> from_node = script->get_node(edited_func, p_from.to_int()); + 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()); ERR_FAIL_COND(!from_node.is_valid()); bool from_seq; @@ -2398,7 +3034,7 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) return; //can't connect this, it's invalid - Ref<VisualScriptNode> to_node = script->get_node(edited_func, p_to.to_int()); + Ref<VisualScriptNode> to_node = script->get_node(func, p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); bool to_seq; @@ -2409,15 +3045,20 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl ERR_FAIL_COND(from_seq != to_seq); - undo_redo->create_action(TTR("Connect Nodes")); + undo_redo->create_action(TTR("Disconnect Nodes")); if (from_seq) { - undo_redo->add_do_method(script.ptr(), "sequence_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int()); - undo_redo->add_undo_method(script.ptr(), "sequence_connect", edited_func, p_from.to_int(), from_port, p_to.to_int()); + 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()); } else { - undo_redo->add_do_method(script.ptr(), "data_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port); - undo_redo->add_undo_method(script.ptr(), "data_connect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port); - //update nodes in sgraph + + 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(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()); @@ -2429,6 +3070,216 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl 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); + + 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; + + 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); @@ -2436,7 +3287,9 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro if (!gn) return; - Ref<VisualScriptNode> vsn = script->get_node(edited_func, p_from.to_int()); + StringName func = _get_function_of_node(p_from.to_int()); + + Ref<VisualScriptNode> vsn = script->get_node(func, p_from.to_int()); if (!vsn.is_valid()) return; @@ -2446,12 +3299,11 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro port_action_node = p_from.to_int(); port_action_output = p_from_slot; - _port_action_menu(CREATE_ACTION); + _port_action_menu(CREATE_ACTION, func); } 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); + _port_action_menu(CREATE_CALL_SET_GET, func); } } @@ -2465,7 +3317,9 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac visited_nodes.insert(p_port_action_node); - Ref<VisualScriptNode> node = script->get_node(edited_func, 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); if (!node.is_valid()) { @@ -2484,7 +3338,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac int from_node; int from_port; - if (script->get_input_value_port_connection_source(edited_func, p_port_action_node, i, &from_node, &from_port)) { + if (script->get_input_value_port_connection_source(func, p_port_action_node, i, &from_node, &from_port)) { g = _guess_output_type(from_node, from_port, visited_nodes); } else { @@ -2509,7 +3363,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) { +void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) { Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; if (graph->is_using_snap()) { @@ -2518,8 +3372,6 @@ void VisualScriptEditor::_port_action_menu(int p_option) { } ofs /= EDSCALE; - bool seq_connect = false; - Set<int> vn; switch (p_option) { @@ -2535,8 +3387,10 @@ void VisualScriptEditor::_port_action_menu(int p_option) { } else { n->set_base_type("Object"); } - - String type_string = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + 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 (tg.type == Variant::OBJECT) { if (tg.script.is_valid()) { new_connect_node_select->select_from_script(tg.script, ""); @@ -2550,11 +3404,19 @@ void VisualScriptEditor::_port_action_menu(int p_option) { } else { new_connect_node_select->select_from_basic_type(tg.type); } + // 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; + pos.y = pos.y > bounds.y ? bounds.y : pos.y; + new_connect_node_select->set_position(pos); } break; case CREATE_ACTION: { - seq_connect = true; VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); - PropertyInfo property_info = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output); + 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 (tg.type == Variant::OBJECT) { if (property_info.type == Variant::OBJECT && property_info.hint_string != String()) { new_connect_node_select->select_from_action(property_info.hint_string); @@ -2566,25 +3428,18 @@ void VisualScriptEditor::_port_action_menu(int p_option) { } else { new_connect_node_select->select_from_action(Variant::get_type_name(tg.type)); } + // 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; + pos.y = pos.y > bounds.y ? bounds.y : pos.y; + new_connect_node_select->set_position(pos); } break; } } -void VisualScriptEditor::new_node(Ref<VisualScriptNode> vnode, Vector2 ofs) { - Set<int> vn; - Ref<VisualScriptNode> vnode_old = script->get_node(edited_func, port_action_node); - int new_id = script->get_available_id(); - undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, 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(); - - port_action_new_node = new_id; -} - void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id) { + undo_redo->create_action(TTR("Connect Node Data")); VisualScriptReturn *vnode_return = Object::cast_to<VisualScriptReturn>(vnode.ptr()); if (vnode_return != NULL && vnode_old->get_output_value_port_count() > 0) { @@ -2603,13 +3458,14 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua if (port >= value_count) { port = 0; } - int count = vnode_old->get_output_value_port_count() + vnode_old->get_output_sequence_port_count(); - undo_redo->add_do_method(script.ptr(), "data_connect", edited_func, port_action_node, port, new_id, 0); - undo_redo->add_undo_method(script.ptr(), "data_disconnect", edited_func, port_action_node, port, new_id, 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->commit_action(); } void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) { + Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -2619,19 +3475,29 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Set<int> vn; + 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 (p_category == "visualscript") { Ref<VisualScriptNode> vnode_new = VisualScriptLanguage::singleton->create_node_from_name(p_text); - Ref<VisualScriptNode> vnode_old = script->get_node(edited_func, port_action_node); + Ref<VisualScriptNode> vnode_old; + if (port_node_exists) + vnode_old = script->get_node(func, port_action_node); int new_id = script->get_available_id(); - if (Object::cast_to<VisualScriptOperator>(vnode_new.ptr()) && script->get_node(edited_func, port_action_node).is_valid()) { - Variant::Type type = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).type; + if (Object::cast_to<VisualScriptOperator>(vnode_new.ptr()) && vnode_old.is_valid()) { + Variant::Type type = vnode_old->get_output_value_port_info(port_action_output).type; Object::cast_to<VisualScriptOperator>(vnode_new.ptr())->set_typed(type); } - if (Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr()) && script->get_node(edited_func, port_action_node).is_valid()) { - Variant::Type type = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).type; - String hint_name = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + if (Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr()) && vnode_old.is_valid()) { + Variant::Type type = vnode_old->get_output_value_port_info(port_action_output).type; + String hint_name = vnode_old->get_output_value_port_info(port_action_output).hint_string; if (type == Variant::OBJECT) { Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr())->set_base_type(hint_name); @@ -2641,14 +3507,15 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Object::cast_to<VisualScriptTypeCast>(vnode_new.ptr())->set_base_type(Variant::get_type_name(type)); } } + undo_redo->create_action(TTR("Add Node")); - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode_new, ofs); - if (vnode_old.is_valid() && p_connecting == true) { + undo_redo->add_do_method(script.ptr(), "add_node", func, 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", edited_func, new_id); + undo_redo->add_undo_method(script.ptr(), "remove_node", func, new_id); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); @@ -2657,7 +3524,6 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Ref<VisualScriptNode> vnode; - seq_connect = false; if (p_category == String("method")) { Ref<VisualScriptFunctionCall> n; @@ -2683,152 +3549,161 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Ref<VisualScriptCondition> n; n.instance(); vnode = n; - seq_connect = true; } if (p_text == "VisualScriptSwitch") { Ref<VisualScriptSwitch> n; n.instance(); vnode = n; - seq_connect = true; } else if (p_text == "VisualScriptSequence") { Ref<VisualScriptSequence> n; n.instance(); vnode = n; - seq_connect = true; } else if (p_text == "VisualScriptIterator") { Ref<VisualScriptIterator> n; n.instance(); vnode = n; - seq_connect = true; } else if (p_text == "VisualScriptWhile") { Ref<VisualScriptWhile> n; n.instance(); vnode = n; - seq_connect = true; } else if (p_text == "VisualScriptReturn") { Ref<VisualScriptReturn> n; n.instance(); vnode = n; - seq_connect = true; } } - new_node(vnode, ofs); + 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(this, "_update_graph", new_id); + undo_redo->add_undo_method(this, "_update_graph", new_id); + undo_redo->commit_action(); + + port_action_new_node = new_id; - Ref<VisualScriptNode> vsn = script->get_node(edited_func, port_action_new_node); + Ref<VisualScriptNode> vsn = script->get_node(func, port_action_new_node); if (Object::cast_to<VisualScriptFunctionCall>(vsn.ptr())) { Ref<VisualScriptFunctionCall> vsfc = vsn; vsfc->set_function(p_text); - VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); - if (tg.type == Variant::OBJECT) { - vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); - vsfc->set_base_type(String("")); - if (tg.gdclass != StringName()) { - vsfc->set_base_type(tg.gdclass); + if (port_node_exists && p_connecting) { + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); + + if (tg.type == Variant::OBJECT) { + vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); + vsfc->set_base_type(String("")); + if (tg.gdclass != StringName()) { + vsfc->set_base_type(tg.gdclass); - } else if (script->get_node(edited_func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + } 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; - if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { - vsfc->set_base_type(base_type); + if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { + vsfc->set_base_type(base_type); + } + if (p_text == "call" || p_text == "call_deferred") { + vsfc->set_function(String("")); + } } - if (p_text == "call" || p_text == "call_deferred") { - vsfc->set_function(String("")); + if (tg.script.is_valid()) { + vsfc->set_base_script(tg.script->get_path()); } + } else if (tg.type == Variant::NIL) { + vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); + vsfc->set_base_type(String("")); + } else { + vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE); + vsfc->set_basic_type(tg.type); } - if (tg.script.is_valid()) { - vsfc->set_base_script(tg.script->get_path()); - } - } else if (tg.type == Variant::NIL) { - vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); - vsfc->set_base_type(String("")); - } else { - vsfc->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE); - vsfc->set_basic_type(tg.type); } } - if (Object::cast_to<VisualScriptPropertySet>(vsn.ptr())) { - - Ref<VisualScriptPropertySet> vsp = vsn; + if (port_node_exists && p_connecting) { + if (Object::cast_to<VisualScriptPropertySet>(vsn.ptr())) { + Ref<VisualScriptPropertySet> vsp = vsn; - VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); - if (tg.type == Variant::OBJECT) { - vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); - vsp->set_base_type(String("")); - if (tg.gdclass != StringName()) { - vsp->set_base_type(tg.gdclass); + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); + if (tg.type == Variant::OBJECT) { + vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); + vsp->set_base_type(String("")); + if (tg.gdclass != StringName()) { + vsp->set_base_type(tg.gdclass); - } else if (script->get_node(edited_func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint_string; + } 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; - if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { - vsp->set_base_type(base_type); + if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { + vsp->set_base_type(base_type); + } } + if (tg.script.is_valid()) { + vsp->set_base_script(tg.script->get_path()); + } + } else if (tg.type == Variant::NIL) { + vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); + vsp->set_base_type(String("")); + } else { + vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_BASIC_TYPE); + vsp->set_basic_type(tg.type); } - if (tg.script.is_valid()) { - vsp->set_base_script(tg.script->get_path()); - } - } else if (tg.type == Variant::NIL) { - vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); - vsp->set_base_type(String("")); - } else { - vsp->set_call_mode(VisualScriptPropertySet::CALL_MODE_BASIC_TYPE); - vsp->set_basic_type(tg.type); } - } - - if (Object::cast_to<VisualScriptPropertyGet>(vsn.ptr())) { - Ref<VisualScriptPropertyGet> vsp = vsn; - VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); - if (tg.type == Variant::OBJECT) { - vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); - vsp->set_base_type(String("")); - if (tg.gdclass != StringName()) { - vsp->set_base_type(tg.gdclass); + if (Object::cast_to<VisualScriptPropertyGet>(vsn.ptr())) { + Ref<VisualScriptPropertyGet> vsp = vsn; - } else if (script->get_node(edited_func, port_action_node).is_valid()) { - PropertyHint hint = script->get_node(edited_func, port_action_node)->get_output_value_port_info(port_action_output).hint; - String base_type = script->get_node(edited_func, 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); + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node, port_action_output, vn); + if (tg.type == Variant::OBJECT) { + vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); + vsp->set_base_type(String("")); + 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; + if (base_type != String() && hint == PROPERTY_HINT_TYPE_STRING) { + vsp->set_base_type(base_type); + } } + if (tg.script.is_valid()) { + vsp->set_base_script(tg.script->get_path()); + } + } else if (tg.type == Variant::NIL) { + vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); + vsp->set_base_type(String("")); + } else { + vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE); + vsp->set_basic_type(tg.type); } - if (tg.script.is_valid()) { - vsp->set_base_script(tg.script->get_path()); - } - } else if (tg.type == Variant::NIL) { - vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); - vsp->set_base_type(String("")); - } else { - vsp->set_call_mode(VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE); - vsp->set_basic_type(tg.type); } } - Ref<VisualScriptNode> vnode_old = script->get_node(edited_func, port_action_node); - if (vnode_old.is_valid() && p_connecting == true) { - connect_seq(vnode_old, vnode, port_action_new_node); - connect_data(vnode_old, vnode, port_action_new_node); + if (port_node_exists) { + Ref<VisualScriptNode> vnode_old = script->get_node(func, 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); - _update_graph_connections(); + if (port_node_exists) + _update_graph_connections(); } void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id) { - int seq_count = vnode_old->get_output_sequence_port_count(); + VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(vnode_new.ptr()); - if (vnode_operator != NULL && vnode_operator->has_input_sequence_port() == false) { + if (vnode_operator != NULL && !vnode_operator->has_input_sequence_port()) { return; } VisualScriptConstructor *vnode_constructor = Object::cast_to<VisualScriptConstructor>(vnode_new.ptr()); @@ -2838,31 +3713,33 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual if (vnode_old->get_output_sequence_port_count() <= 0) { return; } - if (vnode_new->has_input_sequence_port() == false) { + if (!vnode_new->has_input_sequence_port()) { return; } - VisualScriptFunction *vnode_function = Object::cast_to<VisualScriptFunction>(vnode_old.ptr()); + + 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(edited_func, port_action_node).has(pass_port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, port_action_node, pass_port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, port_action_node, pass_port, new_id); + !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); } else if (vnode_old->get_output_value_port_info(port_action_output).name == String("return") && - !script->get_output_sequence_ports_connected(edited_func, port_action_node).has(return_port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, port_action_node, return_port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, port_action_node, return_port, new_id); + !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); } 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(edited_func, port_action_node).has(port_action_output)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, port_action_node, port_action_output, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, port_action_node, port_action_output, new_id); + 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); break; - } else if (!script->get_output_sequence_ports_connected(edited_func, port_action_node).has(port)) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, port_action_node, port, new_id); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, port_action_node, port, new_id); + } 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); break; } } @@ -2895,7 +3772,6 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons } selected = name; - edited_func = selected; Ref<VisualScriptFunction> func_node; func_node.instance(); func_node->set_name(name); @@ -2907,14 +3783,16 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons func_node->add_argument(minfo.arguments[i].type, minfo.arguments[i].name, -1, minfo.arguments[i].hint, minfo.arguments[i].hint_string); } - undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node); + Vector2 ofs = _get_available_pos(); + + undo_redo->add_do_method(script.ptr(), "add_node", name, script->get_available_id(), func_node, ofs); 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, Vector2(500, 0)); + 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))); } undo_redo->add_undo_method(script.ptr(), "remove_function", name); @@ -2929,31 +3807,30 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons } void VisualScriptEditor::_cancel_connect_node() { - // Causes crashes - //script->remove_node(edited_func, port_action_new_node); - _update_graph(); + // ensure the cancel is done + port_action_new_node = -1; } -void VisualScriptEditor::_create_new_node(const String &p_text, const String &p_category, const Vector2 &p_point) { - Vector2 ofs = graph->get_scroll_ofs() + p_point; - if (graph->is_using_snap()) { - int snap = graph->get_snap(); - ofs = ofs.snapped(Vector2(snap, snap)); - } - ofs /= EDSCALE; +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; + 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", edited_func, new_id, vnode, ofs); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); + return new_id; } void VisualScriptEditor::_default_value_changed() { - Ref<VisualScriptNode> vsn = script->get_node(edited_func, editing_id); + Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(editing_id), editing_id); if (vsn.is_null()) return; @@ -2968,7 +3845,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(edited_func, p_id); + Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(p_id), p_id); if (vsn.is_null()) return; @@ -2987,16 +3864,18 @@ 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(); - Node *script_node = _find_script_node(edited_scene, edited_scene, script); + 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 - pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; - pinfo.hint_string = script_node->get_path(); - } else { - //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(); + if (script_node) { + //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 + pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; + pinfo.hint_string = get_tree()->get_edited_scene_root()->get_path(); + } } } @@ -3023,54 +3902,64 @@ void VisualScriptEditor::_hide_timer() { hint_text->hide(); } -void VisualScriptEditor::_node_filter_changed(const String &p_text) { +void VisualScriptEditor::_notification(int p_what) { - _update_available_nodes(); -} + switch (p_what) { + case NOTIFICATION_READY: { + variable_editor->connect("changed", this, "_update_members"); + signal_editor->connect("changed", this, "_update_members"); + FALLTHROUGH; + } + case NOTIFICATION_THEME_CHANGED: { + if (p_what != NOTIFICATION_READY && !is_visible_in_tree()) { + return; + } -void VisualScriptEditor::_notification(int p_what) { + edit_variable_edit->add_style_override("bg", get_stylebox("bg", "Tree")); + edit_signal_edit->add_style_override("bg", get_stylebox("bg", "Tree")); + func_input_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); - if (p_what == NOTIFICATION_READY) { - node_filter->set_right_icon(Control::get_icon("Search", "EditorIcons")); - node_filter->set_clear_button_enabled(true); - variable_editor->connect("changed", this, "_update_members"); - signal_editor->connect("changed", this, "_update_members"); + Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); - Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); + bool dark_theme = tm->get_constant("dark_theme", "Editor"); - bool dark_theme = tm->get_constant("dark_theme", "Editor"); + List<Pair<String, Color> > colors; + if (dark_theme) { + colors.push_back(Pair<String, Color>("flow_control", Color(0.96, 0.96, 0.96))); + colors.push_back(Pair<String, Color>("functions", Color(0.96, 0.52, 0.51))); + colors.push_back(Pair<String, Color>("data", Color(0.5, 0.96, 0.81))); + colors.push_back(Pair<String, Color>("operators", Color(0.67, 0.59, 0.87))); + colors.push_back(Pair<String, Color>("custom", Color(0.5, 0.73, 0.96))); + colors.push_back(Pair<String, Color>("constants", Color(0.96, 0.5, 0.69))); + } else { + colors.push_back(Pair<String, Color>("flow_control", Color(0.26, 0.26, 0.26))); + colors.push_back(Pair<String, Color>("functions", Color(0.95, 0.4, 0.38))); + colors.push_back(Pair<String, Color>("data", Color(0.07, 0.73, 0.51))); + colors.push_back(Pair<String, Color>("operators", Color(0.51, 0.4, 0.82))); + colors.push_back(Pair<String, Color>("custom", Color(0.31, 0.63, 0.95))); + colors.push_back(Pair<String, Color>("constants", Color(0.94, 0.18, 0.49))); + } - List<Pair<String, Color> > colors; - if (dark_theme) { - colors.push_back(Pair<String, Color>("flow_control", Color::html("#f4f4f4"))); - colors.push_back(Pair<String, Color>("functions", Color::html("#f58581"))); - colors.push_back(Pair<String, Color>("data", Color::html("#80f6cf"))); - colors.push_back(Pair<String, Color>("operators", Color::html("#ab97df"))); - colors.push_back(Pair<String, Color>("custom", Color::html("#80bbf6"))); - colors.push_back(Pair<String, Color>("constants", Color::html("#f680b0"))); - } else { - colors.push_back(Pair<String, Color>("flow_control", Color::html("#424242"))); - colors.push_back(Pair<String, Color>("functions", Color::html("#f26661"))); - colors.push_back(Pair<String, Color>("data", Color::html("#13bb83"))); - colors.push_back(Pair<String, Color>("operators", Color::html("#8265d0"))); - colors.push_back(Pair<String, Color>("custom", Color::html("#4ea0f2"))); - colors.push_back(Pair<String, Color>("constants", Color::html("#f02f7d"))); - } + for (List<Pair<String, Color> >::Element *E = colors.front(); E; E = E->next()) { + Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode"); + if (!sb.is_null()) { + Ref<StyleBoxFlat> frame_style = sb->duplicate(); + Color c = sb->get_border_color(); + Color cn = E->get().second; + cn.a = c.a; + frame_style->set_border_color(cn); + node_styles[E->get().first] = frame_style; + } + } - for (List<Pair<String, Color> >::Element *E = colors.front(); E; E = E->next()) { - Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode"); - if (!sb.is_null()) { - Ref<StyleBoxFlat> frame_style = sb->duplicate(); - Color c = sb->get_border_color(MARGIN_TOP); - Color cn = E->get().second; - cn.a = c.a; - frame_style->set_border_color_all(cn); - node_styles[E->get().first] = frame_style; + if (is_visible_in_tree() && script.is_valid()) { + _update_members(); + _update_graph(); } - } - } - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - left_vsplit->set_visible(is_visible_in_tree()); + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + members_section->set_visible(is_visible_in_tree()); + } break; } } @@ -3081,8 +3970,9 @@ void VisualScriptEditor::_graph_ofs_changed(const Vector2 &p_ofs) { updating_graph = true; - if (script->has_function(edited_func)) { - script->set_function_scroll(edited_func, graph->get_scroll_ofs() / EDSCALE); + // 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); } updating_graph = false; @@ -3093,7 +3983,9 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ if (updating_graph) return; - Ref<VisualScriptComment> vsc = script->get_node(edited_func, p_node); + StringName func = _get_function_of_node(p_node); + + Ref<VisualScriptComment> vsc = script->get_node(func, p_node); if (vsc.is_null()) return; @@ -3106,12 +3998,12 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ graph->set_block_minimum_size_adjust(true); //faster resize - undo_redo->create_action("Resize Comment", UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Resize Comment"), UndoRedo::MERGE_ENDS); undo_redo->add_do_method(vsc.ptr(), "set_size", p_new_size / EDSCALE); undo_redo->add_undo_method(vsc.ptr(), "set_size", vsc->get_size()); undo_redo->commit_action(); - gn->set_custom_minimum_size(p_new_size); //for this time since graph update is blocked + gn->set_custom_minimum_size(p_new_size); gn->set_size(Size2(1, 1)); graph->set_block_minimum_size_adjust(false); updating_graph = false; @@ -3131,7 +4023,8 @@ void VisualScriptEditor::_menu_option(int p_what) { if (gn) { if (gn->is_selected()) { int id = String(gn->get_name()).to_int(); - Ref<VisualScriptNode> vsn = script->get_node(edited_func, id); + StringName func = _get_function_of_node(id); + Ref<VisualScriptNode> vsn = script->get_node(func, id); if (vsn.is_valid()) { vsn->set_breakpoint(!vsn->is_breakpoint()); reselect.push_back(gn->get_name()); @@ -3149,32 +4042,34 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_FIND_NODE_TYPE: { - _generic_search(); + _generic_search(script->get_instance_base_type()); } break; case EDIT_COPY_NODES: case EDIT_CUT_NODES: { - - if (!script->has_function(edited_func)) + 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(); - Ref<VisualScriptNode> node = script->get_node(edited_func, id); + StringName func = _get_function_of_node(id); + Ref<VisualScriptNode> node = script->get_node(func, 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(edited_func, id); + clipboard->nodes_positions[id] = script->get_node_position(func, id); + funcs.insert(String(func)); } } } @@ -3183,37 +4078,38 @@ void VisualScriptEditor::_menu_option(int p_what) { if (clipboard->nodes.empty()) break; - List<VisualScript::SequenceConnection> sequence_connections; + for (Set<String>::Element *F = funcs.front(); F; F = F->next()) { + List<VisualScript::SequenceConnection> sequence_connections; - script->get_sequence_connection_list(edited_func, &sequence_connections); + script->get_sequence_connection_list(F->get(), &sequence_connections); - for (List<VisualScript::SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { + 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)) { + if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->sequence_connections.insert(E->get()); + clipboard->sequence_connections.insert(E->get()); + } } - } - List<VisualScript::DataConnection> data_connections; + List<VisualScript::DataConnection> data_connections; - script->get_data_connection_list(edited_func, &data_connections); + script->get_data_connection_list(F->get(), &data_connections); - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + 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)) { + if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->data_connections.insert(E->get()); + clipboard->data_connections.insert(E->get()); + } } } - if (p_what == EDIT_CUT_NODES) { _on_nodes_delete(); // oh yeah, also delete on cut } } break; case EDIT_PASTE_NODES: { - if (!script->has_function(edited_func)) + if (!script->has_function(default_func)) break; if (clipboard->nodes.empty()) { @@ -3231,11 +4127,15 @@ void VisualScriptEditor::_menu_option(int p_what) { Set<Vector2> existing_positions; { - List<int> nodes; - script->get_node_list(edited_func, &nodes); - for (List<int>::Element *E = nodes.front(); E; E = E->next()) { - Vector2 pos = script->get_node_position(edited_func, E->get()).snapped(Vector2(2, 2)); - existing_positions.insert(pos); + 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); + } } } @@ -3254,20 +4154,20 @@ void VisualScriptEditor::_menu_option(int p_what) { paste_pos += Vector2(20, 20) * EDSCALE; } - undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, node, paste_pos); - undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id); + 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); } for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); - undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, remap[E->get().from_node], E->get().from_output, remap[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]); + 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]); } for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "data_connect", edited_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", edited_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", 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(this, "_update_graph"); @@ -3283,6 +4183,275 @@ void VisualScriptEditor::_menu_option(int p_what) { } } } break; + case EDIT_CREATE_FUNCTION: { + + StringName function = ""; + Map<int, Ref<VisualScriptNode> > nodes; + Set<int> selections; + 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); + 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; + } + } + } + } + + if (nodes.size() == 0) { + return; // nothing to be done if there are no valid nodes selected + } + + Set<VisualScript::SequenceConnection> seqmove; + Set<VisualScript::DataConnection> datamove; + + Set<VisualScript::SequenceConnection> seqext; + Set<VisualScript::DataConnection> dataext; + + int start_node = -1; + Set<int> end_nodes; + if (nodes.size() == 1) { + Ref<VisualScriptNode> nd = script->get_node(function, nodes.front()->key()); + if (nd.is_valid() && nd->has_input_sequence_port()) + start_node = nodes.front()->key(); + else { + EditorNode::get_singleton()->show_warning(TTR("Select atleast one node with sequence port.")); + return; + } + } else { + List<VisualScript::SequenceConnection> seqs; + script->get_sequence_connection_list(function, &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 + 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()); + 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); + } + Vector2 pos = script->get_node_position(function, E->key()); + if (top.y > pos.y) { + top_nd = E->key(); + top = pos; + } + } + } + Ref<VisualScriptNode> nd = script->get_node(function, top_nd); + if (nd.is_valid() && nd->has_input_sequence_port()) + start_node = top_nd; + else { + EditorNode::get_singleton()->show_warning(TTR("Select atleast one node with sequence port.")); + return; + } + } else { + // 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()) { + if (nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) { + seqmove.insert(E->get()); + nodes_from.insert(E->get().from_node); + } else if (nodes.has(E->get().from_node) && !nodes.has(E->get().to_node)) { + seqext.insert(E->get()); + } else if (!nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) { + if (start_node == -1) { + seqext.insert(E->get()); + start_node = E->get().to_node; + } else { + EditorNode::get_singleton()->show_warning(TTR("Try to only have one sequence input in selection.")); + return; + } + } + nodes_to.insert(E->get().to_node); + } + + // 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 + for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) { + if (!nodes_to.has(E->get())) { + start_node = E->get(); + } + } + } + } + } + + if (start_node == -1) { + 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); + 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); + if (node.is_valid()) { + dataext.insert(E->get()); + PropertyInfo pi = node->get_input_value_port_info(E->get().to_port); + inputs.push_back(pi.type); + input_connections.push_back(Pair<int, int>(E->get().to_node, E->get().to_port)); + } + } else if (nodes.has(E->get().from_node) && !nodes.has(E->get().to_node)) { + dataext.insert(E->get()); + } + } + } + + 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 + + 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())); + + // 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())); + } + + 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); + } + + 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); + } + + // 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 + 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); + } + 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); + } + + // 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); + + // end nodes are mapped to the return nodes with data connections if possible + int m = 1; + for (Set<int>::Element *G = end_nodes.front(); G; G = G->next()) { + Ref<VisualScriptReturn> ret_node; + ret_node.instance(); + + 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); + + 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()); + 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 + 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); + } + } + + // * 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 + selections.insert(fn_id); + for (int k = 0; k < graph->get_child_count(); k++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(k)); + if (gn) { + int id = gn->get_name().operator String().to_int(); + gn->set_selected(selections.has(id)); + } + } + + // 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(); + } break; + } +} + +// 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 + _get_ends(to, p_seqs, p_selected, r_end_nodes); + } else if (from == p_node && !p_selected.has(to)) { + r_end_nodes.insert(from); + } } } @@ -3295,6 +4464,9 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { member_popup->set_position(members->get_global_position() + p_pos); member_popup->set_size(Vector2()); + function_name_edit->set_position(members->get_global_position() + p_pos); + function_name_edit->set_size(Vector2()); + TreeItem *root = members->get_root(); Ref<Texture> del_icon = Control::get_icon("Remove", "EditorIcons"); @@ -3305,6 +4477,8 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { member_type = MEMBER_FUNCTION; member_name = ti->get_text(0); + member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); + member_popup->add_separator(); member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE); member_popup->popup(); return; @@ -3367,16 +4541,16 @@ void VisualScriptEditor::_member_option(int p_option) { 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); } - /* - for(int i=0;i<script->function_get_argument_count(name);i++) { - undo_redo->add_undo_method(script.ptr(),"function_add_argument",name,script->function_get_argument_name(name,i),script->function_get_argument_type(name,i)); - } - */ undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); + } else if (p_option == MEMBER_EDIT) { + selected = members->get_selected()->get_text(0); + function_name_edit->popup(); + function_name_box->set_text(selected); + function_name_box->select_all(); } } break; case MEMBER_VARIABLE: { @@ -3413,7 +4587,6 @@ void VisualScriptEditor::_member_option(int p_option) { undo_redo->add_undo_method(this, "_update_members"); undo_redo->commit_action(); } else if (p_option == MEMBER_EDIT) { - signal_editor->edit(name); edit_signal_dialog->set_title(TTR("Editing Signal:") + " " + name); edit_signal_dialog->popup_centered_minsize(Size2(400, 300) * EDSCALE); @@ -3434,8 +4607,14 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_member_edited", &VisualScriptEditor::_member_edited); ClassDB::bind_method("_member_selected", &VisualScriptEditor::_member_selected); ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members); + ClassDB::bind_method("_members_gui_input", &VisualScriptEditor::_members_gui_input); + ClassDB::bind_method("_member_rmb_selected", &VisualScriptEditor::_member_rmb_selected); + ClassDB::bind_method("_member_option", &VisualScriptEditor::_member_option); + ClassDB::bind_method("_fn_name_box_input", &VisualScriptEditor::_fn_name_box_input); + ClassDB::bind_method("_change_base_type", &VisualScriptEditor::_change_base_type); ClassDB::bind_method("_change_base_type_callback", &VisualScriptEditor::_change_base_type_callback); + ClassDB::bind_method("_toggle_tool_script", &VisualScriptEditor::_toggle_tool_script); ClassDB::bind_method("_node_selected", &VisualScriptEditor::_node_selected); ClassDB::bind_method("_node_moved", &VisualScriptEditor::_node_moved); ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); @@ -3444,7 +4623,14 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_remove_node", &VisualScriptEditor::_remove_node); ClassDB::bind_method("_update_graph", &VisualScriptEditor::_update_graph, DEFVAL(-1)); ClassDB::bind_method("_node_ports_changed", &VisualScriptEditor::_node_ports_changed); - ClassDB::bind_method("_available_node_doubleclicked", &VisualScriptEditor::_available_node_doubleclicked); + + ClassDB::bind_method("_create_function_dialog", &VisualScriptEditor::_create_function_dialog); + ClassDB::bind_method("_create_function", &VisualScriptEditor::_create_function); + ClassDB::bind_method("_add_node_dialog", &VisualScriptEditor::_add_node_dialog); + ClassDB::bind_method("_add_func_input", &VisualScriptEditor::_add_func_input); + ClassDB::bind_method("_remove_func_input", &VisualScriptEditor::_remove_func_input); + ClassDB::bind_method("_deselect_input_names", &VisualScriptEditor::_deselect_input_names); + ClassDB::bind_method("_default_value_edited", &VisualScriptEditor::_default_value_edited); ClassDB::bind_method("_default_value_changed", &VisualScriptEditor::_default_value_changed); ClassDB::bind_method("_menu_option", &VisualScriptEditor::_menu_option); @@ -3457,15 +4643,23 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_selected_new_virtual_method", &VisualScriptEditor::_selected_new_virtual_method); ClassDB::bind_method("_cancel_connect_node", &VisualScriptEditor::_cancel_connect_node); - ClassDB::bind_method("_create_new_node", &VisualScriptEditor::_create_new_node); + ClassDB::bind_method("_create_new_node_from_name", &VisualScriptEditor::_create_new_node_from_name); ClassDB::bind_method("_expression_text_changed", &VisualScriptEditor::_expression_text_changed); + ClassDB::bind_method("_add_input_port", &VisualScriptEditor::_add_input_port); + ClassDB::bind_method("_add_output_port", &VisualScriptEditor::_add_output_port); + ClassDB::bind_method("_remove_input_port", &VisualScriptEditor::_remove_input_port); + ClassDB::bind_method("_remove_output_port", &VisualScriptEditor::_remove_output_port); + ClassDB::bind_method("_change_port_type", &VisualScriptEditor::_change_port_type); + ClassDB::bind_method("_update_node_size", &VisualScriptEditor::_update_node_size); + ClassDB::bind_method("_port_name_focus_out", &VisualScriptEditor::_port_name_focus_out); ClassDB::bind_method("get_drag_data_fw", &VisualScriptEditor::get_drag_data_fw); ClassDB::bind_method("can_drop_data_fw", &VisualScriptEditor::can_drop_data_fw); ClassDB::bind_method("drop_data_fw", &VisualScriptEditor::drop_data_fw); ClassDB::bind_method("_input", &VisualScriptEditor::_input); - ClassDB::bind_method("_members_gui_input", &VisualScriptEditor::_members_gui_input); + ClassDB::bind_method("_graph_gui_input", &VisualScriptEditor::_graph_gui_input); + ClassDB::bind_method("_on_nodes_delete", &VisualScriptEditor::_on_nodes_delete); ClassDB::bind_method("_on_nodes_duplicate", &VisualScriptEditor::_on_nodes_duplicate); @@ -3476,17 +4670,10 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_graph_connect_to_empty", &VisualScriptEditor::_graph_connect_to_empty); ClassDB::bind_method("_update_graph_connections", &VisualScriptEditor::_update_graph_connections); - ClassDB::bind_method("_node_filter_changed", &VisualScriptEditor::_node_filter_changed); ClassDB::bind_method("_selected_method", &VisualScriptEditor::_selected_method); ClassDB::bind_method("_draw_color_over_button", &VisualScriptEditor::_draw_color_over_button); - ClassDB::bind_method("_member_rmb_selected", &VisualScriptEditor::_member_rmb_selected); - - ClassDB::bind_method("_member_option", &VisualScriptEditor::_member_option); - - ClassDB::bind_method("_update_available_nodes", &VisualScriptEditor::_update_available_nodes); - ClassDB::bind_method("_generic_search", &VisualScriptEditor::_generic_search); } @@ -3496,9 +4683,12 @@ VisualScriptEditor::VisualScriptEditor() { clipboard = memnew(Clipboard); } updating_graph = false; + saved_pos_dirty = false; + saved_position = Vector2(0, 0); edit_menu = memnew(MenuButton); 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); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/find_node_type"), EDIT_FIND_NODE_TYPE); @@ -3506,56 +4696,50 @@ VisualScriptEditor::VisualScriptEditor() { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/copy_nodes"), EDIT_COPY_NODES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/cut_nodes"), EDIT_CUT_NODES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/paste_nodes"), EDIT_PASTE_NODES); - + edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/create_function"), EDIT_CREATE_FUNCTION); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/refresh_nodes"), REFRESH_GRAPH); edit_menu->get_popup()->connect("id_pressed", this, "_menu_option"); - left_vsplit = memnew(VSplitContainer); - ScriptEditor::get_singleton()->get_left_list_split()->call_deferred("add_child", left_vsplit); //add but wait until done settig up this - left_vsplit->set_v_size_flags(SIZE_EXPAND_FILL); - left_vsplit->set_stretch_ratio(2); - left_vsplit->hide(); + members_section = memnew(VBoxContainer); + // Add but wait until done setting up this. + ScriptEditor::get_singleton()->get_left_list_split()->call_deferred("add_child", members_section); + members_section->set_v_size_flags(SIZE_EXPAND_FILL); - VBoxContainer *left_vb = memnew(VBoxContainer); - left_vsplit->add_child(left_vb); - left_vb->set_v_size_flags(SIZE_EXPAND_FILL); - //left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE); + CheckButton *tool_script_check = memnew(CheckButton); + tool_script_check->set_text(TTR("Make Tool:")); + members_section->add_child(tool_script_check); + tool_script_check->connect("pressed", this, "_toggle_tool_script"); - base_type_select = memnew(Button); - left_vb->add_margin_child(TTR("Base Type:"), base_type_select); - base_type_select->connect("pressed", this, "_change_base_type"); + /// Members /// members = memnew(Tree); - left_vb->add_margin_child(TTR("Members:"), members, true); + members_section->add_margin_child(TTR("Members:"), members, true); + members->set_custom_minimum_size(Size2(0, 50 * EDSCALE)); members->set_hide_root(true); members->connect("button_pressed", this, "_member_button"); members->connect("item_edited", this, "_member_edited"); members->connect("cell_selected", this, "_member_selected", varray(), CONNECT_DEFERRED); members->connect("gui_input", this, "_members_gui_input"); + members->connect("item_rmb_selected", this, "_member_rmb_selected"); + members->set_allow_rmb_select(true); members->set_allow_reselect(true); members->set_hide_folding(true); members->set_drag_forwarding(this); - VBoxContainer *left_vb2 = memnew(VBoxContainer); - left_vsplit->add_child(left_vb2); - left_vb2->set_v_size_flags(SIZE_EXPAND_FILL); - - VBoxContainer *vbc_nodes = memnew(VBoxContainer); - HBoxContainer *hbc_nodes = memnew(HBoxContainer); - node_filter = memnew(LineEdit); - node_filter->connect("text_changed", this, "_node_filter_changed"); - hbc_nodes->add_child(node_filter); - node_filter->set_h_size_flags(SIZE_EXPAND_FILL); - vbc_nodes->add_child(hbc_nodes); - - nodes = memnew(Tree); - vbc_nodes->add_child(nodes); - nodes->set_v_size_flags(SIZE_EXPAND_FILL); + member_popup = memnew(PopupMenu); + add_child(member_popup); + member_popup->connect("id_pressed", this, "_member_option"); - left_vb2->add_margin_child(TTR("Available Nodes:"), vbc_nodes, true); + function_name_edit = memnew(PopupDialog); + function_name_box = memnew(LineEdit); + function_name_edit->add_child(function_name_box); + function_name_edit->set_h_size_flags(SIZE_EXPAND); + function_name_box->connect("gui_input", this, "_fn_name_box_input"); + function_name_box->set_expand_to_text_length(true); + add_child(function_name_edit); - nodes->set_hide_root(true); - nodes->connect("item_activated", this, "_available_node_doubleclicked"); - nodes->set_drag_forwarding(this); + /// Actual Graph /// graph = memnew(GraphEdit); add_child(graph); @@ -3566,12 +4750,79 @@ VisualScriptEditor::VisualScriptEditor() { graph->connect("_end_node_move", this, "_end_node_move"); graph->connect("delete_nodes_request", this, "_on_nodes_delete"); graph->connect("duplicate_nodes_request", this, "_on_nodes_duplicate"); + graph->connect("gui_input", this, "_graph_gui_input"); graph->set_drag_forwarding(this); graph->hide(); graph->connect("scroll_offset_changed", this, "_graph_ofs_changed"); + /// Add Buttons to Top Bar/Zoom bar. + HBoxContainer *graph_hbc = graph->get_zoom_hbox(); + + Label *base_lbl = memnew(Label); + base_lbl->set_text("Change Base Type: "); + graph_hbc->add_child(base_lbl); + + base_type_select = memnew(Button); + base_type_select->connect("pressed", this, "_change_base_type"); + graph_hbc->add_child(base_type_select); + + Button *add_nds = memnew(Button); + add_nds->set_text("Add Nodes..."); + graph_hbc->add_child(add_nds); + add_nds->connect("pressed", this, "_add_node_dialog"); + + Button *fn_btn = memnew(Button); + fn_btn->set_text("Add Function..."); + graph_hbc->add_child(fn_btn); + fn_btn->connect("pressed", this, "_create_function_dialog"); + + // Add Function Dialog. + VBoxContainer *function_vb = memnew(VBoxContainer); + function_vb->set_v_size_flags(SIZE_EXPAND_FILL); + + HBoxContainer *func_name_hbox = memnew(HBoxContainer); + function_vb->add_child(func_name_hbox); + + Label *func_name_label = memnew(Label); + func_name_label->set_text(TTR("Name:")); + func_name_hbox->add_child(func_name_label); + + func_name_box = memnew(LineEdit); + func_name_box->set_h_size_flags(SIZE_EXPAND_FILL); + func_name_box->set_placeholder(TTR("function_name")); + func_name_box->set_text(""); + func_name_box->connect("focus_entered", this, "_deselect_input_names"); + func_name_hbox->add_child(func_name_box); + + // Add minor setting for function if needed, here! + + function_vb->add_child(memnew(HSeparator)); + + Button *add_input_button = memnew(Button); + add_input_button->set_h_size_flags(SIZE_EXPAND_FILL); + add_input_button->set_text(TTR("Add Input")); + add_input_button->connect("pressed", this, "_add_func_input"); + function_vb->add_child(add_input_button); + + func_input_scroll = memnew(ScrollContainer); + func_input_scroll->set_v_size_flags(SIZE_EXPAND_FILL); + function_vb->add_child(func_input_scroll); + + func_input_vbox = memnew(VBoxContainer); + func_input_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + func_input_scroll->add_child(func_input_vbox); + + function_create_dialog = memnew(ConfirmationDialog); + function_create_dialog->set_custom_minimum_size(Size2(450, 300) * EDSCALE); + function_create_dialog->set_v_size_flags(SIZE_EXPAND_FILL); + 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", this, "_create_function"); + add_child(function_create_dialog); + select_func_text = memnew(Label); - select_func_text->set_text(TTR("Select or create a function to edit graph")); + select_func_text->set_text(TTR("Select or create a function to edit its graph.")); select_func_text->set_align(Label::ALIGN_CENTER); select_func_text->set_valign(Label::VALIGN_CENTER); select_func_text->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3590,7 +4841,7 @@ VisualScriptEditor::VisualScriptEditor() { hint_text_timer->connect("timeout", this, "_hide_timer"); add_child(hint_text_timer); - //allowed casts (connections) + // Allowed casts (connections). for (int i = 0; i < Variant::VARIANT_MAX; i++) { graph->add_valid_connection_type(Variant::NIL, i); graph->add_valid_connection_type(i, Variant::NIL); @@ -3612,7 +4863,6 @@ VisualScriptEditor::VisualScriptEditor() { edit_signal_dialog = memnew(AcceptDialog); edit_signal_dialog->get_ok()->set_text(TTR("Close")); add_child(edit_signal_dialog); - edit_signal_dialog->set_title(TTR("Edit Signal Arguments:")); signal_editor = memnew(VisualScriptEditorSignalEdit); edit_signal_edit = memnew(EditorInspector); @@ -3623,7 +4873,6 @@ VisualScriptEditor::VisualScriptEditor() { edit_variable_dialog = memnew(AcceptDialog); edit_variable_dialog->get_ok()->set_text(TTR("Close")); add_child(edit_variable_dialog); - edit_variable_dialog->set_title(TTR("Edit Variable:")); variable_editor = memnew(VisualScriptEditorVariableEdit); edit_variable_edit = memnew(EditorInspector); @@ -3632,17 +4881,16 @@ VisualScriptEditor::VisualScriptEditor() { edit_variable_edit->edit(variable_editor); select_base_type = memnew(CreateDialog); - select_base_type->set_base_type("Object"); //anything goes + select_base_type->set_base_type("Object"); // Anything goes. select_base_type->connect("create", this, "_change_base_type_callback"); - select_base_type->get_ok()->set_text(TTR("Change")); add_child(select_base_type); undo_redo = EditorNode::get_singleton()->get_undo_redo(); updating_members = false; - set_process_input(true); //for revert on drag - set_process_unhandled_input(true); //for revert on drag + set_process_input(true); + set_process_unhandled_input(true); default_value_edit = memnew(CustomPropertyEditor); add_child(default_value_edit); @@ -3655,26 +4903,18 @@ VisualScriptEditor::VisualScriptEditor() { new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); + new_connect_node_select->set_resizable(true); new_connect_node_select->connect("selected", this, "_selected_connect_node"); new_connect_node_select->get_cancel()->connect("pressed", this, "_cancel_connect_node"); new_virtual_method_select = memnew(VisualScriptPropertySelector); add_child(new_virtual_method_select); new_virtual_method_select->connect("selected", this, "_selected_new_virtual_method"); - new_virtual_method_select->get_cancel()->connect("pressed", this, "_selected_new_virtual_method"); - - member_popup = memnew(PopupMenu); - add_child(member_popup); - members->connect("item_rmb_selected", this, "_member_rmb_selected"); - members->set_allow_rmb_select(true); - member_popup->connect("id_pressed", this, "_member_option"); - - _VisualScriptEditor::get_singleton()->connect("custom_nodes_updated", this, "_update_available_nodes"); } VisualScriptEditor::~VisualScriptEditor() { - undo_redo->clear_history(); //avoid crashes + undo_redo->clear_history(); // Avoid crashes. memdelete(signal_editor); memdelete(variable_editor); } @@ -3705,12 +4945,14 @@ static void register_editor_callback() { ED_SHORTCUT("visual_script_editor/copy_nodes", TTR("Copy Nodes"), KEY_MASK_CMD + KEY_C); ED_SHORTCUT("visual_script_editor/cut_nodes", TTR("Cut Nodes"), KEY_MASK_CMD + KEY_X); ED_SHORTCUT("visual_script_editor/paste_nodes", TTR("Paste Nodes"), KEY_MASK_CMD + KEY_V); + ED_SHORTCUT("visual_script_editor/create_function", TTR("Make Function"), KEY_MASK_CMD + KEY_G); + ED_SHORTCUT("visual_script_editor/refresh_nodes", TTR("Refresh Graph"), KEY_MASK_CMD + KEY_R); ED_SHORTCUT("visual_script_editor/edit_member", TTR("Edit Member"), KEY_MASK_CMD + KEY_E); } void VisualScriptEditor::register_editor() { - //too early to register stuff here, request a callback + // Too early to register stuff here, request a callback. EditorNode::add_plugin_init_callback(register_editor_callback); } @@ -3752,4 +4994,7 @@ void _VisualScriptEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_custom_node", "name", "category"), &_VisualScriptEditor::remove_custom_node); ADD_SIGNAL(MethodInfo("custom_nodes_updated")); } + +void VisualScriptEditor::validate() { +} #endif diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index b0bf971630..5a00469eea 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -37,13 +37,14 @@ #include "scene/gui/graph_edit.h" #include "visual_script.h" #include "visual_script_property_selector.h" + class VisualScriptEditorSignalEdit; class VisualScriptEditorVariableEdit; #ifdef TOOLS_ENABLED class VisualScriptEditor : public ScriptEditorBase { - GDCLASS(VisualScriptEditor, ScriptEditorBase) + GDCLASS(VisualScriptEditor, ScriptEditorBase); enum { TYPE_SEQUENCE = 1000, @@ -58,6 +59,8 @@ class VisualScriptEditor : public ScriptEditorBase { EDIT_COPY_NODES, EDIT_CUT_NODES, EDIT_PASTE_NODES, + EDIT_CREATE_FUNCTION, + REFRESH_GRAPH }; enum PortAction { @@ -78,17 +81,19 @@ class VisualScriptEditor : public ScriptEditorBase { MEMBER_SIGNAL }; - VSplitContainer *left_vsplit; + VBoxContainer *members_section; MenuButton *edit_menu; Ref<VisualScript> script; Button *base_type_select; - GraphEdit *graph; + LineEdit *func_name_box; + ScrollContainer *func_input_scroll; + VBoxContainer *func_input_vbox; + ConfirmationDialog *function_create_dialog; - LineEdit *node_filter; - TextureRect *node_filter_icon; + GraphEdit *graph; VisualScriptEditorSignalEdit *signal_editor; @@ -109,7 +114,8 @@ class VisualScriptEditor : public ScriptEditorBase { UndoRedo *undo_redo; Tree *members; - Tree *nodes; + PopupDialog *function_name_edit; + LineEdit *function_name_box; Label *hint_text; Timer *hint_text_timer; @@ -132,6 +138,7 @@ 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); @@ -159,16 +166,18 @@ class VisualScriptEditor : public ScriptEditorBase { MemberType member_type; String member_name; - bool seq_connect = false; - PortAction port_action; int port_action_node; int port_action_output; Vector2 port_action_pos; int port_action_new_node; - void _port_action_menu(int p_option); - void new_node(Ref<VisualScriptNode> vnode, Vector2 ofs); + bool saved_pos_dirty; + Vector2 saved_position; + + Vector2 mouse_up_position; + + void _port_action_menu(int p_option, const StringName &p_func); void connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id); @@ -176,23 +185,26 @@ class VisualScriptEditor : public ScriptEditorBase { void connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id); void _cancel_connect_node(); - void _create_new_node(const String &p_text, const String &p_category, const Vector2 &p_point); - void _selected_new_virtual_method(const String &p_text = String(""), const String &p_category = String(""), const bool p_connecting = true); + int _create_new_node_from_name(const String &p_text, const Vector2 &p_point, const StringName &p_func = StringName()); + 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(int p_id); + void _center_on_node(const StringName &p_func, int p_id); void _node_filter_changed(const String &p_text); void _change_base_type_callback(); void _change_base_type(); + void _toggle_tool_script(); void _member_selected(); void _member_edited(); void _begin_node_move(); void _end_node_move(); - void _move_node(String func, int p_id, const Vector2 &p_to); + void _move_node(const StringName &p_func, 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); void _node_moved(Vector2 p_from, Vector2 p_to, int p_id); void _remove_node(int p_id); @@ -201,21 +213,44 @@ class VisualScriptEditor : public ScriptEditorBase { 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 _available_node_doubleclicked(); + void _node_create(); void _update_available_nodes(); void _member_button(Object *p_item, int p_column, int p_button); void _expression_text_changed(const String &p_text, int p_id); + void _add_input_port(int p_id); + void _add_output_port(int p_id); + void _remove_input_port(int p_id, int p_port); + void _remove_output_port(int p_id, int p_port); + void _change_port_type(int p_select, int p_id, int p_port, bool is_input); + void _update_node_size(int p_id); + void _port_name_focus_out(const Node *p_name_box, int p_id, int p_port, bool is_input); - String revert_on_drag; + Vector2 _get_available_pos(bool centered = true, Vector2 pos = Vector2()) const; + StringName _get_function_of_node(int p_id) const; - void _input(const Ref<InputEvent> &p_event); + 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); - void _generic_search(); + void _generic_search(String p_base_type = "", Vector2 pos = Vector2(), bool node_centered = false); + void _input(const Ref<InputEvent> &p_event); + void _graph_gui_input(const Ref<InputEvent> &p_event); void _members_gui_input(const Ref<InputEvent> &p_event); + void _fn_name_box_input(const Ref<InputEvent> &p_event); + void _rename_function(const String &p_name, const String &p_new_name); + + void _create_function_dialog(); + void _create_function(); + void _add_func_input(); + void _remove_func_input(Node *p_node); + void _deselect_input_names(); + void _add_node_dialog(); + void _node_item_selected(); + void _node_item_unselected(); + void _on_nodes_delete(); void _on_nodes_duplicate(); @@ -226,6 +261,10 @@ class VisualScriptEditor : public ScriptEditorBase { int editing_id; int editing_input; + bool can_swap; + int data_disconnect_node; + int data_disconnect_port; + void _default_value_changed(); void _default_value_edited(Node *p_button, int p_id, int p_input_port); @@ -235,12 +274,12 @@ class VisualScriptEditor : public ScriptEditorBase { void _comment_node_resized(const Vector2 &p_new_size, int p_node); int selecting_method_id; - void _selected_method(const String &p_method, const String &p_type); + void _selected_method(const String &p_method, const String &p_type, const bool p_connecting); void _draw_color_over_button(Object *obj, Color p_color); - void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud); + void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud); - VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes); + VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &p_visited_nodes); void _member_rmb_selected(const Vector2 &p_pos); void _member_option(int p_option); @@ -264,7 +303,10 @@ public: virtual Variant get_edit_state(); virtual void set_edit_state(const Variant &p_state); virtual void goto_line(int p_line, bool p_with_error = false); + virtual void set_executing_line(int p_line); + virtual void clear_executing_line(); virtual void trim_trailing_whitespace(); + virtual void insert_final_newline(); virtual void convert_indent_to_spaces(); virtual void convert_indent_to_tabs(); virtual void ensure_focus(); @@ -279,6 +321,7 @@ public: virtual Control *get_edit_menu(); virtual void clear_edit_menu(); virtual bool can_lose_focus_on_node_selection() { return false; } + virtual void validate(); static void register_editor(); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 868d22b541..4b74c088e0 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -679,10 +679,10 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(expr2); _get_token(tk); if (tk.type != TK_COLON) { @@ -690,11 +690,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { return NULL; } - expr = _parse_expression(); - if (!expr) + expr2 = _parse_expression(); + if (!expr2) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -723,10 +723,10 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - an->array.push_back(expr); + an->array.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -807,11 +807,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - constructor->arguments.push_back(expr); + constructor->arguments.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -848,11 +848,11 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - bifunc->arguments.push_back(expr); + bifunc->arguments.push_back(expr2); cofs = str_ofs; _get_token(tk); @@ -947,25 +947,25 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs3; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *expr2 = _parse_expression(); + if (!expr2) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(expr2); - cofs = str_ofs; + cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs3; } else { _set_error("Expected ',' or ')'"); } @@ -1032,7 +1032,8 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break; case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break; case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break; - default: {}; + default: { + }; } if (op == Variant::OP_MAX) { //stop appending stuff @@ -1129,7 +1130,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { if (next_op == -1) { _set_error("Yet another parser bug...."); - ERR_FAIL_COND_V(next_op == -1, NULL); + ERR_FAIL_V(NULL); } // OK! create operator.. @@ -1426,8 +1427,8 @@ public: for (int i = 0; i < call->arguments.size(); i++) { Variant value; - bool ret = _execute(p_inputs, call->arguments[i], value, r_error_str, ce); - if (ret) + bool ret2 = _execute(p_inputs, call->arguments[i], value, r_error_str, ce); + if (ret2) return true; arr.write[i] = value; argp.write[i] = &arr[i]; diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h index 1f41e442c5..3a045d2cf7 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -36,7 +36,7 @@ class VisualScriptExpression : public VisualScriptNode { - GDCLASS(VisualScriptExpression, VisualScriptNode) + GDCLASS(VisualScriptExpression, VisualScriptNode); friend class VisualScriptNodeInstanceExpression; struct Input { diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index c3ab949d24..d927b75f89 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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.h b/modules/visual_script/visual_script_flow_control.h index 40809d488a..d3c7aa68e3 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -35,7 +35,7 @@ class VisualScriptReturn : public VisualScriptNode { - GDCLASS(VisualScriptReturn, VisualScriptNode) + GDCLASS(VisualScriptReturn, VisualScriptNode); Variant::Type type; bool with_value; @@ -72,7 +72,7 @@ public: class VisualScriptCondition : public VisualScriptNode { - GDCLASS(VisualScriptCondition, VisualScriptNode) + GDCLASS(VisualScriptCondition, VisualScriptNode); protected: static void _bind_methods(); @@ -100,7 +100,7 @@ public: class VisualScriptWhile : public VisualScriptNode { - GDCLASS(VisualScriptWhile, VisualScriptNode) + GDCLASS(VisualScriptWhile, VisualScriptNode); protected: static void _bind_methods(); @@ -128,7 +128,7 @@ public: class VisualScriptIterator : public VisualScriptNode { - GDCLASS(VisualScriptIterator, VisualScriptNode) + GDCLASS(VisualScriptIterator, VisualScriptNode); protected: static void _bind_methods(); @@ -156,7 +156,7 @@ public: class VisualScriptSequence : public VisualScriptNode { - GDCLASS(VisualScriptSequence, VisualScriptNode) + GDCLASS(VisualScriptSequence, VisualScriptNode); int steps; @@ -189,7 +189,7 @@ public: class VisualScriptSwitch : public VisualScriptNode { - GDCLASS(VisualScriptSwitch, VisualScriptNode) + GDCLASS(VisualScriptSwitch, VisualScriptNode); struct Case { Variant::Type type; @@ -231,7 +231,7 @@ public: class VisualScriptTypeCast : public VisualScriptNode { - GDCLASS(VisualScriptTypeCast, VisualScriptNode) + GDCLASS(VisualScriptTypeCast, VisualScriptNode); StringName base_type; String script; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 1913bfd8c7..7f36549ae4 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -51,10 +51,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const { bool VisualScriptFunctionCall::has_input_sequence_port() 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))) - return false; - else - return true; + 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))); } #ifdef TOOLS_ENABLED @@ -129,18 +126,19 @@ StringName VisualScriptFunctionCall::_get_base_type() const { int VisualScriptFunctionCall::get_input_value_port_count() const { if (call_mode == CALL_MODE_BASIC_TYPE) { - - Vector<StringName> names = Variant::get_method_argument_names(basic_type, function); - return names.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1; + Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function); + return types.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1; } else { MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { - return mb->get_argument_count() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - use_default_args; + int defaulted_args = mb->get_argument_count() < use_default_args ? mb->get_argument_count() : use_default_args; + return mb->get_argument_count() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args; } - return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - use_default_args; + int defaulted_args = method_cache.arguments.size() < use_default_args ? method_cache.arguments.size() : use_default_args; + return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args; } } int VisualScriptFunctionCall::get_output_value_port_count() const { @@ -574,7 +572,6 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string - } else { } } } @@ -950,7 +947,7 @@ int VisualScriptPropertySet::get_output_sequence_port_count() const { bool VisualScriptPropertySet::has_input_sequence_port() const { - return call_mode != CALL_MODE_BASIC_TYPE ? true : false; + return call_mode != CALL_MODE_BASIC_TYPE; } Node *VisualScriptPropertySet::_get_base_node() const { @@ -1031,7 +1028,6 @@ void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const { } PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const { - if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) { if (p_idx == 0) { PropertyInfo pi; @@ -1039,8 +1035,16 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower()); _adjust_input_index(pi); return pi; - } else { - p_idx--; + } + } + + List<PropertyInfo> props; + ClassDB::get_property_list(_get_base_type(), &props, true); + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + if (E->get().name == property) { + PropertyInfo pinfo = PropertyInfo(E->get().type, "value", PROPERTY_HINT_TYPE_STRING, E->get().hint_string); + _adjust_input_index(pinfo); + return pinfo; } } @@ -1356,7 +1360,6 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string - } else { } } } @@ -1563,7 +1566,8 @@ public: case VisualScriptPropertySet::ASSIGN_OP_BIT_XOR: { value = Variant::evaluate(Variant::OP_BIT_XOR, value, p_argument); } break; - default: {} + default: { + } } if (index != StringName()) { @@ -1797,22 +1801,18 @@ PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type); pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower()); return pi; - } else { - p_idx--; } } return PropertyInfo(); } PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const { - - if (index != StringName()) { - - Variant v; - Variant::CallError ce; - v = Variant::construct(type_cache, NULL, 0, ce); - Variant i = v.get(index); - return PropertyInfo(i.get_type(), "value." + String(index)); + List<PropertyInfo> props; + ClassDB::get_property_list(_get_base_type(), &props, true); + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + if (E->get().name == property) { + return PropertyInfo(E->get().type, "value." + String(index)); + } } return PropertyInfo(type_cache, "value"); @@ -2076,7 +2076,6 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string - } else { } } } diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 3b522564d4..11eb96293b 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -35,7 +35,8 @@ class VisualScriptFunctionCall : public VisualScriptNode { - GDCLASS(VisualScriptFunctionCall, VisualScriptNode) + GDCLASS(VisualScriptFunctionCall, VisualScriptNode); + public: enum CallMode { CALL_MODE_SELF, @@ -137,7 +138,8 @@ VARIANT_ENUM_CAST(VisualScriptFunctionCall::RPCCallMode); class VisualScriptPropertySet : public VisualScriptNode { - GDCLASS(VisualScriptPropertySet, VisualScriptNode) + GDCLASS(VisualScriptPropertySet, VisualScriptNode); + public: enum CallMode { CALL_MODE_SELF, @@ -242,7 +244,8 @@ VARIANT_ENUM_CAST(VisualScriptPropertySet::AssignOp); class VisualScriptPropertyGet : public VisualScriptNode { - GDCLASS(VisualScriptPropertyGet, VisualScriptNode) + GDCLASS(VisualScriptPropertyGet, VisualScriptNode); + public: enum CallMode { CALL_MODE_SELF, @@ -323,7 +326,7 @@ VARIANT_ENUM_CAST(VisualScriptPropertyGet::CallMode); class VisualScriptEmitSignal : public VisualScriptNode { - GDCLASS(VisualScriptEmitSignal, VisualScriptNode) + GDCLASS(VisualScriptEmitSignal, VisualScriptNode); private: StringName name; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 5c880f48d1..957127fe61 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -197,7 +197,6 @@ String VisualScriptFunction::get_output_sequence_port_text(int p_port) const { PropertyInfo VisualScriptFunction::get_input_value_port_info(int p_idx) const { ERR_FAIL_V(PropertyInfo()); - return PropertyInfo(); } PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const { @@ -357,6 +356,441 @@ int VisualScriptFunction::get_stack_size() const { } ////////////////////////////////////////// +/////////////////LISTS//////////////////// +////////////////////////////////////////// + +int VisualScriptLists::get_output_sequence_port_count() const { + if (sequenced) + return 1; + return 0; +} +bool VisualScriptLists::has_input_sequence_port() const { + return sequenced; +} + +String VisualScriptLists::get_output_sequence_port_text(int p_port) const { + return ""; +} + +int VisualScriptLists::get_input_value_port_count() const { + return inputports.size(); +} +int VisualScriptLists::get_output_value_port_count() const { + return outputports.size(); +} + +PropertyInfo VisualScriptLists::get_input_value_port_info(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo()); + + PropertyInfo pi; + pi.name = inputports[p_idx].name; + pi.type = inputports[p_idx].type; + return pi; +} +PropertyInfo VisualScriptLists::get_output_value_port_info(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, outputports.size(), PropertyInfo()); + + PropertyInfo pi; + pi.name = outputports[p_idx].name; + pi.type = outputports[p_idx].type; + return pi; +} + +bool VisualScriptLists::is_input_port_editable() const { + return ((flags & INPUT_EDITABLE) == INPUT_EDITABLE); +} +bool VisualScriptLists::is_input_port_name_editable() const { + return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE); +} +bool VisualScriptLists::is_input_port_type_editable() const { + return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE); +} + +bool VisualScriptLists::is_output_port_editable() const { + return ((flags & OUTPUT_EDITABLE) == OUTPUT_EDITABLE); +} +bool VisualScriptLists::is_output_port_name_editable() const { + return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE); +} +bool VisualScriptLists::is_output_port_type_editable() const { + return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE); +} + +// for the inspector +bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { + + if (p_name == "input_count" && is_input_port_editable()) { + + int new_argc = p_value; + int argc = inputports.size(); + if (argc == new_argc) + return true; + + inputports.resize(new_argc); + + for (int i = argc; i < new_argc; i++) { + inputports.write[i].name = "arg" + itos(i + 1); + inputports.write[i].type = Variant::NIL; + } + ports_changed_notify(); + _change_notify(); + return true; + } + if (String(p_name).begins_with("input_") && is_input_port_editable()) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; + ERR_FAIL_INDEX_V(idx, inputports.size(), false); + String what = String(p_name).get_slice("/", 1); + if (what == "type") { + + Variant::Type new_type = Variant::Type(int(p_value)); + inputports.write[idx].type = new_type; + ports_changed_notify(); + + return true; + } + + if (what == "name") { + + inputports.write[idx].name = p_value; + ports_changed_notify(); + return true; + } + } + + if (p_name == "output_count" && is_output_port_editable()) { + + int new_argc = p_value; + int argc = outputports.size(); + if (argc == new_argc) + return true; + + outputports.resize(new_argc); + + for (int i = argc; i < new_argc; i++) { + outputports.write[i].name = "arg" + itos(i + 1); + outputports.write[i].type = Variant::NIL; + } + ports_changed_notify(); + _change_notify(); + return true; + } + if (String(p_name).begins_with("output_") && is_output_port_editable()) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; + ERR_FAIL_INDEX_V(idx, outputports.size(), false); + String what = String(p_name).get_slice("/", 1); + if (what == "type") { + + Variant::Type new_type = Variant::Type(int(p_value)); + outputports.write[idx].type = new_type; + ports_changed_notify(); + + return true; + } + + if (what == "name") { + + outputports.write[idx].name = p_value; + ports_changed_notify(); + return true; + } + } + + if (p_name == "sequenced/sequenced") { + sequenced = p_value; + ports_changed_notify(); + return true; + } + + return false; +} +bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const { + + if (p_name == "input_count" && is_input_port_editable()) { + r_ret = inputports.size(); + return true; + } + if (String(p_name).begins_with("input_") && is_input_port_editable()) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; + ERR_FAIL_INDEX_V(idx, inputports.size(), false); + String what = String(p_name).get_slice("/", 1); + if (what == "type") { + r_ret = inputports[idx].type; + return true; + } + if (what == "name") { + r_ret = inputports[idx].name; + return true; + } + } + + if (p_name == "output_count" && is_output_port_editable()) { + r_ret = outputports.size(); + return true; + } + if (String(p_name).begins_with("output_") && is_output_port_editable()) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; + ERR_FAIL_INDEX_V(idx, outputports.size(), false); + String what = String(p_name).get_slice("/", 1); + if (what == "type") { + r_ret = outputports[idx].type; + return true; + } + if (what == "name") { + r_ret = outputports[idx].name; + return true; + } + } + + if (p_name == "sequenced/sequenced") { + r_ret = sequenced; + return true; + } + + return false; +} +void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const { + + if (is_input_port_editable()) { + p_list->push_back(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,256")); + String argt = "Any"; + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + argt += "," + Variant::get_type_name(Variant::Type(i)); + } + + for (int i = 0; i < inputports.size(); i++) { + p_list->push_back(PropertyInfo(Variant::INT, "input_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt)); + p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i + 1) + "/name")); + } + } + + if (is_output_port_editable()) { + p_list->push_back(PropertyInfo(Variant::INT, "output_count", PROPERTY_HINT_RANGE, "0,256")); + String argt = "Any"; + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + argt += "," + Variant::get_type_name(Variant::Type(i)); + } + + for (int i = 0; i < outputports.size(); i++) { + p_list->push_back(PropertyInfo(Variant::INT, "output_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt)); + p_list->push_back(PropertyInfo(Variant::STRING, "output_" + itos(i + 1) + "/name")); + } + } + p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced/sequenced")); +} + +// input data port interaction +void VisualScriptLists::add_input_data_port(Variant::Type p_type, const String &p_name, int p_index) { + + if (!is_input_port_editable()) + return; + + Port inp; + inp.name = p_name; + inp.type = p_type; + if (p_index >= 0) + inputports.insert(p_index, inp); + else + inputports.push_back(inp); + + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) { + + if (!is_input_port_type_editable()) + return; + + ERR_FAIL_INDEX(p_idx, inputports.size()); + + inputports.write[p_idx].type = p_type; + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) { + + if (!is_input_port_name_editable()) + return; + + ERR_FAIL_INDEX(p_idx, inputports.size()); + + inputports.write[p_idx].name = p_name; + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::remove_input_data_port(int p_argidx) { + + if (!is_input_port_editable()) + return; + + ERR_FAIL_INDEX(p_argidx, inputports.size()); + + inputports.remove(p_argidx); + + ports_changed_notify(); + _change_notify(); +} + +// output data port interaction +void VisualScriptLists::add_output_data_port(Variant::Type p_type, const String &p_name, int p_index) { + + if (!is_output_port_editable()) + return; + + Port out; + out.name = p_name; + out.type = p_type; + if (p_index >= 0) + outputports.insert(p_index, out); + else + outputports.push_back(out); + + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) { + + if (!is_output_port_type_editable()) + return; + + ERR_FAIL_INDEX(p_idx, outputports.size()); + + outputports.write[p_idx].type = p_type; + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) { + + if (!is_output_port_name_editable()) + return; + + ERR_FAIL_INDEX(p_idx, outputports.size()); + + outputports.write[p_idx].name = p_name; + ports_changed_notify(); + _change_notify(); +} +void VisualScriptLists::remove_output_data_port(int p_argidx) { + + if (!is_output_port_editable()) + return; + + ERR_FAIL_INDEX(p_argidx, outputports.size()); + + outputports.remove(p_argidx); + + ports_changed_notify(); + _change_notify(); +} + +// sequences +void VisualScriptLists::set_sequenced(bool p_enable) { + if (sequenced == p_enable) + return; + sequenced = p_enable; + ports_changed_notify(); +} +bool VisualScriptLists::is_sequenced() const { + return sequenced; +} + +VisualScriptLists::VisualScriptLists() { + // initialize + sequenced = false; + flags = 0; +} + +void VisualScriptLists::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_input_data_port", "type", "name", "index"), &VisualScriptLists::add_input_data_port); + ClassDB::bind_method(D_METHOD("set_input_data_port_name", "index", "name"), &VisualScriptLists::set_input_data_port_name); + ClassDB::bind_method(D_METHOD("set_input_data_port_type", "index", "type"), &VisualScriptLists::set_input_data_port_type); + ClassDB::bind_method(D_METHOD("remove_input_data_port", "index"), &VisualScriptLists::remove_input_data_port); + + ClassDB::bind_method(D_METHOD("add_output_data_port", "type", "name", "index"), &VisualScriptLists::add_output_data_port); + ClassDB::bind_method(D_METHOD("set_output_data_port_name", "index", "name"), &VisualScriptLists::set_output_data_port_name); + ClassDB::bind_method(D_METHOD("set_output_data_port_type", "index", "type"), &VisualScriptLists::set_output_data_port_type); + ClassDB::bind_method(D_METHOD("remove_output_data_port", "index"), &VisualScriptLists::remove_output_data_port); +} + +////////////////////////////////////////// +//////////////COMPOSEARRAY//////////////// +////////////////////////////////////////// + +int VisualScriptComposeArray::get_output_sequence_port_count() const { + if (sequenced) + return 1; + return 0; +} +bool VisualScriptComposeArray::has_input_sequence_port() const { + return sequenced; +} + +String VisualScriptComposeArray::get_output_sequence_port_text(int p_port) const { + return ""; +} + +int VisualScriptComposeArray::get_input_value_port_count() const { + return inputports.size(); +} +int VisualScriptComposeArray::get_output_value_port_count() const { + return 1; +} + +PropertyInfo VisualScriptComposeArray::get_input_value_port_info(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo()); + + PropertyInfo pi; + pi.name = inputports[p_idx].name; + pi.type = inputports[p_idx].type; + return pi; +} +PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) const { + PropertyInfo pi; + pi.name = "out"; + pi.type = Variant::ARRAY; + return pi; +} + +String VisualScriptComposeArray::get_caption() const { + return "Compose Array"; +} +String VisualScriptComposeArray::get_text() const { + return ""; +} + +class VisualScriptComposeArrayNode : public VisualScriptNodeInstance { +public: + int input_count = 0; + 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, Variant::CallError &r_error, String &r_error_str) { + + if (input_count > 0) { + Array arr; + for (int i = 0; i < input_count; i++) + arr.push_back((*p_inputs[i])); + Variant va = Variant(arr); + + *p_outputs[0] = va; + } + + return 0; + } +}; + +VisualScriptNodeInstance *VisualScriptComposeArray::instance(VisualScriptInstance *p_instance) { + + VisualScriptComposeArrayNode *instance = memnew(VisualScriptComposeArrayNode); + instance->input_count = inputports.size(); + return instance; +} + +VisualScriptComposeArray::VisualScriptComposeArray() { + // initialize stuff here + sequenced = false; + flags = INPUT_EDITABLE; +} + +////////////////////////////////////////// ////////////////OPERATOR////////////////// ////////////////////////////////////////// @@ -418,7 +852,7 @@ PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { { Variant::NIL, Variant::NIL } //OP_IN, }; - ERR_FAIL_INDEX_V(p_idx, Variant::OP_MAX, PropertyInfo()); + ERR_FAIL_INDEX_V(p_idx, 2, PropertyInfo()); PropertyInfo pinfo; pinfo.name = p_idx == 0 ? "A" : "B"; @@ -853,7 +1287,7 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { - if (instance->get_variable(variable, p_outputs[0]) == false) { + if (!instance->get_variable(variable, p_outputs[0])) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableGet not found in script: ") + "'" + String(variable) + "'"; return false; @@ -975,7 +1409,7 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { - if (instance->set_variable(variable, *p_inputs[0]) == false) { + if (!instance->set_variable(variable, *p_inputs[0])) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableSet not found in script: ") + "'" + String(variable) + "'"; @@ -2531,7 +2965,7 @@ String VisualScriptCustomNode::get_category() const { if (get_script_instance() && get_script_instance()->has_method("_get_category")) { return get_script_instance()->call("_get_category"); } - return "custom"; + return "Custom"; } class VisualScriptNodeInstanceCustomNode : public VisualScriptNodeInstance { @@ -3641,6 +4075,14 @@ VisualScriptDeconstruct::VisualScriptDeconstruct() { type = Variant::NIL; } +template <Variant::Type T> +static Ref<VisualScriptNode> create_node_deconst_typed(const String &p_name) { + Ref<VisualScriptDeconstruct> node; + node.instance(); + node->set_deconstruct_type(T); + return node; +} + void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("data/set_variable", create_node_generic<VisualScriptVariableSet>); @@ -3698,7 +4140,17 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/logic/in", create_op_node<Variant::OP_IN>); VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>); - VisualScriptLanguage::singleton->add_register_func("functions/deconstruct", create_node_generic<VisualScriptDeconstruct>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2), create_node_deconst_typed<Variant::Type::VECTOR2>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM2D), create_node_deconst_typed<Variant::Type::TRANSFORM2D>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PLANE), create_node_deconst_typed<Variant::Type::PLANE>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUAT), create_node_deconst_typed<Variant::Type::QUAT>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM), create_node_deconst_typed<Variant::Type::TRANSFORM>); + VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>); for (int i = 1; i < Variant::VARIANT_MAX; i++) { @@ -3708,18 +4160,18 @@ void register_visual_script_nodes() { for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { if (E->get().arguments.size() > 0) { - - String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + " ( "; + String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "("; for (int j = 0; j < E->get().arguments.size(); j++) { - if (j > 0) + if (j > 0) { name += ", "; - if (E->get().arguments.size() == 1) + } + if (E->get().arguments.size() == 1) { name += Variant::get_type_name(E->get().arguments[j].type); - else + } else { name += E->get().arguments[j].name; + } } - name += ") "; - + name += ")"; VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node); Pair<Variant::Type, MethodInfo> pair; pair.first = Variant::Type(i); diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index f7ac995816..c7354cb0d8 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -35,7 +35,7 @@ class VisualScriptFunction : public VisualScriptNode { - GDCLASS(VisualScriptFunction, VisualScriptNode) + GDCLASS(VisualScriptFunction, VisualScriptNode); struct Argument { String name; @@ -103,9 +103,106 @@ public: VisualScriptFunction(); }; +class VisualScriptLists : public VisualScriptNode { + + GDCLASS(VisualScriptLists, VisualScriptNode) + + struct Port { + String name; + Variant::Type type; + }; + +protected: + Vector<Port> inputports; + Vector<Port> outputports; + + enum { + OUTPUT_EDITABLE = 0x0001, + OUTPUT_NAME_EDITABLE = 0x0002, + OUTPUT_TYPE_EDITABLE = 0x0004, + INPUT_EDITABLE = 0x0008, + INPUT_NAME_EDITABLE = 0x000F, + INPUT_TYPE_EDITABLE = 0x0010, + }; + + int flags; + + bool sequenced; + + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + +public: + virtual bool is_output_port_editable() const; + virtual bool is_output_port_name_editable() const; + virtual bool is_output_port_type_editable() const; + + virtual bool is_input_port_editable() const; + virtual bool is_input_port_name_editable() const; + virtual bool is_input_port_type_editable() const; + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + virtual String get_output_sequence_port_text(int p_port) const; + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const = 0; + virtual String get_text() const = 0; + virtual String get_category() const = 0; + + void add_input_data_port(Variant::Type p_type, const String &p_name, int p_index = -1); + void set_input_data_port_type(int p_idx, Variant::Type p_type); + void set_input_data_port_name(int p_idx, const String &p_name); + void remove_input_data_port(int p_argidx); + + void add_output_data_port(Variant::Type p_type, const String &p_name, int p_index = -1); + void set_output_data_port_type(int p_idx, Variant::Type p_type); + void set_output_data_port_name(int p_idx, const String &p_name); + void remove_output_data_port(int p_argidx); + + void set_sequenced(bool p_enable); + bool is_sequenced() const; + + VisualScriptLists(); +}; + +class VisualScriptComposeArray : public VisualScriptLists { + + GDCLASS(VisualScriptComposeArray, VisualScriptLists) + +public: + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + virtual String get_output_sequence_port_text(int p_port) const; + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const { return "functions"; } + + virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); + + VisualScriptComposeArray(); +}; + class VisualScriptOperator : public VisualScriptNode { - GDCLASS(VisualScriptOperator, VisualScriptNode) + GDCLASS(VisualScriptOperator, VisualScriptNode); Variant::Type typed; Variant::Operator op; @@ -141,7 +238,7 @@ public: class VisualScriptSelect : public VisualScriptNode { - GDCLASS(VisualScriptSelect, VisualScriptNode) + GDCLASS(VisualScriptSelect, VisualScriptNode); Variant::Type typed; @@ -174,7 +271,7 @@ public: class VisualScriptVariableGet : public VisualScriptNode { - GDCLASS(VisualScriptVariableGet, VisualScriptNode) + GDCLASS(VisualScriptVariableGet, VisualScriptNode); StringName variable; @@ -207,7 +304,7 @@ public: class VisualScriptVariableSet : public VisualScriptNode { - GDCLASS(VisualScriptVariableSet, VisualScriptNode) + GDCLASS(VisualScriptVariableSet, VisualScriptNode); StringName variable; @@ -240,7 +337,7 @@ public: class VisualScriptConstant : public VisualScriptNode { - GDCLASS(VisualScriptConstant, VisualScriptNode) + GDCLASS(VisualScriptConstant, VisualScriptNode); Variant::Type type; Variant value; @@ -277,7 +374,7 @@ public: class VisualScriptPreload : public VisualScriptNode { - GDCLASS(VisualScriptPreload, VisualScriptNode) + GDCLASS(VisualScriptPreload, VisualScriptNode); Ref<Resource> preload; @@ -309,7 +406,7 @@ public: class VisualScriptIndexGet : public VisualScriptNode { - GDCLASS(VisualScriptIndexGet, VisualScriptNode) + GDCLASS(VisualScriptIndexGet, VisualScriptNode); public: virtual int get_output_sequence_port_count() const; @@ -333,7 +430,7 @@ public: class VisualScriptIndexSet : public VisualScriptNode { - GDCLASS(VisualScriptIndexSet, VisualScriptNode) + GDCLASS(VisualScriptIndexSet, VisualScriptNode); public: virtual int get_output_sequence_port_count() const; @@ -357,7 +454,7 @@ public: class VisualScriptGlobalConstant : public VisualScriptNode { - GDCLASS(VisualScriptGlobalConstant, VisualScriptNode) + GDCLASS(VisualScriptGlobalConstant, VisualScriptNode); int index; @@ -388,7 +485,7 @@ public: class VisualScriptClassConstant : public VisualScriptNode { - GDCLASS(VisualScriptClassConstant, VisualScriptNode) + GDCLASS(VisualScriptClassConstant, VisualScriptNode); StringName base_type; StringName name; @@ -425,7 +522,7 @@ public: class VisualScriptBasicTypeConstant : public VisualScriptNode { - GDCLASS(VisualScriptBasicTypeConstant, VisualScriptNode) + GDCLASS(VisualScriptBasicTypeConstant, VisualScriptNode); Variant::Type type; StringName name; @@ -463,7 +560,8 @@ public: class VisualScriptMathConstant : public VisualScriptNode { - GDCLASS(VisualScriptMathConstant, VisualScriptNode) + GDCLASS(VisualScriptMathConstant, VisualScriptNode); + public: enum MathConstant { MATH_CONSTANT_ONE, @@ -512,7 +610,7 @@ VARIANT_ENUM_CAST(VisualScriptMathConstant::MathConstant) class VisualScriptEngineSingleton : public VisualScriptNode { - GDCLASS(VisualScriptEngineSingleton, VisualScriptNode) + GDCLASS(VisualScriptEngineSingleton, VisualScriptNode); String singleton; @@ -545,7 +643,7 @@ public: class VisualScriptSceneNode : public VisualScriptNode { - GDCLASS(VisualScriptSceneNode, VisualScriptNode) + GDCLASS(VisualScriptSceneNode, VisualScriptNode); NodePath path; @@ -580,7 +678,7 @@ public: class VisualScriptSceneTree : public VisualScriptNode { - GDCLASS(VisualScriptSceneTree, VisualScriptNode) + GDCLASS(VisualScriptSceneTree, VisualScriptNode); protected: virtual void _validate_property(PropertyInfo &property) const; @@ -610,7 +708,7 @@ public: class VisualScriptResourcePath : public VisualScriptNode { - GDCLASS(VisualScriptResourcePath, VisualScriptNode) + GDCLASS(VisualScriptResourcePath, VisualScriptNode); String path; @@ -642,7 +740,7 @@ public: class VisualScriptSelf : public VisualScriptNode { - GDCLASS(VisualScriptSelf, VisualScriptNode) + GDCLASS(VisualScriptSelf, VisualScriptNode); protected: static void _bind_methods(); @@ -671,7 +769,7 @@ public: class VisualScriptCustomNode : public VisualScriptNode { - GDCLASS(VisualScriptCustomNode, VisualScriptNode) + GDCLASS(VisualScriptCustomNode, VisualScriptNode); protected: static void _bind_methods(); @@ -719,7 +817,7 @@ VARIANT_ENUM_CAST(VisualScriptCustomNode::StartMode); class VisualScriptSubCall : public VisualScriptNode { - GDCLASS(VisualScriptSubCall, VisualScriptNode) + GDCLASS(VisualScriptSubCall, VisualScriptNode); protected: static void _bind_methods(); @@ -747,7 +845,7 @@ public: class VisualScriptComment : public VisualScriptNode { - GDCLASS(VisualScriptComment, VisualScriptNode) + GDCLASS(VisualScriptComment, VisualScriptNode); String title; String description; @@ -788,7 +886,7 @@ public: class VisualScriptConstructor : public VisualScriptNode { - GDCLASS(VisualScriptConstructor, VisualScriptNode) + GDCLASS(VisualScriptConstructor, VisualScriptNode); Variant::Type type; MethodInfo constructor; @@ -824,7 +922,7 @@ public: class VisualScriptLocalVar : public VisualScriptNode { - GDCLASS(VisualScriptLocalVar, VisualScriptNode) + GDCLASS(VisualScriptLocalVar, VisualScriptNode); StringName name; Variant::Type type; @@ -860,7 +958,7 @@ public: class VisualScriptLocalVarSet : public VisualScriptNode { - GDCLASS(VisualScriptLocalVarSet, VisualScriptNode) + GDCLASS(VisualScriptLocalVarSet, VisualScriptNode); StringName name; Variant::Type type; @@ -897,7 +995,8 @@ public: class VisualScriptInputAction : public VisualScriptNode { - GDCLASS(VisualScriptInputAction, VisualScriptNode) + GDCLASS(VisualScriptInputAction, VisualScriptNode); + public: enum Mode { MODE_PRESSED, @@ -944,7 +1043,7 @@ VARIANT_ENUM_CAST(VisualScriptInputAction::Mode) class VisualScriptDeconstruct : public VisualScriptNode { - GDCLASS(VisualScriptDeconstruct, VisualScriptNode) + GDCLASS(VisualScriptDeconstruct, VisualScriptNode); struct Element { StringName name; diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index 9942d5baa6..42d4c5e209 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -87,38 +87,17 @@ void VisualScriptPropertySelector::_update_search() { TreeItem *root = search_options->create_item(); bool found = false; + StringName base = base_type; + List<StringName> base_list; + while (base) { + base_list.push_back(base); + base = ClassDB::get_parent_class_nocheck(base); + } - if (properties) { - + for (List<StringName>::Element *E = base_list.front(); E; E = E->next()) { + List<MethodInfo> methods; List<PropertyInfo> props; - - if (instance) { - instance->get_property_list(&props, true); - } else if (type != Variant::NIL) { - Variant v; - Variant::CallError ce; - v = Variant::construct(type, NULL, 0, ce); - - v.get_property_list(&props); - } else { - - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - - props.push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - Object::cast_to<Script>(obj)->get_script_property_list(&props); - } - - StringName base = base_type; - while (base) { - props.push_back(PropertyInfo(Variant::NIL, base, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - ClassDB::get_property_list(base, &props, true); - base = ClassDB::get_parent_class_nocheck(base); - } - } - TreeItem *category = NULL; - Ref<Texture> type_icons[Variant::VARIANT_MAX] = { Control::get_icon("Variant", "EditorIcons"), Control::get_icon("bool", "EditorIcons"), @@ -148,90 +127,165 @@ void VisualScriptPropertySelector::_update_search() { Control::get_icon("PoolVector3Array", "EditorIcons"), Control::get_icon("PoolColorArray", "EditorIcons") }; - - if (!seq_connect && visual_script_generic == false) { - get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); - get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); - get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); - get_visual_node_names("operators/compare/", Set<String>(), found, root, search_box); - if (type == Variant::INT) { - get_visual_node_names("operators/bitwise/", Set<String>(), found, root, search_box); + { + String b = String(E->get()); + category = search_options->create_item(root); + if (category) { + category->set_text(0, b.replace_first("*", "")); + category->set_selectable(0, false); + Ref<Texture> icon; + String rep = b.replace("*", ""); + icon = EditorNode::get_singleton()->get_class_icon(rep); + category->set_icon(0, icon); } - if (type == Variant::BOOL) { - get_visual_node_names("operators/logic/", Set<String>(), found, root, search_box); + } + if (properties || seq_connect) { + if (instance) { + instance->get_property_list(&props, true); + } else { + Object *obj = ObjectDB::get_instance(script); + if (Object::cast_to<Script>(obj)) { + Object::cast_to<Script>(obj)->get_script_property_list(&props); + } else { + ClassDB::get_property_list(E->get(), &props, true); + } } - if (type == Variant::BOOL || type == Variant::INT || type == Variant::REAL || type == Variant::VECTOR2 || type == Variant::VECTOR3) { - get_visual_node_names("operators/math/", Set<String>(), found, root, search_box); + for (List<PropertyInfo>::Element *F = props.front(); F; F = F->next()) { + if (!(F->get().usage & PROPERTY_USAGE_EDITOR) && !(F->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) + continue; + + if (type_filter.size() && type_filter.find(F->get().type) == -1) + continue; + + // capitalize() also converts underscore to space, we'll match again both possible styles + String get_text_raw = String(vformat(TTR("Get %s"), F->get().name)); + String get_text = get_text_raw.capitalize(); + String set_text_raw = String(vformat(TTR("Set %s"), F->get().name)); + String set_text = set_text_raw.capitalize(); + String input = search_box->get_text().capitalize(); + + if (input == String() || get_text_raw.findn(input) != -1 || get_text.findn(input) != -1) { + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, get_text); + item->set_metadata(0, F->get().name); + item->set_icon(0, type_icons[F->get().type]); + item->set_metadata(1, "get"); + item->set_collapsed(1); + item->set_selectable(0, true); + item->set_selectable(1, false); + item->set_selectable(2, false); + item->set_metadata(2, connecting); + } + + if (input == String() || set_text_raw.findn(input) != -1 || set_text.findn(input) != -1) { + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, set_text); + item->set_metadata(0, F->get().name); + item->set_icon(0, type_icons[F->get().type]); + item->set_metadata(1, "set"); + item->set_selectable(0, true); + item->set_selectable(1, false); + item->set_selectable(2, false); + item->set_metadata(2, connecting); + } } } + { + if (type != Variant::NIL) { + Variant v; + Variant::CallError ce; + v = Variant::construct(type, NULL, 0, ce); + v.get_method_list(&methods); + } else { - for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - if (E->get().usage == PROPERTY_USAGE_CATEGORY) { - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused + Object *obj = ObjectDB::get_instance(script); + if (Object::cast_to<Script>(obj)) { + Object::cast_to<Script>(obj)->get_script_method_list(&methods); } - category = search_options->create_item(root); - category->set_text(0, E->get().name); - category->set_selectable(0, false); - Ref<Texture> icon; - if (E->get().name == "Script Variables") { - icon = get_icon("Script", "EditorIcons"); - } else { - icon = EditorNode::get_singleton()->get_class_icon(E->get().name); - } - category->set_icon(0, icon); - continue; + ClassDB::get_method_list(E->get(), &methods, true, true); } + } + for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) { + + String name = M->get().name.get_slice(":", 0); + if (name.begins_with("_") && !(M->get().flags & METHOD_FLAG_VIRTUAL)) + continue; - if (!(E->get().usage & PROPERTY_USAGE_EDITOR) && !(E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) + if (virtuals_only && !(M->get().flags & METHOD_FLAG_VIRTUAL)) continue; - if (type_filter.size() && type_filter.find(E->get().type) == -1) + if (!virtuals_only && (M->get().flags & METHOD_FLAG_VIRTUAL)) continue; - String get_text_raw = String(vformat(TTR("Get %s"), E->get().name)); - String get_text = get_text_raw.capitalize(); - - String set_text_raw = String(vformat(TTR("Set %s"), E->get().name)); - String set_text = set_text_raw.capitalize(); - String input = search_box->get_text().capitalize(); - if (input == String() || - get_text_raw.findn(input) != -1 || - get_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, get_text); - item->set_metadata(0, E->get().name); - item->set_icon(0, type_icons[E->get().type]); - item->set_metadata(1, "get"); - item->set_collapsed(1); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); + MethodInfo mi = M->get(); + String desc_arguments; + if (mi.arguments.size() > 0) { + desc_arguments = "("; + for (int i = 0; i < mi.arguments.size(); i++) { + + if (i > 0) { + desc_arguments += ", "; + } + if (mi.arguments[i].type == Variant::NIL) { + desc_arguments += "var"; + } else if (mi.arguments[i].name.find(":") != -1) { + desc_arguments += mi.arguments[i].name.get_slice(":", 1); + mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); + } else { + desc_arguments += Variant::get_type_name(mi.arguments[i].type); + } + } + desc_arguments += ")"; } + String desc_raw = mi.name + desc_arguments; + String desc = desc_raw.capitalize().replace("( ", "("); - if (input == String() || - set_text_raw.findn(input) != -1 && - set_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, set_text); - item->set_metadata(0, E->get().name); - item->set_icon(0, type_icons[E->get().type]); - item->set_metadata(1, "set"); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); + if (search_box->get_text() != String() && + name.findn(search_box->get_text()) == -1 && + desc.findn(search_box->get_text()) == -1 && + desc_raw.findn(search_box->get_text()) == -1) { + continue; } + + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, desc); + item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); + item->set_metadata(0, name); + item->set_selectable(0, true); + + item->set_metadata(1, "method"); + item->set_collapsed(1); + item->set_selectable(1, false); + + item->set_selectable(2, false); + item->set_metadata(2, connecting); } if (category && category->get_children() == NULL) { memdelete(category); //old category was unused } } + if (properties) { + if (!seq_connect && !visual_script_generic) { + get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); + get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); + get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); + get_visual_node_names("functions/deconstruct/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); + get_visual_node_names("operators/compare/", Set<String>(), found, root, search_box); + if (type == Variant::INT) { + get_visual_node_names("operators/bitwise/", Set<String>(), found, root, search_box); + } + if (type == Variant::BOOL) { + get_visual_node_names("operators/logic/", Set<String>(), found, root, search_box); + } + if (type == Variant::BOOL || type == Variant::INT || type == Variant::REAL || type == Variant::VECTOR2 || type == Variant::VECTOR3) { + get_visual_node_names("operators/math/", Set<String>(), found, root, search_box); + } + } + } - if (seq_connect == true && visual_script_generic == false) { + if (seq_connect && !visual_script_generic) { String text = search_box->get_text(); create_visualscript_item(String("VisualScriptCondition"), root, text, String("Condition")); create_visualscript_item(String("VisualScriptSwitch"), root, text, String("Switch")); @@ -243,122 +297,16 @@ void VisualScriptPropertySelector::_update_search() { get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); } - if (visual_script_generic) { + if ((properties || seq_connect) && visual_script_generic) { get_visual_node_names("", Set<String>(), found, root, search_box); } - List<MethodInfo> methods; - - if (type != Variant::NIL) { - Variant v; - Variant::CallError ce; - v = Variant::construct(type, NULL, 0, ce); - v.get_method_list(&methods); - } else { - - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - - methods.push_back(MethodInfo("*Script Methods")); - Object::cast_to<Script>(obj)->get_script_method_list(&methods); - } - - StringName base = base_type; - while (base) { - methods.push_back(MethodInfo("*" + String(base))); - ClassDB::get_method_list(base, &methods, true, true); - base = ClassDB::get_parent_class_nocheck(base); - } - } - TreeItem *category = NULL; - bool script_methods = false; - - for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().name.begins_with("*")) { - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - category = search_options->create_item(root); - category->set_text(0, E->get().name.replace_first("*", "")); - category->set_selectable(0, false); - - Ref<Texture> icon; - script_methods = false; - String rep = E->get().name.replace("*", ""); - if (E->get().name == "*Script Methods") { - icon = get_icon("Script", "EditorIcons"); - script_methods = true; - } else { - icon = EditorNode::get_singleton()->get_class_icon(rep); - } - category->set_icon(0, icon); - - continue; - } - - String name = E->get().name.get_slice(":", 0); - if (!script_methods && name.begins_with("_") && !(E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - if (virtuals_only && !(E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - if (!virtuals_only && (E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - MethodInfo mi = E->get(); - String desc = mi.name.capitalize() + " ("; - - if (search_box->get_text() != String() && - name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1) - continue; - - TreeItem *item = search_options->create_item(category ? category : root); - - for (int i = 0; i < mi.arguments.size(); i++) { - - if (i > 0) - desc += ", "; - - if (mi.arguments[i].type == Variant::NIL) - desc += "var"; - else if (mi.arguments[i].name.find(":") != -1) { - desc += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else - desc += Variant::get_type_name(mi.arguments[i].type); - } - - desc += ")"; - - item->set_text(0, desc); - item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); - item->set_metadata(0, name); - item->set_selectable(0, true); - - item->set_metadata(1, "method"); - item->set_collapsed(1); - item->set_selectable(1, false); - - item->set_selectable(2, false); - item->set_metadata(2, connecting); - - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - } - TreeItem *selected_item = search_options->search_item_text(search_box->get_text()); if (!found && selected_item != NULL) { selected_item->select(0); found = true; } - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - get_ok()->set_disabled(root->get_children() == NULL); } @@ -377,7 +325,7 @@ void VisualScriptPropertySelector::create_visualscript_item(const String &name, } } -void VisualScriptPropertySelector::get_visual_node_names(const String &root_filter, const Set<String> &filter, bool &found, TreeItem *const root, LineEdit *const search_box) { +void VisualScriptPropertySelector::get_visual_node_names(const String &root_filter, const Set<String> &p_modifiers, bool &found, TreeItem *const root, LineEdit *const search_box) { Map<String, TreeItem *> path_cache; List<String> fnodes; @@ -388,40 +336,67 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt continue; } Vector<String> path = E->get().split("/"); - bool is_filter = false; - for (Set<String>::Element *E = filter.front(); E; E = E->next()) { - if (path.size() >= 2 && path[1].findn(E->get()) != -1) { - is_filter = true; + + // check if the name has the filter + bool in_filter = false; + Vector<String> tx_filters = search_box->get_text().split(" "); + for (int i = 0; i < tx_filters.size(); i++) { + if (tx_filters[i] == "") { + in_filter = true; + } else { + in_filter = false; + } + if (E->get().findn(tx_filters[i]) != -1) { + in_filter = true; break; } } - if (is_filter == true) { + if (!in_filter) { continue; } - if (search_box->get_text() != String() && E->get().findn(search_box->get_text()) == -1) { + bool in_modifier = false | p_modifiers.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; + } + if (!in_modifier) { continue; } + TreeItem *item = search_options->create_item(root); - VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); + Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(E->get()); + Ref<VisualScriptOperator> vnode_operator = vnode; String type_name; - if (vnode_operator != NULL) { + if (vnode_operator.is_valid()) { String type; if (path.size() >= 2) { type = path[1]; } type_name = type.capitalize() + " "; } - VisualScriptFunctionCall *vnode_function_call = Object::cast_to<VisualScriptFunctionCall>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); - if (vnode_function_call != NULL) { + Ref<VisualScriptFunctionCall> vnode_function_call = vnode; + if (vnode_function_call.is_valid()) { String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); type_name = basic_type.capitalize() + " "; } - VisualScriptBuiltinFunc *vnode_builtin_function_call = Object::cast_to<VisualScriptBuiltinFunc>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); - if (vnode_builtin_function_call != NULL) { - type_name = "Builtin "; + Ref<VisualScriptConstructor> vnode_constructor = vnode; + if (vnode_constructor.is_valid()) { + type_name = "Construct "; + } + Ref<VisualScriptDeconstruct> vnode_deconstruct = vnode; + if (vnode_deconstruct.is_valid()) { + type_name = "Deconstruct "; } - item->set_text(0, type_name + path[path.size() - 1].capitalize()); + Vector<String> desc = path[path.size() - 1].replace("(", " ").replace(")", " ").replace(",", " ").split(" "); + for (int i = 0; i < desc.size(); i++) { + desc.write[i] = desc[i].capitalize(); + if (desc[i].ends_with(",")) { + desc.write[i] = desc[i].replace(",", ", "); + } + } + + item->set_text(0, type_name + String("").join(desc)); item->set_icon(0, get_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); @@ -452,7 +427,7 @@ void VisualScriptPropertySelector::_item_selected() { String name = item->get_metadata(0); String class_type; - if (type) { + if (type != Variant::NIL) { class_type = Variant::get_type_name(type); } else { @@ -481,23 +456,23 @@ void VisualScriptPropertySelector::_item_selected() { while (at_class != String()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { - if (E->get().methods[i].name == name) { - text = E->get().methods[i].description; + Map<String, DocData::ClassDoc>::Element *C = dd->class_list.find(at_class); + if (C) { + for (int i = 0; i < C->get().methods.size(); i++) { + if (C->get().methods[i].name == name) { + text = C->get().methods[i].description; } } } at_class = ClassDB::get_parent_class_nocheck(at_class); } - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { + Map<String, DocData::ClassDoc>::Element *T = dd->class_list.find(class_type); + if (T) { + for (int i = 0; i < T->get().methods.size(); i++) { Vector<String> functions = name.rsplit("/", false, 1); - if (E->get().methods[i].name == functions[functions.size() - 1]) { - text = E->get().methods[i].description; + if (T->get().methods[i].name == functions[functions.size() - 1]) { + text = T->get().methods[i].description; } } } @@ -507,26 +482,26 @@ void VisualScriptPropertySelector::_item_selected() { if (names->find(name) != NULL) { Ref<VisualScriptOperator> operator_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (operator_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(operator_node->get_class_name()); - if (E) { + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(operator_node->get_class_name()); + if (F) { text = Variant::get_operator_name(operator_node->get_operator()); } } Ref<VisualScriptTypeCast> typecast_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (typecast_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(typecast_node->get_class_name()); - if (E) { - text = E->get().description; + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(typecast_node->get_class_name()); + if (F) { + text = F->get().description; } } Ref<VisualScriptBuiltinFunc> builtin_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (builtin_node.is_valid()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(builtin_node->get_class_name()); - if (E) { - for (int i = 0; i < E->get().constants.size(); i++) { - if (E->get().constants[i].value.to_int() == int(builtin_node->get_func())) { - text = E->get().constants[i].description; + Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(builtin_node->get_class_name()); + if (F) { + for (int i = 0; i < F->get().constants.size(); i++) { + if (F->get().constants[i].value.to_int() == int(builtin_node->get_func())) { + text = F->get().constants[i].description; } } } @@ -549,7 +524,7 @@ void VisualScriptPropertySelector::_notification(int p_what) { } } -void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting) { +void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting, bool clear_text) { base_type = p_base; selected = p_current; @@ -560,7 +535,10 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_ virtuals_only = p_virtuals_only; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); connecting = p_connecting; @@ -571,18 +549,22 @@ void VisualScriptPropertySelector::set_type_filter(const Vector<Variant::Type> & type_filter = p_type_filter; } -void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting) { +void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting, bool clear_text) { base_type = p_base; selected = p_current; type = Variant::NIL; script = 0; properties = true; + visual_script_generic = false; instance = NULL; virtuals_only = p_virtuals_only; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); seq_connect = p_seq_connect; connecting = p_connecting; @@ -590,7 +572,7 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c _update_search(); } -void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const String &p_current, const bool p_connecting) { +void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const String &p_current, const bool p_connecting, bool clear_text) { ERR_FAIL_COND(p_script.is_null()); base_type = p_script->get_instance_base_type(); @@ -598,11 +580,15 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip type = Variant::NIL; script = p_script->get_instance_id(); properties = true; + visual_script_generic = false; instance = NULL; virtuals_only = false; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -610,18 +596,22 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip _update_search(); } -void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const String &p_current, const bool p_connecting) { +void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const String &p_current, const bool p_connecting, bool clear_text) { ERR_FAIL_COND(p_type == Variant::NIL); base_type = ""; selected = p_current; type = p_type; script = 0; properties = true; + visual_script_generic = false; instance = NULL; virtuals_only = false; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -629,17 +619,21 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, _update_search(); } -void VisualScriptPropertySelector::select_from_action(const String &p_type, const String &p_current, const bool p_connecting) { +void VisualScriptPropertySelector::select_from_action(const String &p_type, const String &p_current, const bool p_connecting, bool clear_text) { base_type = p_type; selected = p_current; type = Variant::NIL; script = 0; properties = false; + visual_script_generic = false; instance = NULL; virtuals_only = false; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); seq_connect = true; connecting = p_connecting; @@ -647,17 +641,21 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons _update_search(); } -void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const String &p_current, const bool p_connecting) { - base_type = ""; +void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const String &p_current, const bool p_connecting, const String &p_basetype, bool clear_text) { + base_type = p_basetype; selected = p_current; type = Variant::NIL; script = 0; properties = true; + visual_script_generic = false; instance = p_instance; virtuals_only = false; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -665,7 +663,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons _update_search(); } -void VisualScriptPropertySelector::select_from_visual_script(const String &p_base, const bool p_connecting) { +void VisualScriptPropertySelector::select_from_visual_script(const String &p_base, const bool p_connecting, bool clear_text) { base_type = p_base; selected = ""; type = Variant::NIL; @@ -675,7 +673,10 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas instance = NULL; virtuals_only = false; show_window(.5f); - search_box->set_text(""); + if (clear_text) + search_box->set_text(""); + else + search_box->select_all(); search_box->grab_focus(); connecting = p_connecting; @@ -686,7 +687,7 @@ void VisualScriptPropertySelector::show_window(float p_screen_ratio) { Rect2 rect; Point2 window_size = get_viewport_rect().size; rect.size = (window_size * p_screen_ratio).floor(); - rect.size.x = rect.size.x / 1.25f; + rect.size.x = rect.size.x / 2.2f; rect.position = ((window_size - rect.size) / 2.0f).floor(); popup(rect); } @@ -721,6 +722,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() { search_options->set_hide_root(true); search_options->set_hide_folding(true); virtuals_only = false; + seq_connect = false; help_bit = memnew(EditorHelpBit); vbc->add_margin_child(TTR("Description:"), help_bit); help_bit->connect("request_hide", this, "_closed"); diff --git a/modules/visual_script/visual_script_property_selector.h b/modules/visual_script/visual_script_property_selector.h index 917ef9ae6d..13ce9bdca2 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -36,7 +36,7 @@ #include "scene/gui/rich_text_label.h" class VisualScriptPropertySelector : public ConfirmationDialog { - GDCLASS(VisualScriptPropertySelector, ConfirmationDialog) + GDCLASS(VisualScriptPropertySelector, ConfirmationDialog); LineEdit *search_box; Tree *search_options; @@ -63,8 +63,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog { ObjectID script; Object *instance; bool virtuals_only; - - bool seq_connect = false; + bool seq_connect; void _item_selected(); @@ -75,13 +74,13 @@ protected: static void _bind_methods(); public: - void select_method_from_base_type(const String &p_base, const String &p_current = "", const bool p_virtuals_only = false, const bool p_connecting = true); - void select_from_base_type(const String &p_base, const String &p_current = "", bool p_virtuals_only = false, bool p_seq_connect = false, const bool p_connecting = true); - void select_from_script(const Ref<Script> &p_script, const String &p_current = "", const bool p_connecting = true); - void select_from_basic_type(Variant::Type p_type, const String &p_current = "", const bool p_connecting = true); - void select_from_action(const String &p_type, const String &p_current = "", const bool p_connecting = true); - void select_from_instance(Object *p_instance, const String &p_current = "", const bool p_connecting = true); - void select_from_visual_script(const String &p_base, const bool p_connecting = true); + void select_method_from_base_type(const String &p_base, const String &p_current = "", const bool p_virtuals_only = false, const bool p_connecting = true, bool clear_text = true); + void select_from_base_type(const String &p_base, const String &p_current = "", bool p_virtuals_only = false, bool p_seq_connect = false, const bool p_connecting = true, bool clear_text = true); + void select_from_script(const Ref<Script> &p_script, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); + void select_from_basic_type(Variant::Type p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); + void select_from_action(const String &p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true); + void select_from_instance(Object *p_instance, const String &p_current = "", const bool p_connecting = true, const String &p_basetype = "", bool clear_text = true); + void select_from_visual_script(const String &p_base, const bool p_connecting = true, bool clear_text = true); void show_window(float p_screen_ratio); diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index a21fff67fe..ebd0f0b3cb 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -431,7 +431,6 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string - } else { } } } diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h index 4009240581..647f2b1e2e 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-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -35,7 +35,8 @@ class VisualScriptYield : public VisualScriptNode { - GDCLASS(VisualScriptYield, VisualScriptNode) + GDCLASS(VisualScriptYield, VisualScriptNode); + public: enum YieldMode { YIELD_RETURN, @@ -84,7 +85,8 @@ VARIANT_ENUM_CAST(VisualScriptYield::YieldMode) class VisualScriptYieldSignal : public VisualScriptNode { - GDCLASS(VisualScriptYieldSignal, VisualScriptNode) + GDCLASS(VisualScriptYieldSignal, VisualScriptNode); + public: enum CallMode { CALL_MODE_SELF, |