Browse Source

Merge pull request #50475 from akien-mga/3.x-cherrypicks

Rémi Verschelde 4 years ago
parent
commit
d07fb152d9
31 changed files with 281 additions and 55 deletions
  1. 12 1
      doc/classes/BaseButton.xml
  2. 2 2
      doc/classes/CPUParticles.xml
  3. 1 1
      doc/classes/CPUParticles2D.xml
  4. 1 1
      doc/classes/ParticlesMaterial.xml
  5. 1 0
      doc/classes/VisualShaderNode.xml
  6. 2 0
      modules/visual_script/doc_classes/VisualScriptExpression.xml
  7. 2 0
      modules/visual_script/doc_classes/VisualScriptFunction.xml
  8. 22 0
      modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
  9. 5 0
      modules/visual_script/doc_classes/VisualScriptFunctionState.xml
  10. 3 0
      modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
  11. 2 0
      modules/visual_script/doc_classes/VisualScriptIndexGet.xml
  12. 2 0
      modules/visual_script/doc_classes/VisualScriptIndexSet.xml
  13. 8 0
      modules/visual_script/doc_classes/VisualScriptInputAction.xml
  14. 8 0
      modules/visual_script/doc_classes/VisualScriptLists.xml
  15. 3 0
      modules/visual_script/doc_classes/VisualScriptOperator.xml
  16. 13 0
      modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
  17. 25 0
      modules/visual_script/doc_classes/VisualScriptPropertySet.xml
  18. 2 0
      modules/visual_script/doc_classes/VisualScriptSceneTree.xml
  19. 3 0
      modules/visual_script/doc_classes/VisualScriptSubCall.xml
  20. 4 0
      modules/visual_script/doc_classes/VisualScriptTypeCast.xml
  21. 7 0
      modules/visual_script/doc_classes/VisualScriptYield.xml
  22. 9 0
      modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
  23. 6 1
      platform/iphone/export/export.cpp
  24. 2 0
      platform/iphone/plugin/godot_plugin_config.h
  25. 113 31
      platform/x11/os_x11.cpp
  26. 0 4
      scene/2d/cpu_particles_2d.cpp
  27. 0 4
      scene/3d/cpu_particles.cpp
  28. 13 0
      scene/gui/base_button.cpp
  29. 2 1
      scene/gui/base_button.h
  30. 7 4
      scene/main/node.cpp
  31. 1 5
      scene/resources/particles_material.cpp

+ 12 - 1
doc/classes/BaseButton.xml

@@ -39,6 +39,16 @@
 				Returns [code]true[/code] if the mouse has entered the button and has not left it yet.
 			</description>
 		</method>
+		<method name="set_pressed_no_signal">
+			<return type="void">
+			</return>
+			<argument index="0" name="pressed" type="bool">
+			</argument>
+			<description>
+				Changes the [member pressed] state of the button, without emitting [signal toggled]. Use when you just want to change the state of the button without sending the pressed event (e.g. when initializing scene). Only works if [member toggle_mode] is [code]true[/code].
+				[b]Note:[/b] This method doesn't unpress other buttons in its button [member group].
+			</description>
+		</method>
 	</methods>
 	<members>
 		<member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode" default="1">
@@ -63,7 +73,8 @@
 			[b]Note:[/b] This property only affects the button's visual appearance. Signals will be emitted at the same moment regardless of this property's value.
 		</member>
 		<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
-			If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active).
+			If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code].
+			[b]Note:[/b] Setting [member pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal].
 		</member>
 		<member name="shortcut" type="ShortCut" setter="set_shortcut" getter="get_shortcut">
 			[ShortCut] associated to the button.

+ 2 - 2
doc/classes/CPUParticles.xml

@@ -150,10 +150,10 @@
 			Animation speed randomness ratio.
 		</member>
 		<member name="color" type="Color" setter="set_color" getter="get_color" default="Color( 1, 1, 1, 1 )">
-			Unused for 3D particles.
+			Each particle's initial color. To have particle display color in a [SpatialMaterial] make sure to set [member SpatialMaterial.vertex_color_use_as_albedo] to [code]true[/code].
 		</member>
 		<member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp">
-			Unused for 3D particles.
+			Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]).
 		</member>
 		<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
 			The rate at which particles lose velocity.

+ 1 - 1
doc/classes/CPUParticles2D.xml

@@ -154,7 +154,7 @@
 			Each particle's initial color. If [member texture] is defined, it will be multiplied by this color.
 		</member>
 		<member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp">
-			Each particle's color will vary along this [Gradient].
+			Each particle's color will vary along this [Gradient] (multiplied with [member color]).
 		</member>
 		<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
 			The rate at which particles lose velocity.

+ 1 - 1
doc/classes/ParticlesMaterial.xml

@@ -135,7 +135,7 @@
 			Each particle's initial color. If the [Particles2D]'s [code]texture[/code] is defined, it will be multiplied by this color. To have particle display color in a [SpatialMaterial] make sure to set [member SpatialMaterial.vertex_color_use_as_albedo] to [code]true[/code].
 		</member>
 		<member name="color_ramp" type="Texture" setter="set_color_ramp" getter="get_color_ramp">
-			Each particle's color will vary along this [GradientTexture].
+			Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]).
 		</member>
 		<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
 			The rate at which particles lose velocity.

+ 1 - 0
doc/classes/VisualShaderNode.xml

@@ -4,6 +4,7 @@
 		Base class for nodes in a visual shader graph.
 	</brief_description>
 	<description>
+		Visual shader graphs consist of various nodes. Each node in the graph is a separate object and they are represented as a rectangular boxes with title and a set of properties. Each node has also connection ports that allow to connect it to another nodes and control the flow of the shader.
 	</description>
 	<tutorials>
 		<link>https://docs.godotengine.org/en/3.3/tutorials/shading/visual_shaders.html</link>

+ 2 - 0
modules/visual_script/doc_classes/VisualScriptExpression.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptExpression" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node that can execute a custom expression.
 	</brief_description>
 	<description>
+		A Visual Script node that can execute a custom expression. Values can be provided for the input and the expression result can be retrieved from the output.
 	</description>
 	<tutorials>
 	</tutorials>

+ 2 - 0
modules/visual_script/doc_classes/VisualScriptFunction.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptFunction" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node representing a function.
 	</brief_description>
 	<description>
+		[VisualScriptFunction] represents a function header. It is the starting point for the function body and can be used to tweak the function's properties (e.g. RPC mode).
 	</description>
 	<tutorials>
 	</tutorials>

+ 22 - 0
modules/visual_script/doc_classes/VisualScriptFunctionCall.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptFunctionCall" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node for calling a function.
 	</brief_description>
 	<description>
+		[VisualScriptFunctionCall] is created when you add or drag and drop a function onto the Visual Script graph. It allows to tweak parameters of the call, e.g. what object the function is called on.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,46 +12,66 @@
 	</methods>
 	<members>
 		<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+			The script to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;Object&quot;">
+			The base type to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+			The type to be used when [member call_mode] is set to [constant CALL_MODE_BASIC_TYPE].
 		</member>
 		<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptFunctionCall.CallMode" default="0">
+			[code]call_mode[/code] determines the target object on which the method will be called. See [enum CallMode] for options.
 		</member>
 		<member name="function" type="String" setter="set_function" getter="get_function" default="&quot;&quot;">
+			The name of the function to be called.
 		</member>
 		<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+			The node path to use when [member call_mode] is set to [constant CALL_MODE_NODE_PATH].
 		</member>
 		<member name="rpc_call_mode" type="int" setter="set_rpc_call_mode" getter="get_rpc_call_mode" enum="VisualScriptFunctionCall.RPCCallMode" default="0">
+			The mode for RPC calls. See [method Node.rpc] for more details and [enum RPCCallMode] for available options.
 		</member>
 		<member name="singleton" type="String" setter="set_singleton" getter="get_singleton">
+			The singleton to call the method on. Used when [member call_mode] is set to [constant CALL_MODE_SINGLETON].
 		</member>
 		<member name="use_default_args" type="int" setter="set_use_default_args" getter="get_use_default_args">
+			Number of default arguments that will be used when calling the function. Can't be higher than the number of available default arguments in the method's declaration.
 		</member>
 		<member name="validate" type="bool" setter="set_validate" getter="get_validate" default="true">
+			If [code]false[/code], call errors (e.g. wrong number of arguments) will be ignored.
 		</member>
 	</members>
 	<constants>
 		<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+			The method will be called on this [Object].
 		</constant>
 		<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+			The method will be called on the given [Node] in the scene tree.
 		</constant>
 		<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+			The method will be called on an instanced node with the given type and script.
 		</constant>
 		<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+			The method will be called on a GDScript basic type (e.g. [Vector2]).
 		</constant>
 		<constant name="CALL_MODE_SINGLETON" value="4" enum="CallMode">
+			The method will be called on a singleton.
 		</constant>
 		<constant name="RPC_DISABLED" value="0" enum="RPCCallMode">
+			The method will be called locally.
 		</constant>
 		<constant name="RPC_RELIABLE" value="1" enum="RPCCallMode">
+			The method will be called remotely.
 		</constant>
 		<constant name="RPC_UNRELIABLE" value="2" enum="RPCCallMode">
+			The method will be called remotely using an unreliable protocol.
 		</constant>
 		<constant name="RPC_RELIABLE_TO_ID" value="3" enum="RPCCallMode">
+			The method will be called remotely for the given peer.
 		</constant>
 		<constant name="RPC_UNRELIABLE_TO_ID" value="4" enum="RPCCallMode">
+			The method will be called remotely for the given peer, using an unreliable protocol.
 		</constant>
 	</constants>
 </class>

+ 5 - 0
modules/visual_script/doc_classes/VisualScriptFunctionState.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptFunctionState" inherits="Reference" version="3.4">
 	<brief_description>
+		A Visual Script node representing a function state.
 	</brief_description>
 	<description>
+		[VisualScriptFunctionState] is returned from [VisualScriptYield] and can be used to resume a paused function call.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -17,12 +19,14 @@
 			<argument index="2" name="args" type="Array">
 			</argument>
 			<description>
+				Connects this [VisualScriptFunctionState] to a signal in the given object to automatically resume when it's emitted.
 			</description>
 		</method>
 		<method name="is_valid" qualifiers="const">
 			<return type="bool">
 			</return>
 			<description>
+				Returns whether the function state is valid.
 			</description>
 		</method>
 		<method name="resume">
@@ -31,6 +35,7 @@
 			<argument index="0" name="args" type="Array" default="null">
 			</argument>
 			<description>
+				Resumes the function to run from the point it was yielded.
 			</description>
 		</method>
 	</methods>

+ 3 - 0
modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node returning a constant from [@GlobalScope].
 	</brief_description>
 	<description>
+		A Visual Script node returning a constant from [@GlobalScope].
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,6 +12,7 @@
 	</methods>
 	<members>
 		<member name="constant" type="int" setter="set_global_constant" getter="get_global_constant" default="0">
+			The constant to be used.
 		</member>
 	</members>
 	<constants>

+ 2 - 0
modules/visual_script/doc_classes/VisualScriptIndexGet.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptIndexGet" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node for getting a value from an array or a dictionary.
 	</brief_description>
 	<description>
+		[VisualScriptIndexGet] will return the value stored in an array or a dictionary under the given index.
 	</description>
 	<tutorials>
 	</tutorials>

+ 2 - 0
modules/visual_script/doc_classes/VisualScriptIndexSet.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptIndexSet" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node for setting a value in an array or a dictionary.
 	</brief_description>
 	<description>
+		[VisualScriptIndexSet] will set the value stored in an array or a dictionary under the given index to the provided new value.
 	</description>
 	<tutorials>
 	</tutorials>

+ 8 - 0
modules/visual_script/doc_classes/VisualScriptInputAction.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptInputAction" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node returning a state of an action.
 	</brief_description>
 	<description>
+		[VisualScriptInputAction] can be used to check if an action is pressed or released.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,18 +12,24 @@
 	</methods>
 	<members>
 		<member name="action" type="String" setter="set_action_name" getter="get_action_name" default="&quot;&quot;">
+			Name of the action.
 		</member>
 		<member name="mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="VisualScriptInputAction.Mode" default="0">
+			State of the action to check. See [enum Mode] for options.
 		</member>
 	</members>
 	<constants>
 		<constant name="MODE_PRESSED" value="0" enum="Mode">
+			[code]True[/code] if action is pressed.
 		</constant>
 		<constant name="MODE_RELEASED" value="1" enum="Mode">
+			[code]True[/code] if action is released (i.e. not pressed).
 		</constant>
 		<constant name="MODE_JUST_PRESSED" value="2" enum="Mode">
+			[code]True[/code] on the frame the action was pressed.
 		</constant>
 		<constant name="MODE_JUST_RELEASED" value="3" enum="Mode">
+			[code]True[/code] on the frame the action was released.
 		</constant>
 	</constants>
 </class>

+ 8 - 0
modules/visual_script/doc_classes/VisualScriptLists.xml

@@ -19,6 +19,7 @@
 			<argument index="2" name="index" type="int">
 			</argument>
 			<description>
+				Adds an input port to the Visual Script node.
 			</description>
 		</method>
 		<method name="add_output_data_port">
@@ -31,6 +32,7 @@
 			<argument index="2" name="index" type="int">
 			</argument>
 			<description>
+				Adds an output port to the Visual Script node.
 			</description>
 		</method>
 		<method name="remove_input_data_port">
@@ -39,6 +41,7 @@
 			<argument index="0" name="index" type="int">
 			</argument>
 			<description>
+				Removes an input port from the Visual Script node.
 			</description>
 		</method>
 		<method name="remove_output_data_port">
@@ -47,6 +50,7 @@
 			<argument index="0" name="index" type="int">
 			</argument>
 			<description>
+				Removes an output port from the Visual Script node.
 			</description>
 		</method>
 		<method name="set_input_data_port_name">
@@ -57,6 +61,7 @@
 			<argument index="1" name="name" type="String">
 			</argument>
 			<description>
+				Sets the name of an input port.
 			</description>
 		</method>
 		<method name="set_input_data_port_type">
@@ -67,6 +72,7 @@
 			<argument index="1" name="type" type="int" enum="Variant.Type">
 			</argument>
 			<description>
+				Sets the type of an input port.
 			</description>
 		</method>
 		<method name="set_output_data_port_name">
@@ -77,6 +83,7 @@
 			<argument index="1" name="name" type="String">
 			</argument>
 			<description>
+				Sets the name of an output port.
 			</description>
 		</method>
 		<method name="set_output_data_port_type">
@@ -87,6 +94,7 @@
 			<argument index="1" name="type" type="int" enum="Variant.Type">
 			</argument>
 			<description>
+				Sets the type of an output port.
 			</description>
 		</method>
 	</methods>

+ 3 - 0
modules/visual_script/doc_classes/VisualScriptOperator.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptOperator" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node that performs an operation on two values.
 	</brief_description>
 	<description>
 		[b]Input Ports:[/b]
@@ -15,8 +16,10 @@
 	</methods>
 	<members>
 		<member name="operator" type="int" setter="set_operator" getter="get_operator" enum="Variant.Operator" default="6">
+			The operation to be performed. See [enum Variant.Operator] for available options.
 		</member>
 		<member name="type" type="int" setter="set_typed" getter="get_typed" enum="Variant.Type" default="0">
+			The type of the values for this operation. See [enum Variant.Type] for available options.
 		</member>
 	</members>
 	<constants>

+ 13 - 0
modules/visual_script/doc_classes/VisualScriptPropertyGet.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptPropertyGet" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node returning a value of a property from an [Object].
 	</brief_description>
 	<description>
+		[VisualScriptPropertyGet] can return a value of any property from the current object or other objects.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,28 +12,39 @@
 	</methods>
 	<members>
 		<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+			The script to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;Object&quot;">
+			The base type to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+			The type to be used when [member set_mode] is set to [constant CALL_MODE_BASIC_TYPE].
 		</member>
 		<member name="index" type="String" setter="set_index" getter="get_index">
+			The indexed name of the property to retrieve. See [method Object.get_indexed] for details.
 		</member>
 		<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+			The node path to use when [member set_mode] is set to [constant CALL_MODE_NODE_PATH].
 		</member>
 		<member name="property" type="String" setter="set_property" getter="get_property" default="&quot;&quot;">
+			The name of the property to retrieve. Changing this will clear [member index].
 		</member>
 		<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertyGet.CallMode" default="0">
+			[code]set_mode[/code] determines the target object from which the property will be retrieved. See [enum CallMode] for options.
 		</member>
 	</members>
 	<constants>
 		<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+			The property will be retrieved from this [Object].
 		</constant>
 		<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+			The property will be retrieved from the given [Node] in the scene tree.
 		</constant>
 		<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+			The property will be retrieved from an instanced node with the given type and script.
 		</constant>
 		<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+			The property will be retrieved from a GDScript basic type (e.g. [Vector2]).
 		</constant>
 	</constants>
 </class>

+ 25 - 0
modules/visual_script/doc_classes/VisualScriptPropertySet.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptPropertySet" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node that sets a property of an [Object].
 	</brief_description>
 	<description>
+		[VisualScriptPropertySet] can set the value of any property from the current object or other objects.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,52 +12,75 @@
 	</methods>
 	<members>
 		<member name="assign_op" type="int" setter="set_assign_op" getter="get_assign_op" enum="VisualScriptPropertySet.AssignOp" default="0">
+			The additional operation to perform when assigning. See [enum AssignOp] for options.
 		</member>
 		<member name="base_script" type="String" setter="set_base_script" getter="get_base_script">
+			The script to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;Object&quot;">
+			The base type to be used when [member set_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="basic_type" type="int" setter="set_basic_type" getter="get_basic_type" enum="Variant.Type">
+			The type to be used when [member set_mode] is set to [constant CALL_MODE_BASIC_TYPE].
 		</member>
 		<member name="index" type="String" setter="set_index" getter="get_index">
+			The indexed name of the property to set. See [method Object.set_indexed] for details.
 		</member>
 		<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+			The node path to use when [member set_mode] is set to [constant CALL_MODE_NODE_PATH].
 		</member>
 		<member name="property" type="String" setter="set_property" getter="get_property" default="&quot;&quot;">
+			The name of the property to set. Changing this will clear [member index].
 		</member>
 		<member name="set_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptPropertySet.CallMode" default="0">
+			[code]set_mode[/code] determines the target object on which the property will be set. See [enum CallMode] for options.
 		</member>
 	</members>
 	<constants>
 		<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+			The property will be set on this [Object].
 		</constant>
 		<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+			The property will be set on the given [Node] in the scene tree.
 		</constant>
 		<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+			The property will be set on an instanced node with the given type and script.
 		</constant>
 		<constant name="CALL_MODE_BASIC_TYPE" value="3" enum="CallMode">
+			The property will be set on a GDScript basic type (e.g. [Vector2]).
 		</constant>
 		<constant name="ASSIGN_OP_NONE" value="0" enum="AssignOp">
+			The property will be assigned regularly.
 		</constant>
 		<constant name="ASSIGN_OP_ADD" value="1" enum="AssignOp">
+			The value will be added to the property. Equivalent of doing [code]+=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_SUB" value="2" enum="AssignOp">
+			The value will be subtracted from the property. Equivalent of doing [code]-=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_MUL" value="3" enum="AssignOp">
+			The property will be multiplied by the value. Equivalent of doing [code]*=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_DIV" value="4" enum="AssignOp">
+			The property will be divided by the value. Equivalent of doing [code]/=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_MOD" value="5" enum="AssignOp">
+			A modulo operation will be performed on the property and the value. Equivalent of doing [code]%=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_SHIFT_LEFT" value="6" enum="AssignOp">
+			The property will be binarly shifted to the left by the given value. Equivalent of doing [code]&lt;&lt;[/code].
 		</constant>
 		<constant name="ASSIGN_OP_SHIFT_RIGHT" value="7" enum="AssignOp">
+			The property will be binarly shifted to the right by the given value. Equivalent of doing [code]&gt;&gt;[/code].
 		</constant>
 		<constant name="ASSIGN_OP_BIT_AND" value="8" enum="AssignOp">
+			A binary [code]AND[/code] operation will be performed on the property. Equivalent of doing [code]&amp;=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_BIT_OR" value="9" enum="AssignOp">
+			A binary [code]OR[/code] operation will be performed on the property. Equivalent of doing [code]|=[/code].
 		</constant>
 		<constant name="ASSIGN_OP_BIT_XOR" value="10" enum="AssignOp">
+			A binary [code]XOR[/code] operation will be performed on the property. Equivalent of doing [code]^=[/code].
 		</constant>
 	</constants>
 </class>

+ 2 - 0
modules/visual_script/doc_classes/VisualScriptSceneTree.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptSceneTree" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node for accessing [SceneTree] methods.
 	</brief_description>
 	<description>
+		A Visual Script node for accessing [SceneTree] methods.
 	</description>
 	<tutorials>
 	</tutorials>

+ 3 - 0
modules/visual_script/doc_classes/VisualScriptSubCall.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptSubCall" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		Calls a method called [code]_subcall[/code] in this object.
 	</brief_description>
 	<description>
+		[VisualScriptSubCall] will call method named [code]_subcall[/code] in the current script. It will fail if the method doesn't exist or the provided arguments are wrong.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -13,6 +15,7 @@
 			<argument index="0" name="arguments" type="Variant">
 			</argument>
 			<description>
+				Called by this node.
 			</description>
 		</method>
 	</methods>

+ 4 - 0
modules/visual_script/doc_classes/VisualScriptTypeCast.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptTypeCast" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node that casts the given value to another type.
 	</brief_description>
 	<description>
+		[VisualScriptTypeCast] will perform a type conversion to an [Object]-derived type.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,8 +12,10 @@
 	</methods>
 	<members>
 		<member name="base_script" type="String" setter="set_base_script" getter="get_base_script" default="&quot;&quot;">
+			The target script class to be converted to. If none, only the [member base_type] will be used.
 		</member>
 		<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;Object&quot;">
+			The target type to be converted to.
 		</member>
 	</members>
 	<constants>

+ 7 - 0
modules/visual_script/doc_classes/VisualScriptYield.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptYield" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node used to pause a function execution.
 	</brief_description>
 	<description>
+		[VisualScriptYield] will pause the function call and return [VisualScriptFunctionState], which can be used to resume the function.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,16 +12,21 @@
 	</methods>
 	<members>
 		<member name="mode" type="int" setter="set_yield_mode" getter="get_yield_mode" enum="VisualScriptYield.YieldMode" default="1">
+			The mode to use for yielding. See [enum YieldMode] for available options.
 		</member>
 		<member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time">
+			The time to wait when [member mode] is set to [constant YIELD_WAIT].
 		</member>
 	</members>
 	<constants>
 		<constant name="YIELD_FRAME" value="1" enum="YieldMode">
+			Yields during an idle frame.
 		</constant>
 		<constant name="YIELD_PHYSICS_FRAME" value="2" enum="YieldMode">
+			Yields during a physics frame.
 		</constant>
 		<constant name="YIELD_WAIT" value="3" enum="YieldMode">
+			Yields a function and waits the given time.
 		</constant>
 	</constants>
 </class>

+ 9 - 0
modules/visual_script/doc_classes/VisualScriptYieldSignal.xml

@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualScriptYieldSignal" inherits="VisualScriptNode" version="3.4">
 	<brief_description>
+		A Visual Script node yielding for a signal.
 	</brief_description>
 	<description>
+		[VisualScriptYieldSignal] will pause the function execution until the provided signal is emitted.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -10,20 +12,27 @@
 	</methods>
 	<members>
 		<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="&quot;Object&quot;">
+			The base type to be used when [member call_mode] is set to [constant CALL_MODE_INSTANCE].
 		</member>
 		<member name="call_mode" type="int" setter="set_call_mode" getter="get_call_mode" enum="VisualScriptYieldSignal.CallMode" default="0">
+			[code]call_mode[/code] determines the target object to wait for the signal emission. See [enum CallMode] for options.
 		</member>
 		<member name="node_path" type="NodePath" setter="set_base_path" getter="get_base_path">
+			The node path to use when [member call_mode] is set to [constant CALL_MODE_NODE_PATH].
 		</member>
 		<member name="signal" type="String" setter="set_signal" getter="get_signal" default="&quot;&quot;">
+			The signal name to be waited for.
 		</member>
 	</members>
 	<constants>
 		<constant name="CALL_MODE_SELF" value="0" enum="CallMode">
+			A signal from this [Object] will be used.
 		</constant>
 		<constant name="CALL_MODE_NODE_PATH" value="1" enum="CallMode">
+			A signal from the given [Node] in the scene tree will be used.
 		</constant>
 		<constant name="CALL_MODE_INSTANCE" value="2" enum="CallMode">
+			A signal from an instanced node with the given type will be used.
 		</constant>
 	</constants>
 </class>

+ 6 - 1
platform/iphone/export/export.cpp

@@ -372,6 +372,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
 		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
 	}
 
+	Set<String> plist_keys;
+
 	for (int i = 0; i < found_plugins.size(); i++) {
 		// Editable plugin plist values
 		PluginConfigIOS plugin = found_plugins[i];
@@ -383,7 +385,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
 			switch (item.type) {
 				case PluginConfigIOS::PlistItemType::STRING_INPUT: {
 					String preset_name = "plugins_plist/" + key;
-					r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+					if (!plist_keys.has(preset_name)) {
+						r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+						plist_keys.insert(preset_name);
+					}
 				} break;
 				default:
 					continue;

+ 2 - 0
platform/iphone/plugin/godot_plugin_config.h

@@ -270,6 +270,8 @@ static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, co
 		return plugin_config;
 	}
 
+	config_file->clear();
+
 	Error err = config_file->load(path);
 
 	if (err != OK) {

+ 113 - 31
platform/x11/os_x11.cpp

@@ -3753,65 +3753,147 @@ static String get_mountpoint(const String &p_path) {
 }
 
 Error OS_X11::move_to_trash(const String &p_path) {
-	String trash_can = "";
+	int err_code;
+	List<String> args;
+	args.push_back(p_path);
+	args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
+	Error result = execute("gio", args, true, nullptr, nullptr, &err_code); // For GNOME based machines.
+	if (result == OK && !err_code) {
+		return OK;
+	} else if (err_code == 2) {
+		return ERR_FILE_NOT_FOUND;
+	}
+
+	args.pop_front();
+	args.push_front("move");
+	args.push_back("trash:/"); // The command is `kioclient5 move <file_name> trash:/`.
+	result = execute("kioclient5", args, true, nullptr, nullptr, &err_code); // For KDE based machines.
+	if (result == OK && !err_code) {
+		return OK;
+	} else if (err_code == 2) {
+		return ERR_FILE_NOT_FOUND;
+	}
+
+	args.pop_front();
+	args.pop_back();
+	result = execute("gvfs-trash", args, true, nullptr, nullptr, &err_code); // For older Linux machines.
+	if (result == OK && !err_code) {
+		return OK;
+	} else if (err_code == 2) {
+		return ERR_FILE_NOT_FOUND;
+	}
+
+	// If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
+	String trash_path = "";
 	String mnt = get_mountpoint(p_path);
 
-	// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
+	// If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
 	if (mnt != "") {
-		String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
+		String path(mnt + "/.Trash-" + itos(getuid()));
 		struct stat s;
 		if (!stat(path.utf8().get_data(), &s)) {
-			trash_can = path;
+			trash_path = path;
 		}
 	}
 
-	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
-	if (trash_can == "") {
+	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash" as the trash can.
+	if (trash_path == "") {
 		char *dhome = getenv("XDG_DATA_HOME");
 		if (dhome) {
-			trash_can = String(dhome) + "/Trash/files";
+			trash_path = String(dhome) + "/Trash";
 		}
 	}
 
-	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
-	if (trash_can == "") {
+	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash" as the trash can.
+	if (trash_path == "") {
 		char *home = getenv("HOME");
 		if (home) {
-			trash_can = String(home) + "/.local/share/Trash/files";
+			trash_path = String(home) + "/.local/share/Trash";
 		}
 	}
 
 	// Issue an error if none of the previous locations is appropriate for the trash can.
-	if (trash_can == "") {
-		ERR_PRINT("move_to_trash: Could not determine the trash can location");
-		return FAILED;
-	}
+	ERR_FAIL_COND_V_MSG(trash_path == "", FAILED, "Could not determine the trash can location");
 
 	// Create needed directories for decided trash can location.
-	DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	Error err = dir_access->make_dir_recursive(trash_can);
-	memdelete(dir_access);
+	{
+		DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		Error err = dir_access->make_dir_recursive(trash_path);
+
+		// Issue an error if trash can is not created proprely.
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
+		err = dir_access->make_dir_recursive(trash_path + "/files");
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
+		err = dir_access->make_dir_recursive(trash_path + "/info");
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
+		memdelete(dir_access);
+	}
+
+	// The trash can is successfully created, now we check that we don't exceed our file name length limit.
+	// If the file name is too long trim it so we can add the identifying number and ".trashinfo".
+	// Assumes that the file name length limit is 255 characters.
+	String file_name = basename(p_path.utf8().get_data());
+	if (file_name.length() > 240) {
+		file_name = file_name.substr(0, file_name.length() - 15);
+	}
+
+	String dest_path = trash_path + "/files/" + file_name;
+	struct stat buff;
+	int id_number = 0;
+	String fn = file_name;
+
+	// Checks if a resource with the same name already exist in the trash can,
+	// if there is, add an identifying number to our resource's name.
+	while (stat(dest_path.utf8().get_data(), &buff) == 0) {
+		id_number++;
+
+		// Added a limit to check for identically named files already on the trash can
+		// if there are too many it could make the editor unresponsive.
+		ERR_FAIL_COND_V_MSG(id_number > 99, FAILED, "Too many identically named resources already in the trash can.");
+		fn = file_name + "." + itos(id_number);
+		dest_path = trash_path + "/files/" + fn;
+	}
+	file_name = fn;
+
+	// Generates the .trashinfo file
+	OS::Date date = OS::get_singleton()->get_date(false);
+	OS::Time time = OS::get_singleton()->get_time(false);
+	String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.min);
+	timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
+	String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
+	{
+		Error err;
+		FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
+		file->store_string(trash_info);
+		file->close();
 
-	// Issue an error if trash can is not created proprely.
-	if (err != OK) {
-		ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
-		return err;
+		// Rename our resource before moving it to the trash can.
+		DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
+		ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
+		memdelete(dir_access);
 	}
 
-	// The trash can is successfully created, now move the given resource to it.
+	// Move the given resource to the trash can.
 	// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
 	List<String> mv_args;
-	mv_args.push_back(p_path);
-	mv_args.push_back(trash_can);
-	int retval;
-	err = execute("mv", mv_args, true, nullptr, nullptr, &retval);
+	mv_args.push_back(p_path.get_base_dir() + "/" + file_name);
+	mv_args.push_back(trash_path + "/files");
+	{
+		int retval;
+		Error err = execute("mv", mv_args, true, nullptr, nullptr, &retval);
 
-	// Issue an error if "mv" failed to move the given resource to the trash can.
-	if (err != OK || retval != 0) {
-		ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
-		return FAILED;
+		// Issue an error if "mv" failed to move the given resource to the trash can.
+		if (err != OK || retval != 0) {
+			ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_path + "/files\"");
+			DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			err = dir_access->rename(p_path.get_base_dir() + "/" + file_name, p_path);
+			memdelete(dir_access);
+			ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename " + p_path.get_base_dir() + "/" + file_name + " back to its original name:" + p_path);
+			return FAILED;
+		}
 	}
-
 	return OK;
 }
 

+ 0 - 4
scene/2d/cpu_particles_2d.cpp

@@ -458,10 +458,6 @@ Vector2 CPUParticles2D::get_gravity() const {
 }
 
 void CPUParticles2D::_validate_property(PropertyInfo &property) const {
-	if (property.name == "color" && color_ramp.is_valid()) {
-		property.usage = 0;
-	}
-
 	if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
 		property.usage = 0;
 	}

+ 0 - 4
scene/3d/cpu_particles.cpp

@@ -450,10 +450,6 @@ Vector3 CPUParticles::get_gravity() const {
 }
 
 void CPUParticles::_validate_property(PropertyInfo &property) const {
-	if (property.name == "color" && color_ramp.is_valid()) {
-		property.usage = 0;
-	}
-
 	if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
 		property.usage = 0;
 	}

+ 13 - 0
scene/gui/base_button.cpp

@@ -231,6 +231,18 @@ void BaseButton::set_pressed(bool p_pressed) {
 	update();
 }
 
+void BaseButton::set_pressed_no_signal(bool p_pressed) {
+	if (!toggle_mode) {
+		return;
+	}
+	if (status.pressed == p_pressed) {
+		return;
+	}
+	status.pressed = p_pressed;
+
+	update();
+}
+
 bool BaseButton::is_pressing() const {
 	return status.press_attempt;
 }
@@ -385,6 +397,7 @@ void BaseButton::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input);
 	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
 	ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
+	ClassDB::bind_method(D_METHOD("set_pressed_no_signal", "pressed"), &BaseButton::set_pressed_no_signal);
 	ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered);
 	ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode);
 	ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode);

+ 2 - 1
scene/gui/base_button.h

@@ -96,7 +96,8 @@ public:
 	bool is_pressing() const; ///< return whether button is pressed (toggled in)
 	bool is_hovered() const;
 
-	void set_pressed(bool p_pressed); ///only works in toggle mode
+	void set_pressed(bool p_pressed); // Only works in toggle mode.
+	void set_pressed_no_signal(bool p_pressed);
 	void set_toggle_mode(bool p_on);
 	bool is_toggle_mode() const;
 

+ 7 - 4
scene/main/node.cpp

@@ -313,7 +313,7 @@ void Node::_propagate_exit_tree() {
 
 void Node::move_child(Node *p_child, int p_pos) {
 	ERR_FAIL_NULL(p_child);
-	ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, "Invalid new child position: " + itos(p_pos) + ".");
+	ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, vformat("Invalid new child position: %d.", p_pos));
 	ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node.");
 	ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup).");
 
@@ -1127,8 +1127,11 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) {
 
 void Node::add_child(Node *p_child, bool p_legible_unique_name) {
 	ERR_FAIL_NULL(p_child);
-	ERR_FAIL_COND_MSG(p_child == this, "Can't add child '" + p_child->get_name() + "' to itself."); // adding to itself!
-	ERR_FAIL_COND_MSG(p_child->data.parent, "Can't add child '" + p_child->get_name() + "' to '" + get_name() + "', already has a parent '" + p_child->data.parent->get_name() + "'."); //Fail if node has a parent
+	ERR_FAIL_COND_MSG(p_child == this, vformat("Can't add child '%s' to itself.", p_child->get_name())); // adding to itself!
+	ERR_FAIL_COND_MSG(p_child->data.parent, vformat("Can't add child '%s' to '%s', already has a parent '%s'.", p_child->get_name(), get_name(), p_child->data.parent->get_name())); //Fail if node has a parent
+#ifdef DEBUG_ENABLED
+	ERR_FAIL_COND_MSG(p_child->is_a_parent_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_name()));
+#endif
 	ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead.");
 
 	/* Validate name */
@@ -1198,7 +1201,7 @@ void Node::remove_child(Node *p_child) {
 		}
 	}
 
-	ERR_FAIL_COND_MSG(idx == -1, "Cannot remove child node " + p_child->get_name() + " as it is not a child of this node.");
+	ERR_FAIL_COND_MSG(idx == -1, vformat("Cannot remove child node '%s' as it is not a child of this node.", p_child->get_name()));
 	//ERR_FAIL_COND( p_child->data.blocked > 0 );
 
 	//if (data.scene) { does not matter

+ 1 - 5
scene/resources/particles_material.cpp

@@ -575,7 +575,7 @@ void ParticlesMaterial::_update_shader() {
 	code += "			vec4(1.250, -1.050, -0.203, 0.0),\n";
 	code += "			vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n";
 	if (color_ramp.is_valid()) {
-		code += "	COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0);\n";
+		code += "	COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0) * color_value;\n";
 	} else {
 		code += "	COLOR = hue_rot_mat * color_value;\n";
 	}
@@ -1095,10 +1095,6 @@ RID ParticlesMaterial::get_shader_rid() const {
 }
 
 void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
-	if (property.name == "color" && color_ramp.is_valid()) {
-		property.usage = 0;
-	}
-
 	if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
 		property.usage = 0;
 	}