diff options
65 files changed, 1870 insertions, 1118 deletions
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index b760a9ef80..5e0c0390f9 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -43,7 +43,6 @@ Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive)."); Error err; IP::Type ip_type = IP::TYPE_ANY; diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index 6a1af0c2a9..27a1cab721 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -91,7 +91,6 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) { ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive)."); Error err; IP::Type ip_type = IP::TYPE_ANY; diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index 1bbf9bcd93..7fbf53c7d1 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -43,7 +43,7 @@ [/csharp] [/codeblocks] The [MeshInstance3D] is ready to be added to the [SceneTree] to be shown. - See also [ImmediateGeometry3D], [MeshDataTool] and [SurfaceTool] for procedural geometry generation. + See also [ImmediateMesh], [MeshDataTool] and [SurfaceTool] for procedural geometry generation. [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes. </description> <tutorials> @@ -202,7 +202,31 @@ Sets a name for a given surface. </description> </method> - <method name="surface_update_region"> + <method name="surface_update_attribute_region"> + <return type="void"> + </return> + <argument index="0" name="surf_idx" type="int"> + </argument> + <argument index="1" name="offset" type="int"> + </argument> + <argument index="2" name="data" type="PackedByteArray"> + </argument> + <description> + </description> + </method> + <method name="surface_update_skin_region"> + <return type="void"> + </return> + <argument index="0" name="surf_idx" type="int"> + </argument> + <argument index="1" name="offset" type="int"> + </argument> + <argument index="2" name="data" type="PackedByteArray"> + </argument> + <description> + </description> + </method> + <method name="surface_update_vertex_region"> <return type="void"> </return> <argument index="0" name="surf_idx" type="int"> @@ -212,8 +236,6 @@ <argument index="2" name="data" type="PackedByteArray"> </argument> <description> - Updates a specified region of mesh arrays on the GPU. - [b]Warning:[/b] Only use if you know what you are doing. You can easily cause crashes by calling this function with improper arguments. </description> </method> </methods> diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml index bf1a9cc929..4620b3d93c 100644 --- a/doc/classes/Camera2D.xml +++ b/doc/classes/Camera2D.xml @@ -161,6 +161,8 @@ </member> <member name="limit_smoothed" type="bool" setter="set_limit_smoothing_enabled" getter="is_limit_smoothing_enabled" default="false"> If [code]true[/code], the camera smoothly stops when reaches its limits. + This has no effect if smoothing is disabled. + [b]Note:[/b] To immediately update the camera's position to be within limits without smoothing, even with this setting enabled, invoke [method reset_smoothing]. </member> <member name="limit_top" type="int" setter="set_limit" getter="get_limit" default="-10000000"> Top scroll limit in pixels. The camera stops moving when reaching this value. diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index 7c4c75bf0f..e96124c9eb 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -266,6 +266,9 @@ The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> + <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject2D.DisableMode" default="0"> + Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. + </member> <member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" default="true"> If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set. </member> @@ -294,5 +297,16 @@ </signal> </signals> <constants> + <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject2D]. + Automatically re-added to the physics simulation when the [Node] is processed again. + </constant> + <constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody2D] can't be affected by forces or other bodies while static. + Automatically set [PhysicsBody2D] back to its original mode when the [Node] is processed again. + </constant> + <constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation. + </constant> </constants> </class> diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml index 4ab37f5c7b..dfd1e85e56 100644 --- a/doc/classes/CollisionObject3D.xml +++ b/doc/classes/CollisionObject3D.xml @@ -230,6 +230,9 @@ The physics layers this CollisionObject3D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> + <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject3D.DisableMode" default="0"> + Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. + </member> <member name="input_capture_on_drag" type="bool" setter="set_capture_input_on_drag" getter="get_capture_input_on_drag" default="false"> If [code]true[/code], the [CollisionObject3D] will continue to receive input events as the mouse is dragged across its shapes. </member> @@ -265,5 +268,16 @@ </signal> </signals> <constants> + <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject3D]. + Automatically re-added to the physics simulation when the [Node] is processed again. + </constant> + <constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody3D] can't be affected by forces or other bodies while static. + Automatically set [PhysicsBody3D] back to its original mode when the [Node] is processed again. + </constant> + <constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation. + </constant> </constants> </class> diff --git a/doc/classes/ImmediateGeometry3D.xml b/doc/classes/ImmediateGeometry3D.xml deleted file mode 100644 index d2d663847f..0000000000 --- a/doc/classes/ImmediateGeometry3D.xml +++ /dev/null @@ -1,113 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="ImmediateGeometry3D" inherits="GeometryInstance3D" version="4.0"> - <brief_description> - Draws simple geometry from code. - </brief_description> - <description> - Draws simple geometry from code. Uses a drawing mode similar to OpenGL 1.x. - See also [ArrayMesh], [MeshDataTool] and [SurfaceTool] for procedural geometry generation. - [b]Note:[/b] ImmediateGeometry3D is best suited to small amounts of mesh data that change every frame. It will be slow when handling large amounts of mesh data. If mesh data doesn't change often, use [ArrayMesh], [MeshDataTool] or [SurfaceTool] instead. - [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes. - </description> - <tutorials> - </tutorials> - <methods> - <method name="add_sphere"> - <return type="void"> - </return> - <argument index="0" name="lats" type="int"> - </argument> - <argument index="1" name="lons" type="int"> - </argument> - <argument index="2" name="radius" type="float"> - </argument> - <argument index="3" name="add_uv" type="bool" default="true"> - </argument> - <description> - Simple helper to draw an UV sphere with given latitude, longitude and radius. - </description> - </method> - <method name="add_vertex"> - <return type="void"> - </return> - <argument index="0" name="position" type="Vector3"> - </argument> - <description> - Adds a vertex in local coordinate space with the currently set color/uv/etc. - </description> - </method> - <method name="begin"> - <return type="void"> - </return> - <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType"> - </argument> - <argument index="1" name="texture" type="Texture2D" default="null"> - </argument> - <description> - Begin drawing (and optionally pass a texture override). When done call [method end]. For more information on how this works, search for [code]glBegin()[/code] and [code]glEnd()[/code] references. - For the type of primitive, see the [enum Mesh.PrimitiveType] enum. - </description> - </method> - <method name="clear"> - <return type="void"> - </return> - <description> - Clears everything that was drawn using begin/end. - </description> - </method> - <method name="end"> - <return type="void"> - </return> - <description> - Ends a drawing context and displays the results. - </description> - </method> - <method name="set_color"> - <return type="void"> - </return> - <argument index="0" name="color" type="Color"> - </argument> - <description> - The current drawing color. - </description> - </method> - <method name="set_normal"> - <return type="void"> - </return> - <argument index="0" name="normal" type="Vector3"> - </argument> - <description> - The next vertex's normal. - </description> - </method> - <method name="set_tangent"> - <return type="void"> - </return> - <argument index="0" name="tangent" type="Plane"> - </argument> - <description> - The next vertex's tangent (and binormal facing). - </description> - </method> - <method name="set_uv"> - <return type="void"> - </return> - <argument index="0" name="uv" type="Vector2"> - </argument> - <description> - The next vertex's UV. - </description> - </method> - <method name="set_uv2"> - <return type="void"> - </return> - <argument index="0" name="uv" type="Vector2"> - </argument> - <description> - The next vertex's second layer UV. - </description> - </method> - </methods> - <constants> - </constants> -</class> diff --git a/doc/classes/ImmediateMesh.xml b/doc/classes/ImmediateMesh.xml new file mode 100644 index 0000000000..d2ae091cad --- /dev/null +++ b/doc/classes/ImmediateMesh.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ImmediateMesh" inherits="Mesh" version="4.0"> + <brief_description> + Mesh optimized for creating geometry manually. + </brief_description> + <description> + Mesh optimized for creating geometry manually, similar to OpenGL1.x immediate mode. + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear_surfaces"> + <return type="void"> + </return> + <description> + Clear all surfaces. + </description> + </method> + <method name="surface_add_vertex"> + <return type="void"> + </return> + <argument index="0" name="vertex" type="Vector3"> + </argument> + <description> + Add a 3D vertex using the current attributes previously set. + </description> + </method> + <method name="surface_add_vertex_2d"> + <return type="void"> + </return> + <argument index="0" name="vertex" type="Vector2"> + </argument> + <description> + Add a 2D vertex using the current attributes previously set. + </description> + </method> + <method name="surface_begin"> + <return type="void"> + </return> + <argument index="0" name="primitive" type="int" enum="Mesh.PrimitiveType"> + </argument> + <argument index="1" name="material" type="Material" default="null"> + </argument> + <description> + Begin a new surface. + </description> + </method> + <method name="surface_end"> + <return type="void"> + </return> + <description> + End and commit current surface. Note that surface being created will not be visible until this function is called. + </description> + </method> + <method name="surface_set_color"> + <return type="void"> + </return> + <argument index="0" name="color" type="Color"> + </argument> + <description> + Set the color attribute that will be pushed with the next vertex. + </description> + </method> + <method name="surface_set_normal"> + <return type="void"> + </return> + <argument index="0" name="normal" type="Vector3"> + </argument> + <description> + Set the normal attribute that will be pushed with the next vertex. + </description> + </method> + <method name="surface_set_tangent"> + <return type="void"> + </return> + <argument index="0" name="tangent" type="Plane"> + </argument> + <description> + Set the tangent attribute that will be pushed with the next vertex. + </description> + </method> + <method name="surface_set_uv"> + <return type="void"> + </return> + <argument index="0" name="uv" type="Vector2"> + </argument> + <description> + Set the UV attribute that will be pushed with the next vertex. + </description> + </method> + <method name="surface_set_uv2"> + <return type="void"> + </return> + <argument index="0" name="uv2" type="Vector2"> + </argument> + <description> + Set the UV2 attribute that will be pushed with the next vertex. + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml index da02511dc0..c0ee1e1956 100644 --- a/doc/classes/MeshDataTool.xml +++ b/doc/classes/MeshDataTool.xml @@ -45,7 +45,7 @@ AddChild(mi); [/csharp] [/codeblocks] - See also [ArrayMesh], [ImmediateGeometry3D] and [SurfaceTool] for procedural geometry generation. + See also [ArrayMesh], [ImmediateMesh] and [SurfaceTool] for procedural geometry generation. [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes. </description> <tutorials> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index f185a2bc57..88e69968d2 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -904,6 +904,12 @@ <constant name="NOTIFICATION_POST_ENTER_TREE" value="27"> Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters tree, instead of only once. </constant> + <constant name="NOTIFICATION_DISABLED" value="28"> + Notification received when the node is disabled. See [constant PROCESS_MODE_DISABLED]. + </constant> + <constant name="NOTIFICATION_ENABLED" value="29"> + Notification received when the node is enabled again after being disabled. See [constant PROCESS_MODE_DISABLED]. + </constant> <constant name="NOTIFICATION_EDITOR_PRE_SAVE" value="9001"> Notification received right before the scene with the node is saved in the editor. This notification is only sent in the Godot editor and will not occur in exported projects. </constant> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 44e0202307..acfa277dcb 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -988,143 +988,6 @@ Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], [code]etc2[/code] and [code]pvrtc[/code]. </description> </method> - <method name="immediate_begin"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="primitive" type="int" enum="RenderingServer.PrimitiveType"> - </argument> - <argument index="2" name="texture" type="RID"> - </argument> - <description> - Sets up [ImmediateGeometry3D] internals to prepare for drawing. Equivalent to [method ImmediateGeometry3D.begin]. - </description> - </method> - <method name="immediate_clear"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <description> - Clears everything that was set up between [method immediate_begin] and [method immediate_end]. Equivalent to [method ImmediateGeometry3D.clear]. - </description> - </method> - <method name="immediate_color"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="color" type="Color"> - </argument> - <description> - Sets the color to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_color]. - </description> - </method> - <method name="immediate_create"> - <return type="RID"> - </return> - <description> - Creates an immediate geometry and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]immediate_*[/code] RenderingServer functions. - Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method. - To place in a scene, attach this immediate geometry to an instance using [method instance_set_base] using the returned RID. - </description> - </method> - <method name="immediate_end"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <description> - Ends drawing the [ImmediateGeometry3D] and displays it. Equivalent to [method ImmediateGeometry3D.end]. - </description> - </method> - <method name="immediate_get_material" qualifiers="const"> - <return type="RID"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <description> - Returns the material assigned to the [ImmediateGeometry3D]. - </description> - </method> - <method name="immediate_normal"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="normal" type="Vector3"> - </argument> - <description> - Sets the normal to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_normal]. - </description> - </method> - <method name="immediate_set_material"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="material" type="RID"> - </argument> - <description> - Sets the material to be used to draw the [ImmediateGeometry3D]. - </description> - </method> - <method name="immediate_tangent"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="tangent" type="Plane"> - </argument> - <description> - Sets the tangent to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_tangent]. - </description> - </method> - <method name="immediate_uv"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="tex_uv" type="Vector2"> - </argument> - <description> - Sets the UV to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_uv]. - </description> - </method> - <method name="immediate_uv2"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="tex_uv" type="Vector2"> - </argument> - <description> - Sets the UV2 to be used with next vertex. Equivalent to [method ImmediateGeometry3D.set_uv2]. - </description> - </method> - <method name="immediate_vertex"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="vertex" type="Vector3"> - </argument> - <description> - Adds the next vertex using the information provided in advance. Equivalent to [method ImmediateGeometry3D.add_vertex]. - </description> - </method> - <method name="immediate_vertex_2d"> - <return type="void"> - </return> - <argument index="0" name="immediate" type="RID"> - </argument> - <argument index="1" name="vertex" type="Vector2"> - </argument> - <description> - Adds the next vertex using the information provided in advance. This is a helper class that calls [method immediate_vertex] under the hood. Equivalent to [method ImmediateGeometry3D.add_vertex]. - </description> - </method> <method name="init"> <return type="void"> </return> @@ -1787,21 +1650,6 @@ Sets a mesh's surface's material. </description> </method> - <method name="mesh_surface_update_region"> - <return type="void"> - </return> - <argument index="0" name="mesh" type="RID"> - </argument> - <argument index="1" name="surface" type="int"> - </argument> - <argument index="2" name="offset" type="int"> - </argument> - <argument index="3" name="data" type="PackedByteArray"> - </argument> - <description> - Updates a specific region of a vertex buffer for the specified surface. Warning: this function alters the vertex buffer directly with no safety mechanisms, you can easily corrupt your mesh. - </description> - </method> <method name="multimesh_allocate_data"> <return type="void"> </return> @@ -3677,35 +3525,32 @@ <constant name="INSTANCE_MULTIMESH" value="2" enum="InstanceType"> The instance is a multimesh. </constant> - <constant name="INSTANCE_IMMEDIATE" value="3" enum="InstanceType"> - The instance is an immediate geometry. - </constant> - <constant name="INSTANCE_PARTICLES" value="4" enum="InstanceType"> + <constant name="INSTANCE_PARTICLES" value="3" enum="InstanceType"> The instance is a particle emitter. </constant> - <constant name="INSTANCE_PARTICLES_COLLISION" value="5" enum="InstanceType"> + <constant name="INSTANCE_PARTICLES_COLLISION" value="4" enum="InstanceType"> </constant> - <constant name="INSTANCE_LIGHT" value="6" enum="InstanceType"> + <constant name="INSTANCE_LIGHT" value="5" enum="InstanceType"> The instance is a light. </constant> - <constant name="INSTANCE_REFLECTION_PROBE" value="7" enum="InstanceType"> + <constant name="INSTANCE_REFLECTION_PROBE" value="6" enum="InstanceType"> The instance is a reflection probe. </constant> - <constant name="INSTANCE_DECAL" value="8" enum="InstanceType"> + <constant name="INSTANCE_DECAL" value="7" enum="InstanceType"> The instance is a decal. </constant> - <constant name="INSTANCE_VOXEL_GI" value="9" enum="InstanceType"> + <constant name="INSTANCE_VOXEL_GI" value="8" enum="InstanceType"> The instance is a VoxelGI. </constant> - <constant name="INSTANCE_LIGHTMAP" value="10" enum="InstanceType"> + <constant name="INSTANCE_LIGHTMAP" value="9" enum="InstanceType"> The instance is a lightmap. </constant> - <constant name="INSTANCE_OCCLUDER" value="11" enum="InstanceType"> + <constant name="INSTANCE_OCCLUDER" value="10" enum="InstanceType"> </constant> - <constant name="INSTANCE_MAX" value="13" enum="InstanceType"> + <constant name="INSTANCE_MAX" value="12" enum="InstanceType"> Represents the size of the [enum InstanceType] enum. </constant> - <constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType"> + <constant name="INSTANCE_GEOMETRY_MASK" value="14" enum="InstanceType"> A combination of the flags of geometry instances (mesh, multimesh, immediate and particles). </constant> <constant name="INSTANCE_FLAG_USE_BAKED_LIGHT" value="0" enum="InstanceFlags"> diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml index 7999ad774d..b143c60d9d 100644 --- a/doc/classes/SoftBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -93,6 +93,9 @@ </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> + <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0"> + Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. + </member> <member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0"> </member> <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5"> @@ -113,5 +116,12 @@ </member> </members> <constants> + <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftBody3D]. + Automatically re-added to the physics simulation when the [Node] is processed again. + </constant> + <constant name="DISABLE_MODE_KEEP_ACTIVE" value="1" enum="DisableMode"> + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation. + </constant> </constants> </class> diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml index f7f2ff0de1..ddb9d543e8 100644 --- a/doc/classes/Sprite3D.xml +++ b/doc/classes/Sprite3D.xml @@ -21,7 +21,6 @@ The number of columns in the sprite sheet. </member> <member name="region_enabled" type="bool" setter="set_region_enabled" getter="is_region_enabled" default="false"> - If [code]true[/code], texture will be cut from a larger atlas texture. See [member region_rect]. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2(0, 0, 0, 0)"> The region of the atlas texture to display. [member region_enabled] must be [code]true[/code]. @@ -39,11 +38,6 @@ Emitted when the [member frame] changes. </description> </signal> - <signal name="texture_changed"> - <description> - Emitted when the [member texture] changes. - </description> - </signal> </signals> <constants> </constants> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index 22d1b52479..a8b836ff0c 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -24,7 +24,7 @@ The above [SurfaceTool] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calling [method set_uv] or [method set_color], then the last values would be used. Vertex attributes must be passed [b]before[/b] calling [method add_vertex]. Failure to do so will result in an error when committing the vertex information to a mesh. Additionally, the attributes used before the first vertex is added determine the format of the mesh. For example, if you only add UVs to the first vertex, you cannot add color to any of the subsequent vertices. - See also [ArrayMesh], [ImmediateGeometry3D] and [MeshDataTool] for procedural geometry generation. + See also [ArrayMesh], [ImmediateMesh] and [MeshDataTool] for procedural geometry generation. [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes. </description> <tutorials> diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 3e4f382383..03914bec3b 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -738,8 +738,8 @@ void CodeTextEditor::_input(const Ref<InputEvent> &event) { accept_event(); return; } - if (ED_IS_SHORTCUT("script_text_editor/clone_down", key_event)) { - clone_lines_down(); + if (ED_IS_SHORTCUT("script_text_editor/duplicate_selection", key_event)) { + duplicate_selection(); accept_event(); return; } @@ -1287,7 +1287,7 @@ void CodeTextEditor::delete_lines() { text_editor->end_complex_operation(); } -void CodeTextEditor::clone_lines_down() { +void CodeTextEditor::duplicate_selection() { const int cursor_column = text_editor->cursor_get_column(); int from_line = text_editor->cursor_get_line(); int to_line = text_editor->cursor_get_line(); diff --git a/editor/code_editor.h b/editor/code_editor.h index 28b09e0a5d..0e5a84b3d5 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -225,7 +225,7 @@ public: void move_lines_up(); void move_lines_down(); void delete_lines(); - void clone_lines_down(); + void duplicate_selection(); /// Toggle inline comment on currently selected lines, or on current line if nothing is selected, /// by adding or removing comment delimiter diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index cfce37ea1b..e6c4c14830 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1182,15 +1182,19 @@ void EditorInspectorSection::_notification(int p_what) { Size2 size = get_size(); Point2 offset; + Rect2 rect; offset.y = font->get_height(font_size); if (arrow.is_valid()) { offset.y = MAX(offset.y, arrow->get_height()); } offset.y += get_theme_constant("vseparation", "Tree"); - offset.x += get_theme_constant("inspector_margin", "Editor"); - - Rect2 rect(offset, size - offset); + if (is_layout_rtl()) { + rect = Rect2(offset, size - offset - Vector2(get_theme_constant("inspector_margin", "Editor"), 0)); + } else { + offset.x += get_theme_constant("inspector_margin", "Editor"); + rect = Rect2(offset, size - offset); + } //set children for (int i = 0; i < get_child_count(); i++) { diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index c1540f2cdd..aa4a394d30 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -206,24 +206,34 @@ void EditorSpinSlider::_notification(int p_what) { // EditorSpinSliders with a label have more space on the left, so add an // higher margin to match the location where the text begins. // The margin values below were determined by empirical testing. - stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE); + if (is_layout_rtl()) { + stylebox->set_default_margin(SIDE_LEFT, 0); + stylebox->set_default_margin(SIDE_RIGHT, (get_label() != String() ? 23 : 16) * EDSCALE); + } else { + stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE); + stylebox->set_default_margin(SIDE_RIGHT, 0); + } value_input->add_theme_style_override("normal", stylebox); } if (p_what == NOTIFICATION_DRAW) { updown_offset = -1; + RID ci = get_canvas_item(); + bool rtl = is_layout_rtl(); + Vector2 size = get_size(); + Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit"); if (!flat) { - draw_style_box(sb, Rect2(Vector2(), get_size())); + draw_style_box(sb, Rect2(Vector2(), size)); } Ref<Font> font = get_theme_font("font", "LineEdit"); int font_size = get_theme_font_size("font_size", "LineEdit"); int sep_base = 4 * EDSCALE; int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better - int string_width = font->get_string_size(label, font_size).width; - int number_width = get_size().width - sb->get_minimum_size().width - string_width - sep; + int label_width = font->get_string_size(label, font_size).width; + int number_width = size.width - sb->get_minimum_size().width - label_width - sep; Ref<Texture2D> updown = get_theme_icon("updown", "SpinBox"); @@ -233,7 +243,7 @@ void EditorSpinSlider::_notification(int p_what) { String numstr = get_text_value(); - int vofs = (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size); + int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size); Color fc = get_theme_color("font_color", "LineEdit"); Color lc; @@ -245,30 +255,59 @@ void EditorSpinSlider::_notification(int p_what) { if (flat && label != String()) { Color label_bg_color = get_theme_color("dark_color_3", "Editor"); - draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + string_width, get_size().height)), label_bg_color); + if (rtl) { + draw_rect(Rect2(Vector2(size.width - (sb->get_offset().x * 2 + label_width), 0), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color); + } else { + draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color); + } } if (has_focus()) { Ref<StyleBox> focus = get_theme_stylebox("focus", "LineEdit"); - draw_style_box(focus, Rect2(Vector2(), get_size())); + draw_style_box(focus, Rect2(Vector2(), size)); } - draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5)); - - Vector2 text_ofs = Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs); - draw_string(font, text_ofs, numstr, HALIGN_LEFT, number_width, font_size, fc); + if (rtl) { + draw_string(font, Vector2(Math::round(size.width - sb->get_offset().x - label_width), vofs), label, HALIGN_RIGHT, -1, font_size, lc * Color(1, 1, 1, 0.5)); + } else { + draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5)); + } - if (suffix != String()) { - int sw = font->get_string_size(numstr).width; - text_ofs.x += sw; - fc.a *= 0.4; - draw_string(font, text_ofs, suffix, HALIGN_LEFT, MAX(0, number_width - sw), font_size, fc); + int suffix_start = numstr.length(); + RID num_rid = TS->create_shaped_text(); + TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size); + + float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep); + Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs); + const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(num_rid); + int v_size = visual.size(); + const TextServer::Glyph *glyphs = visual.ptr(); + for (int i = 0; i < v_size; i++) { + for (int j = 0; j < glyphs[i].repeat; j++) { + if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) { + Color color = fc; + if (glyphs[i].start >= suffix_start) { + color.a *= 0.4; + } + if (glyphs[i].font_rid != RID()) { + TS->font_draw_glyph(glyphs[i].font_rid, ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color); + } else if ((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { + TS->draw_hex_code_box(ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color); + } + } + text_ofs.x += glyphs[i].advance; + } } + TS->free(num_rid); if (get_step() == 1) { Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox"); - int updown_vofs = (get_size().height - updown2->get_height()) / 2; - updown_offset = get_size().width - sb->get_margin(SIDE_RIGHT) - updown2->get_width(); + int updown_vofs = (size.height - updown2->get_height()) / 2; + if (rtl) { + updown_offset = sb->get_margin(SIDE_LEFT); + } else { + updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width(); + } Color c(1, 1, 1); if (hover_updown) { c *= Color(1.2, 1.2, 1.2); @@ -279,9 +318,9 @@ void EditorSpinSlider::_notification(int p_what) { } } else if (!hide_slider) { int grabber_w = 4 * EDSCALE; - int width = get_size().width - sb->get_minimum_size().width - grabber_w; + int width = size.width - sb->get_minimum_size().width - grabber_w; int ofs = sb->get_offset().x; - int svofs = (get_size().height + vofs) / 2 - 1; + int svofs = (size.height + vofs) / 2 - 1; Color c = fc; c.a = 0.2; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 25002fd995..2830b942a3 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5423,24 +5423,32 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); unlock_button = memnew(Button); unlock_button->set_flat(true); hb->add_child(unlock_button); unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved).")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); group_button = memnew(Button); group_button->set_flat(true); hb->add_child(group_button); group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED)); group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); ungroup_button = memnew(Button); ungroup_button->set_flat(true); hb->add_child(ungroup_button); ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED)); ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); hb->add_child(memnew(VSeparator)); @@ -5478,7 +5486,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p = view_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_MASK_CMD | KEY_G), SHOW_GRID); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_NUMBERSIGN), SHOW_GRID); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index 7873c1b136..6f90d278bd 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -358,9 +358,9 @@ void CollisionPolygon3DEditor::_polygon_draw() { float depth = _get_depth() * 0.5; - imgeom->clear(); + imesh->clear_surfaces(); imgeom->set_material_override(line_material); - imgeom->begin(Mesh::PRIMITIVE_LINES, Ref<Texture2D>()); + imesh->surface_begin(Mesh::PRIMITIVE_LINES); Rect2 rect; @@ -382,10 +382,10 @@ void CollisionPolygon3DEditor::_polygon_draw() { Vector3 point = Vector3(p.x, p.y, depth); Vector3 next_point = Vector3(p2.x, p2.y, depth); - imgeom->set_color(Color(1, 0.3, 0.1, 0.8)); - imgeom->add_vertex(point); - imgeom->set_color(Color(1, 0.3, 0.1, 0.8)); - imgeom->add_vertex(next_point); + imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8)); + imesh->surface_add_vertex(point); + imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8)); + imesh->surface_add_vertex(next_point); //Color col=Color(1,0.3,0.1,0.8); //vpc->draw_line(point,next_point,col,2); @@ -402,45 +402,43 @@ void CollisionPolygon3DEditor::_polygon_draw() { r.size.y = rect.size.y; r.size.z = 0; - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0.3, 0, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0.0, 0.3, 0)); - - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0)); - - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0)); - - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + r.size); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + r.size - Vector3(0.3, 0, 0)); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + r.size); - imgeom->set_color(Color(0.8, 0.8, 0.8, 0.2)); - imgeom->add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0)); - - imgeom->end(); - - m->clear_surfaces(); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0)); + + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0)); + + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0)); + + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + r.size); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0)); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + r.size); + imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2)); + imesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0)); + + imesh->surface_end(); if (poly.size() == 0) { return; @@ -515,7 +513,9 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) { mode = MODE_EDIT; wip_active = false; - imgeom = memnew(ImmediateGeometry3D); + imgeom = memnew(MeshInstance3D); + imesh.instantiate(); + imgeom->set_mesh(imesh); imgeom->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001))); line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.h b/editor/plugins/collision_polygon_3d_editor_plugin.h index c66518e3e5..5db0f7308a 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.h +++ b/editor/plugins/collision_polygon_3d_editor_plugin.h @@ -34,8 +34,8 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/3d/collision_polygon_3d.h" -#include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/resources/immediate_mesh.h" class CanvasItemEditor; @@ -60,7 +60,8 @@ class CollisionPolygon3DEditor : public HBoxContainer { EditorNode *editor; Panel *panel; Node3D *node; - ImmediateGeometry3D *imgeom; + Ref<ImmediateMesh> imesh; + MeshInstance3D *imgeom; MeshInstance3D *pointsm; Ref<ArrayMesh> m; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index d964644d38..b2cbd56b1a 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -6778,6 +6778,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); @@ -6785,6 +6787,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); tool_button[TOOL_GROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); @@ -6792,6 +6796,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.write[0] = MENU_GROUP_SELECTED; tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); @@ -6799,6 +6805,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.write[0] = MENU_UNGROUP_SELECTED; tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); hbc_menu->add_child(memnew(VSeparator)); @@ -6917,7 +6925,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN); - p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_MASK_CMD + KEY_G), MENU_VIEW_GRID); + p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_NUMBERSIGN), MENU_VIEW_GRID); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index fa432a5868..02f89a12de 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "editor/editor_scale.h" -#include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/visual_instance_3d.h" #include "scene/3d/world_environment.h" diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 5fc1f74089..bec2814462 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1051,8 +1051,8 @@ void ScriptTextEditor::_edit_option(int p_op) { case EDIT_DELETE_LINE: { code_editor->delete_lines(); } break; - case EDIT_CLONE_DOWN: { - code_editor->clone_lines_down(); + case EDIT_DUPLICATE_SELECTION: { + code_editor->duplicate_selection(); } break; case EDIT_TOGGLE_FOLD_LINE: { tx->toggle_foldable_line(tx->cursor_get_line()); @@ -1759,7 +1759,7 @@ void ScriptTextEditor::_enable_code_editor() { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES); edit_menu->get_popup()->add_separator(); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/evaluate_selection"), EDIT_EVALUATE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE); @@ -1933,9 +1933,9 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0); ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); #ifdef OSX_ENABLED - ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); + ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); #else - ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D); + ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D); #endif ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E); ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 8a8e9aa737..e4a13951e4 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -117,7 +117,7 @@ class ScriptTextEditor : public ScriptEditorBase { EDIT_INDENT_RIGHT, EDIT_INDENT_LEFT, EDIT_DELETE_LINE, - EDIT_CLONE_DOWN, + EDIT_DUPLICATE_SELECTION, EDIT_PICK_COLOR, EDIT_TO_UPPERCASE, EDIT_TO_LOWERCASE, diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 173f1dd7fb..c1216a9732 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -334,8 +334,8 @@ void ShaderEditor::_menu_option(int p_option) { case EDIT_DELETE_LINE: { shader_editor->delete_lines(); } break; - case EDIT_CLONE_DOWN: { - shader_editor->clone_lines_down(); + case EDIT_DUPLICATE_SELECTION: { + shader_editor->duplicate_selection(); } break; case EDIT_TOGGLE_COMMENT: { if (shader.is_null()) { @@ -692,7 +692,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION); edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE); edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option)); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index d7da73f2ae..77579754d3 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -91,7 +91,7 @@ class ShaderEditor : public PanelContainer { EDIT_INDENT_LEFT, EDIT_INDENT_RIGHT, EDIT_DELETE_LINE, - EDIT_CLONE_DOWN, + EDIT_DUPLICATE_SELECTION, EDIT_TOGGLE_COMMENT, EDIT_COMPLETE, SEARCH_FIND, diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index d62be993af..5766646f7d 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -328,8 +328,8 @@ void TextEditor::_edit_option(int p_op) { case EDIT_DELETE_LINE: { code_editor->delete_lines(); } break; - case EDIT_CLONE_DOWN: { - code_editor->clone_lines_down(); + case EDIT_DUPLICATE_SELECTION: { + code_editor->duplicate_selection(); } break; case EDIT_TOGGLE_FOLD_LINE: { tx->toggle_foldable_line(tx->cursor_get_line()); @@ -559,7 +559,7 @@ TextEditor::TextEditor() { edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/fold_all_lines"), EDIT_FOLD_ALL_LINES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES); edit_menu->get_popup()->add_separator(); - edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_spaces"), EDIT_CONVERT_INDENT_TO_SPACES); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_tabs"), EDIT_CONVERT_INDENT_TO_TABS); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 4e667dc676..86a4910ac0 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -66,7 +66,7 @@ private: EDIT_INDENT_RIGHT, EDIT_INDENT_LEFT, EDIT_DELETE_LINE, - EDIT_CLONE_DOWN, + EDIT_DUPLICATE_SELECTION, EDIT_TO_UPPERCASE, EDIT_TO_LOWERCASE, EDIT_CAPITALIZE, diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index e63818ef07..262861cb11 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1409,7 +1409,7 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pai _fill_path_renames(base_path, new_base_path, p_node, p_renames); } -bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &p_node_path, List<Pair<NodePath, NodePath>> *p_renames) { +bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames) { NodePath root_path_new = p_root_path; for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) { if (p_root_path == F->get().first) { @@ -1423,7 +1423,7 @@ bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &p_n NodePath rel_path_old = p_root_path.rel_path_to(F->get().first); // If old path detected, then it needs to be replaced with the new one. - if (p_node_path == rel_path_old) { + if (r_node_path == rel_path_old) { NodePath rel_path_new = F->get().second; // If not empty, get new relative path. @@ -1431,16 +1431,16 @@ bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &p_n rel_path_new = root_path_new.rel_path_to(rel_path_new); } - p_node_path = rel_path_new; + r_node_path = rel_path_new; return true; } // Update the node itself if it has a valid node path and has not been deleted. - if (p_root_path == F->get().first && p_node_path != NodePath() && F->get().second != NodePath()) { - NodePath abs_path = NodePath(String(root_path_new).plus_file(p_node_path)).simplified(); + if (p_root_path == F->get().first && r_node_path != NodePath() && F->get().second != NodePath()) { + NodePath abs_path = NodePath(String(root_path_new).plus_file(r_node_path)).simplified(); NodePath rel_path_new = F->get().second.rel_path_to(abs_path); - p_node_path = rel_path_new; + r_node_path = rel_path_new; return true; } } @@ -1448,18 +1448,18 @@ bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &p_n return false; } -bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Variant &p_variant, List<Pair<NodePath, NodePath>> *p_renames) { - switch (p_variant.get_type()) { +bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames) { + switch (r_variant.get_type()) { case Variant::NODE_PATH: { - NodePath node_path = p_variant; + NodePath node_path = r_variant; if (_update_node_path(p_root_path, node_path, p_renames)) { - p_variant = node_path; + r_variant = node_path; return true; } } break; case Variant::ARRAY: { - Array a = p_variant; + Array a = r_variant; bool updated = false; for (int i = 0; i < a.size(); i++) { Variant value = a[i]; @@ -1472,13 +1472,13 @@ bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Vari } } if (updated) { - p_variant = a; + r_variant = a; return true; } } break; case Variant::DICTIONARY: { - Dictionary d = p_variant; + Dictionary d = r_variant; bool updated = false; for (int i = 0; i < d.size(); i++) { Variant value = d.get_value_at_index(i); @@ -1491,7 +1491,7 @@ bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Vari } } if (updated) { - p_variant = d; + r_variant = d; return true; } } break; diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index d2a68ebd2e..88c4a85f4c 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -247,8 +247,8 @@ class SceneTreeDock : public VBoxContainer { static SceneTreeDock *singleton; static void _update_configuration_warning(); - static bool _update_node_path(const NodePath &p_root_path, NodePath &p_node_path, List<Pair<NodePath, NodePath>> *p_renames); - static bool _check_node_path_recursive(const NodePath &p_root_path, Variant &p_variant, List<Pair<NodePath, NodePath>> *p_renames); + static bool _update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames); + static bool _check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames); protected: void _notification(int p_what); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 926997a715..f293081987 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -178,20 +178,23 @@ Transform2D Camera2D::get_camera_transform() { } Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom); - if (screen_rect.position.x < limit[SIDE_LEFT]) { - screen_rect.position.x = limit[SIDE_LEFT]; - } - if (screen_rect.position.x + screen_rect.size.x > limit[SIDE_RIGHT]) { - screen_rect.position.x = limit[SIDE_RIGHT] - screen_rect.size.x; - } + if (!limit_smoothing_enabled) { + if (screen_rect.position.x < limit[SIDE_LEFT]) { + screen_rect.position.x = limit[SIDE_LEFT]; + } - if (screen_rect.position.y + screen_rect.size.y > limit[SIDE_BOTTOM]) { - screen_rect.position.y = limit[SIDE_BOTTOM] - screen_rect.size.y; - } + if (screen_rect.position.x + screen_rect.size.x > limit[SIDE_RIGHT]) { + screen_rect.position.x = limit[SIDE_RIGHT] - screen_rect.size.x; + } + + if (screen_rect.position.y + screen_rect.size.y > limit[SIDE_BOTTOM]) { + screen_rect.position.y = limit[SIDE_BOTTOM] - screen_rect.size.y; + } - if (screen_rect.position.y < limit[SIDE_TOP]) { - screen_rect.position.y = limit[SIDE_TOP]; + if (screen_rect.position.y < limit[SIDE_TOP]) { + screen_rect.position.y = limit[SIDE_TOP]; + } } if (offset != Vector2()) { diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index a633923be7..93d154bb01 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -31,7 +31,6 @@ #include "collision_object_2d.h" #include "scene/scene_string_names.h" -#include "servers/physics_server_2d.h" void CollisionObject2D::_notification(int p_what) { switch (p_what) { @@ -44,16 +43,22 @@ void CollisionObject2D::_notification(int p_what) { PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform); } - RID space = get_world_2d()->get_space(); - if (area) { - PhysicsServer2D::get_singleton()->area_set_space(rid, space); - } else { - PhysicsServer2D::get_singleton()->body_set_space(rid, space); + bool disabled = !is_enabled(); + + if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) { + _apply_disabled(); } - _update_pickable(); + if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) { + RID space = get_world_2d()->get_space(); + if (area) { + PhysicsServer2D::get_singleton()->area_set_space(rid, space); + } else { + PhysicsServer2D::get_singleton()->body_set_space(rid, space); + } + } - //get space + _update_pickable(); } break; case NOTIFICATION_ENTER_CANVAS: { @@ -67,6 +72,7 @@ void CollisionObject2D::_notification(int p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); } break; + case NOTIFICATION_TRANSFORM_CHANGED: { if (only_update_transform_changes) { return; @@ -79,15 +85,22 @@ void CollisionObject2D::_notification(int p_what) { } else { PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform); } - } break; + case NOTIFICATION_EXIT_TREE: { - if (area) { - PhysicsServer2D::get_singleton()->area_set_space(rid, RID()); - } else { - PhysicsServer2D::get_singleton()->body_set_space(rid, RID()); + bool disabled = !is_enabled(); + + if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) { + if (area) { + PhysicsServer2D::get_singleton()->area_set_space(rid, RID()); + } else { + PhysicsServer2D::get_singleton()->body_set_space(rid, RID()); + } } + if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) { + _apply_enabled(); + } } break; case NOTIFICATION_EXIT_CANVAS: { @@ -97,6 +110,14 @@ void CollisionObject2D::_notification(int p_what) { PhysicsServer2D::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID()); } } break; + + case NOTIFICATION_DISABLED: { + _apply_disabled(); + } break; + + case NOTIFICATION_ENABLED: { + _apply_enabled(); + } break; } } @@ -158,6 +179,79 @@ bool CollisionObject2D::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } +void CollisionObject2D::set_disable_mode(DisableMode p_mode) { + if (disable_mode == p_mode) { + return; + } + + bool disabled = is_inside_tree() && !is_enabled(); + + if (disabled) { + // Cancel previous disable mode. + _apply_enabled(); + } + + disable_mode = p_mode; + + if (disabled) { + // Apply new disable mode. + _apply_disabled(); + } +} + +CollisionObject2D::DisableMode CollisionObject2D::get_disable_mode() const { + return disable_mode; +} + +void CollisionObject2D::_apply_disabled() { + switch (disable_mode) { + case DISABLE_MODE_REMOVE: { + if (is_inside_tree()) { + if (area) { + PhysicsServer2D::get_singleton()->area_set_space(rid, RID()); + } else { + PhysicsServer2D::get_singleton()->body_set_space(rid, RID()); + } + } + } break; + + case DISABLE_MODE_MAKE_STATIC: { + if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) { + PhysicsServer2D::get_singleton()->body_set_mode(rid, PhysicsServer2D::BODY_MODE_STATIC); + } + } break; + + case DISABLE_MODE_KEEP_ACTIVE: { + // Nothing to do. + } break; + } +} + +void CollisionObject2D::_apply_enabled() { + switch (disable_mode) { + case DISABLE_MODE_REMOVE: { + if (is_inside_tree()) { + RID space = get_world_2d()->get_space(); + if (area) { + PhysicsServer2D::get_singleton()->area_set_space(rid, space); + } else { + PhysicsServer2D::get_singleton()->body_set_space(rid, space); + } + } + } break; + + case DISABLE_MODE_MAKE_STATIC: { + if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) { + PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode); + } + } break; + + case DISABLE_MODE_KEEP_ACTIVE: { + // Nothing to do. + } break; + } +} + uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) { ShapeData sd; uint32_t id; @@ -412,6 +506,22 @@ bool CollisionObject2D::is_only_update_transform_changes_enabled() const { return only_update_transform_changes; } +void CollisionObject2D::set_body_mode(PhysicsServer2D::BodyMode p_mode) { + ERR_FAIL_COND(area); + + if (body_mode == p_mode) { + return; + } + + body_mode = p_mode; + + if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) { + return; + } + + PhysicsServer2D::get_singleton()->body_set_mode(rid, p_mode); +} + void CollisionObject2D::_update_pickable() { if (!is_inside_tree()) { return; @@ -445,6 +555,8 @@ void CollisionObject2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject2D::get_collision_layer_bit); ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject2D::set_collision_mask_bit); ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject2D::get_collision_mask_bit); + ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject2D::set_disable_mode); + ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject2D::get_disable_mode); ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable); ClassDB::bind_method(D_METHOD("is_pickable"), &CollisionObject2D::is_pickable); ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject2D::create_shape_owner); @@ -473,12 +585,18 @@ void CollisionObject2D::_bind_methods() { ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); + ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode"); + ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Input", "input_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_pickable"), "set_pickable", "is_pickable"); + + BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE); + BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC); + BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { @@ -493,6 +611,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { PhysicsServer2D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { PhysicsServer2D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode); } } diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index e10f3097d9..7a71affbb5 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -33,10 +33,19 @@ #include "scene/2d/node_2d.h" #include "scene/resources/shape_2d.h" +#include "servers/physics_server_2d.h" class CollisionObject2D : public Node2D { GDCLASS(CollisionObject2D, Node2D); +public: + enum DisableMode { + DISABLE_MODE_REMOVE, + DISABLE_MODE_MAKE_STATIC, + DISABLE_MODE_KEEP_ACTIVE, + }; + +private: uint32_t collision_layer = 1; uint32_t collision_mask = 1; @@ -44,6 +53,10 @@ class CollisionObject2D : public Node2D { RID rid; bool pickable = false; + DisableMode disable_mode = DISABLE_MODE_REMOVE; + + PhysicsServer2D::BodyMode body_mode = PhysicsServer2D::BODY_MODE_STATIC; + struct ShapeData { Object *owner = nullptr; Transform2D xform; @@ -64,6 +77,9 @@ class CollisionObject2D : public Node2D { Map<uint32_t, ShapeData> shapes; bool only_update_transform_changes = false; //this is used for sync physics in CharacterBody2D + void _apply_disabled(); + void _apply_enabled(); + protected: CollisionObject2D(RID p_rid, bool p_area); @@ -79,6 +95,8 @@ protected: void set_only_update_transform_changes(bool p_enable); bool is_only_update_transform_changes_enabled() const; + void set_body_mode(PhysicsServer2D::BodyMode p_mode); + public: void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; @@ -92,6 +110,9 @@ public: void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; + void set_disable_mode(DisableMode p_mode); + DisableMode get_disable_mode() const; + uint32_t create_shape_owner(Object *p_owner); void remove_shape_owner(uint32_t owner); void get_shape_owners(List<uint32_t> *r_owners); @@ -131,4 +152,6 @@ public: ~CollisionObject2D(); }; +VARIANT_ENUM_CAST(CollisionObject2D::DisableMode); + #endif // COLLISION_OBJECT_2D_H diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index 0c1be16174..d547914e16 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -31,33 +31,37 @@ #include "physical_bone_2d.h" void PhysicalBone2D::_notification(int p_what) { - if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { - // Position the RigidBody in the correct position - if (follow_bone_when_simulating) { - _position_at_bone2d(); - } + switch (p_what) { + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // Position the RigidBody in the correct position. + if (follow_bone_when_simulating) { + _position_at_bone2d(); + } - // Keep the child joint in the correct position. - if (child_joint && auto_configure_joint) { - child_joint->set_global_position(get_global_position()); - } - } else if (p_what == NOTIFICATION_READY) { - _find_skeleton_parent(); - _find_joint_child(); + // Keep the child joint in the correct position. + if (child_joint && auto_configure_joint) { + child_joint->set_global_position(get_global_position()); + } + } break; - // Configure joint - if (child_joint && auto_configure_joint) { - _auto_configure_joint(); - } + case NOTIFICATION_READY: { + _find_skeleton_parent(); + _find_joint_child(); - // Simulate physics if set - if (simulate_physics) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); - } + // Configure joint. + if (child_joint && auto_configure_joint) { + _auto_configure_joint(); + } + + // Simulate physics if set. + if (simulate_physics) { + _start_physics_simulation(); + } else { + _stop_physics_simulation(); + } - set_physics_process_internal(true); + set_physics_process_internal(true); + } break; } } @@ -156,16 +160,16 @@ void PhysicalBone2D::_start_physics_simulation() { // Apply the correct mode RigidBody2D::Mode rigid_mode = get_mode(); if (rigid_mode == RigidBody2D::MODE_STATIC) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_STATIC); } else if (rigid_mode == RigidBody2D::MODE_DYNAMIC) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC); } else if (rigid_mode == RigidBody2D::MODE_KINEMATIC) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC); } else if (rigid_mode == RigidBody2D::MODE_DYNAMIC_LOCKED) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC_LOCKED); + set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED); } else { - // Default to Rigid - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC); + // Default to Dynamic. + set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC); } _internal_simulate_physics = true; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 7c41cd98fb..be619ed60d 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -49,7 +49,7 @@ void PhysicsBody2D::_bind_methods() { PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) : CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), p_mode); + set_body_mode(p_mode); set_pickable(false); } @@ -219,9 +219,9 @@ void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) { kinematic_motion = p_enabled; if (kinematic_motion) { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC); } else { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_STATIC); } _update_kinematic_motion(); @@ -232,28 +232,30 @@ bool StaticBody2D::is_kinematic_motion_enabled() const { } void StaticBody2D::_notification(int p_what) { - if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { + switch (p_what) { + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - return; - } + if (Engine::get_singleton()->is_editor_hint()) { + return; + } #endif - ERR_FAIL_COND(!kinematic_motion); + ERR_FAIL_COND(!kinematic_motion); - real_t delta_time = get_physics_process_delta_time(); + real_t delta_time = get_physics_process_delta_time(); - Transform2D new_transform = get_global_transform(); + Transform2D new_transform = get_global_transform(); - new_transform.translate(constant_linear_velocity * delta_time); - new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time); + new_transform.translate(constant_linear_velocity * delta_time); + new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time); - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); - // Propagate transform change to node. - set_block_transform_notify(true); - set_global_transform(new_transform); - set_block_transform_notify(false); + // Propagate transform change to node. + set_block_transform_notify(true); + set_global_transform(new_transform); + set_block_transform_notify(false); + } break; } } @@ -528,18 +530,18 @@ void RigidBody2D::set_mode(Mode p_mode) { mode = p_mode; switch (p_mode) { case MODE_DYNAMIC: { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC); } break; case MODE_STATIC: { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_STATIC); } break; case MODE_KINEMATIC: { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC); } break; case MODE_DYNAMIC_LOCKED: { - PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED); + set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED); } break; } @@ -795,18 +797,19 @@ bool RigidBody2D::is_contact_monitor_enabled() const { void RigidBody2D::_notification(int p_what) { #ifdef TOOLS_ENABLED - if (p_what == NOTIFICATION_ENTER_TREE) { - if (Engine::get_singleton()->is_editor_hint()) { - set_notify_local_transform(true); //used for warnings and only in editor - } - } + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (Engine::get_singleton()->is_editor_hint()) { + set_notify_local_transform(true); //used for warnings and only in editor + } + } break; - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - } + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warnings(); + } + } break; } - #endif } @@ -1261,26 +1264,28 @@ void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) { } void CharacterBody2D::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - last_valid_transform = get_global_transform(); - - // Reset move_and_slide() data. - on_floor = false; - on_floor_body = RID(); - on_ceiling = false; - on_wall = false; - motion_results.clear(); - floor_velocity = Vector2(); - } + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + last_valid_transform = get_global_transform(); + + // Reset move_and_slide() data. + on_floor = false; + on_floor_body = RID(); + on_ceiling = false; + on_wall = false; + motion_results.clear(); + floor_velocity = Vector2(); + } break; - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - //used by sync to physics, send the new transform to the physics - Transform2D new_transform = get_global_transform(); - PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); - //but then revert changes - set_notify_local_transform(false); - set_global_transform(last_valid_transform); - set_notify_local_transform(true); + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + // Used by sync to physics, send the new transform to the physics. + Transform2D new_transform = get_global_transform(); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); + // But then revert changes. + set_notify_local_transform(false); + set_global_transform(last_valid_transform); + set_notify_local_transform(true); + } break; } } diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index a04667e53b..40e3f7c764 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -32,7 +32,6 @@ #include "core/config/engine.h" #include "scene/scene_string_names.h" -#include "servers/physics_server_3d.h" void CollisionObject3D::_notification(int p_what) { switch (p_what) { @@ -59,15 +58,22 @@ void CollisionObject3D::_notification(int p_what) { PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); } - RID space = get_world_3d()->get_space(); - if (area) { - PhysicsServer3D::get_singleton()->area_set_space(rid, space); - } else { - PhysicsServer3D::get_singleton()->body_set_space(rid, space); + bool disabled = !is_enabled(); + + if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) { + _apply_disabled(); + } + + if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) { + RID space = get_world_3d()->get_space(); + if (area) { + PhysicsServer3D::get_singleton()->area_set_space(rid, space); + } else { + PhysicsServer3D::get_singleton()->body_set_space(rid, space); + } } _update_pickable(); - //get space } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -78,19 +84,34 @@ void CollisionObject3D::_notification(int p_what) { } _on_transform_changed(); - } break; + case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); - } break; + case NOTIFICATION_EXIT_WORLD: { - if (area) { - PhysicsServer3D::get_singleton()->area_set_space(rid, RID()); - } else { - PhysicsServer3D::get_singleton()->body_set_space(rid, RID()); + bool disabled = !is_enabled(); + + if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) { + if (area) { + PhysicsServer3D::get_singleton()->area_set_space(rid, RID()); + } else { + PhysicsServer3D::get_singleton()->body_set_space(rid, RID()); + } + } + + if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) { + _apply_enabled(); } + } break; + case NOTIFICATION_DISABLED: { + _apply_disabled(); + } break; + + case NOTIFICATION_ENABLED: { + _apply_enabled(); } break; } } @@ -153,6 +174,79 @@ bool CollisionObject3D::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } +void CollisionObject3D::set_disable_mode(DisableMode p_mode) { + if (disable_mode == p_mode) { + return; + } + + bool disabled = is_inside_tree() && !is_enabled(); + + if (disabled) { + // Cancel previous disable mode. + _apply_enabled(); + } + + disable_mode = p_mode; + + if (disabled) { + // Apply new disable mode. + _apply_disabled(); + } +} + +CollisionObject3D::DisableMode CollisionObject3D::get_disable_mode() const { + return disable_mode; +} + +void CollisionObject3D::_apply_disabled() { + switch (disable_mode) { + case DISABLE_MODE_REMOVE: { + if (is_inside_tree()) { + if (area) { + PhysicsServer3D::get_singleton()->area_set_space(rid, RID()); + } else { + PhysicsServer3D::get_singleton()->body_set_space(rid, RID()); + } + } + } break; + + case DISABLE_MODE_MAKE_STATIC: { + if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) { + PhysicsServer3D::get_singleton()->body_set_mode(rid, PhysicsServer3D::BODY_MODE_STATIC); + } + } break; + + case DISABLE_MODE_KEEP_ACTIVE: { + // Nothing to do. + } break; + } +} + +void CollisionObject3D::_apply_enabled() { + switch (disable_mode) { + case DISABLE_MODE_REMOVE: { + if (is_inside_tree()) { + RID space = get_world_3d()->get_space(); + if (area) { + PhysicsServer3D::get_singleton()->area_set_space(rid, space); + } else { + PhysicsServer3D::get_singleton()->body_set_space(rid, space); + } + } + } break; + + case DISABLE_MODE_MAKE_STATIC: { + if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) { + PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode); + } + } break; + + case DISABLE_MODE_KEEP_ACTIVE: { + // Nothing to do. + } break; + } +} + void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { if (get_script_instance()) { get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); @@ -174,6 +268,22 @@ void CollisionObject3D::_mouse_exit() { emit_signal(SceneStringNames::get_singleton()->mouse_exited); } +void CollisionObject3D::set_body_mode(PhysicsServer3D::BodyMode p_mode) { + ERR_FAIL_COND(area); + + if (body_mode == p_mode) { + return; + } + + body_mode = p_mode; + + if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) { + return; + } + + PhysicsServer3D::get_singleton()->body_set_mode(rid, p_mode); +} + void CollisionObject3D::_update_pickable() { if (!is_inside_tree()) { return; @@ -305,6 +415,8 @@ void CollisionObject3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject3D::get_collision_layer_bit); ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject3D::set_collision_mask_bit); ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject3D::get_collision_mask_bit); + ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject3D::set_disable_mode); + ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject3D::get_disable_mode); ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable); ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable); ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag); @@ -332,6 +444,8 @@ void CollisionObject3D::_bind_methods() { ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); + ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode"); + ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); @@ -339,6 +453,10 @@ void CollisionObject3D::_bind_methods() { ADD_GROUP("Input", "input_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); + + BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE); + BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC); + BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) { @@ -540,8 +658,8 @@ CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) { PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { PhysicsServer3D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode); } - //set_transform_notify(true); } void CollisionObject3D::set_capture_input_on_drag(bool p_capture) { diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index 50a9b4fcd0..a3a890db75 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -33,10 +33,19 @@ #include "scene/3d/node_3d.h" #include "scene/resources/shape_3d.h" +#include "servers/physics_server_3d.h" class CollisionObject3D : public Node3D { GDCLASS(CollisionObject3D, Node3D); +public: + enum DisableMode { + DISABLE_MODE_REMOVE, + DISABLE_MODE_MAKE_STATIC, + DISABLE_MODE_KEEP_ACTIVE, + }; + +private: uint32_t collision_layer = 1; uint32_t collision_mask = 1; @@ -44,6 +53,10 @@ class CollisionObject3D : public Node3D { RID rid; + DisableMode disable_mode = DISABLE_MODE_REMOVE; + + PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC; + struct ShapeData { Object *owner = nullptr; Transform3D xform; @@ -76,6 +89,9 @@ class CollisionObject3D : public Node3D { void _update_debug_shapes(); void _clear_debug_shapes(); + void _apply_disabled(); + void _apply_enabled(); + protected: CollisionObject3D(RID p_rid, bool p_area); @@ -89,6 +105,8 @@ protected: virtual void _mouse_enter(); virtual void _mouse_exit(); + void set_body_mode(PhysicsServer3D::BodyMode p_mode); + public: void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; @@ -102,6 +120,9 @@ public: void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; + void set_disable_mode(DisableMode p_mode); + DisableMode get_disable_mode() const; + uint32_t create_shape_owner(Object *p_owner); void remove_shape_owner(uint32_t owner); void get_shape_owners(List<uint32_t> *r_owners); @@ -138,4 +159,6 @@ public: ~CollisionObject3D(); }; +VARIANT_ENUM_CAST(CollisionObject3D::DisableMode); + #endif // COLLISION_OBJECT__H diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp deleted file mode 100644 index d64babaa9d..0000000000 --- a/scene/3d/immediate_geometry_3d.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry_3d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "immediate_geometry_3d.h" - -void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) { - RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); - if (p_texture.is_valid()) { - cached_textures.push_back(p_texture); - } -} - -void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) { - RS::get_singleton()->immediate_normal(im, p_normal); -} - -void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) { - RS::get_singleton()->immediate_tangent(im, p_tangent); -} - -void ImmediateGeometry3D::set_color(const Color &p_color) { - RS::get_singleton()->immediate_color(im, p_color); -} - -void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) { - RS::get_singleton()->immediate_uv(im, p_uv); -} - -void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) { - RS::get_singleton()->immediate_uv2(im, p_uv2); -} - -void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) { - RS::get_singleton()->immediate_vertex(im, p_vertex); - if (empty) { - aabb.position = p_vertex; - aabb.size = Vector3(); - empty = false; - } else { - aabb.expand_to(p_vertex); - } -} - -void ImmediateGeometry3D::end() { - RS::get_singleton()->immediate_end(im); -} - -void ImmediateGeometry3D::clear() { - RS::get_singleton()->immediate_clear(im); - empty = true; - cached_textures.clear(); -} - -AABB ImmediateGeometry3D::get_aabb() const { - return aabb; -} - -Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const { - return Vector<Face3>(); -} - -void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { - const double lat_step = Math_TAU / p_lats; - const double lon_step = Math_TAU / p_lons; - - for (int i = 1; i <= p_lats; i++) { - double lat0 = lat_step * (i - 1) - Math_TAU / 4; - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = lat_step * i - Math_TAU / 4; - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for (int j = p_lons; j >= 1; j--) { - double lng0 = lon_step * (j - 1); - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = lon_step * j; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v[4] = { - Vector3(x1 * zr0, z0, y1 * zr0), - Vector3(x1 * zr1, z1, y1 * zr1), - Vector3(x0 * zr1, z1, y0 * zr1), - Vector3(x0 * zr0, z0, y0 * zr0) - }; - -#define ADD_POINT(m_idx) \ - if (p_add_uv) { \ - set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \ - set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \ - } \ - set_normal(v[m_idx]); \ - add_vertex(v[m_idx] * p_radius); - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } -} - -void ImmediateGeometry3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref<Texture2D>())); - ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal); - ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent); - ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry3D::set_color); - ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry3D::set_uv); - ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry3D::set_uv2); - ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry3D::add_vertex); - ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry3D::add_sphere, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry3D::end); - ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry3D::clear); -} - -ImmediateGeometry3D::ImmediateGeometry3D() { - im = RenderingServer::get_singleton()->immediate_create(); - set_base(im); -} - -ImmediateGeometry3D::~ImmediateGeometry3D() { - RenderingServer::get_singleton()->free(im); -} diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h deleted file mode 100644 index ee4938d9f7..0000000000 --- a/scene/3d/immediate_geometry_3d.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry_3d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef IMMEDIATE_GEOMETRY_3D_H -#define IMMEDIATE_GEOMETRY_3D_H - -#include "scene/3d/visual_instance_3d.h" -#include "scene/resources/mesh.h" - -class ImmediateGeometry3D : public GeometryInstance3D { - GDCLASS(ImmediateGeometry3D, GeometryInstance3D); - - RID im; - //a list of textures drawn need to be kept, to avoid references - // in RenderingServer from becoming invalid if the texture is no longer used - List<Ref<Texture2D>> cached_textures; - bool empty = true; - AABB aabb; - -protected: - static void _bind_methods(); - -public: - void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture = Ref<Texture2D>()); - void set_normal(const Vector3 &p_normal); - void set_tangent(const Plane &p_tangent); - void set_color(const Color &p_color); - void set_uv(const Vector2 &p_uv); - void set_uv2(const Vector2 &p_uv2); - - void add_vertex(const Vector3 &p_vertex); - - void end(); - void clear(); - - void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true); - - virtual AABB get_aabb() const override; - virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override; - - ImmediateGeometry3D(); - ~ImmediateGeometry3D(); -}; - -#endif // IMMEDIATE_GEOMETRY_H diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index cb2a873f62..e7482d35e7 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -65,7 +65,7 @@ void PhysicsBody3D::_bind_methods() { PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) : CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode); + set_body_mode(p_mode); } PhysicsBody3D::~PhysicsBody3D() { @@ -233,9 +233,9 @@ void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) { kinematic_motion = p_enabled; if (kinematic_motion) { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC); } else { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC); + set_body_mode(PhysicsServer3D::BODY_MODE_STATIC); } _update_kinematic_motion(); @@ -282,35 +282,37 @@ Vector3 StaticBody3D::get_angular_velocity() const { } void StaticBody3D::_notification(int p_what) { - if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { + switch (p_what) { + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - return; - } + if (Engine::get_singleton()->is_editor_hint()) { + return; + } #endif - ERR_FAIL_COND(!kinematic_motion); + ERR_FAIL_COND(!kinematic_motion); - real_t delta_time = get_physics_process_delta_time(); + real_t delta_time = get_physics_process_delta_time(); - Transform3D new_transform = get_global_transform(); - new_transform.origin += constant_linear_velocity * delta_time; + Transform3D new_transform = get_global_transform(); + new_transform.origin += constant_linear_velocity * delta_time; - real_t ang_vel = constant_angular_velocity.length(); - if (!Math::is_zero_approx(ang_vel)) { - Vector3 ang_vel_axis = constant_angular_velocity / ang_vel; - Basis rot(ang_vel_axis, ang_vel * delta_time); - new_transform.basis = rot * new_transform.basis; - new_transform.orthonormalize(); - } + real_t ang_vel = constant_angular_velocity.length(); + if (!Math::is_zero_approx(ang_vel)) { + Vector3 ang_vel_axis = constant_angular_velocity / ang_vel; + Basis rot(ang_vel_axis, ang_vel * delta_time); + new_transform.basis = rot * new_transform.basis; + new_transform.orthonormalize(); + } - PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform); - // Propagate transform change to node. - set_ignore_transform_notification(true); - set_global_transform(new_transform); - set_ignore_transform_notification(false); - _on_transform_changed(); + // Propagate transform change to node. + set_ignore_transform_notification(true); + set_global_transform(new_transform); + set_ignore_transform_notification(false); + _on_transform_changed(); + } break; } } @@ -598,18 +600,19 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { void RigidBody3D::_notification(int p_what) { #ifdef TOOLS_ENABLED - if (p_what == NOTIFICATION_ENTER_TREE) { - if (Engine::get_singleton()->is_editor_hint()) { - set_notify_local_transform(true); //used for warnings and only in editor - } - } + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (Engine::get_singleton()->is_editor_hint()) { + set_notify_local_transform(true); //used for warnings and only in editor + } + } break; - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - } + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warnings(); + } + } break; } - #endif } @@ -617,18 +620,16 @@ void RigidBody3D::set_mode(Mode p_mode) { mode = p_mode; switch (p_mode) { case MODE_DYNAMIC: { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); } break; case MODE_STATIC: { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC); - + set_body_mode(PhysicsServer3D::BODY_MODE_STATIC); } break; case MODE_DYNAMIC_LOCKED: { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED); - + set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED); } break; case MODE_KINEMATIC: { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC); } break; } update_configuration_warnings(); @@ -1262,14 +1263,16 @@ void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) { } void CharacterBody3D::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - // Reset move_and_slide() data. - on_floor = false; - on_floor_body = RID(); - on_ceiling = false; - on_wall = false; - motion_results.clear(); - floor_velocity = Vector3(); + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + // Reset move_and_slide() data. + on_floor = false; + on_floor_body = RID(); + on_ceiling = false; + on_wall = false; + motion_results.clear(); + floor_velocity = Vector3(); + } break; } } @@ -2121,7 +2124,8 @@ void PhysicalBone3D::_notification(int p_what) { _reload_joint(); } break; - case NOTIFICATION_EXIT_TREE: + + case NOTIFICATION_EXIT_TREE: { if (parent_skeleton) { if (-1 != bone_id) { parent_skeleton->unbind_physical_bone_from_bone(bone_id); @@ -2131,12 +2135,13 @@ void PhysicalBone3D::_notification(int p_what) { } parent_skeleton = nullptr; PhysicsServer3D::get_singleton()->joint_clear(joint); - break; - case NOTIFICATION_TRANSFORM_CHANGED: + } break; + + case NOTIFICATION_TRANSFORM_CHANGED: { if (Engine::get_singleton()->is_editor_hint()) { update_offset(); } - break; + } break; } } @@ -2620,7 +2625,7 @@ void PhysicalBone3D::_start_physics_simulation() { return; } reset_to_rest_position(); - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed)); @@ -2633,11 +2638,11 @@ void PhysicalBone3D::_stop_physics_simulation() { return; } if (parent_skeleton->get_animate_physical_bones()) { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); + set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); } else { - PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC); + set_body_mode(PhysicsServer3D::BODY_MODE_STATIC); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0); } diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 9592fe5849..efd8a2b50c 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -81,7 +81,7 @@ void SoftBodyRenderingServerHandler::close() { } void SoftBodyRenderingServerHandler::commit_changes() { - RS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer); } void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { @@ -266,12 +266,13 @@ void SoftBody3D::_notification(int p_what) { PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space); prepare_physics_server(); } break; + case NOTIFICATION_READY: { if (!parent_collision_ignore.is_empty()) { add_collision_exception_with(get_node(parent_collision_ignore)); } - } break; + case NOTIFICATION_TRANSFORM_CHANGED: { if (Engine::get_singleton()->is_editor_hint()) { _reset_points_offsets(); @@ -285,27 +286,36 @@ void SoftBody3D::_notification(int p_what) { set_as_top_level(true); set_transform(Transform3D()); set_notify_transform(true); - } break; + case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); - } break; + case NOTIFICATION_EXIT_WORLD: { PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID()); - } break; - } -#ifdef TOOLS_ENABLED + case NOTIFICATION_DISABLED: { + if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) { + prepare_physics_server(); + } + } break; - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warnings(); - } - } + case NOTIFICATION_ENABLED: { + if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) { + prepare_physics_server(); + } + } break; +#ifdef TOOLS_ENABLED + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warnings(); + } + } break; #endif + } } void SoftBody3D::_bind_methods() { @@ -326,6 +336,9 @@ void SoftBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore); ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode); + ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode); + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with); ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with); @@ -364,6 +377,11 @@ void SoftBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,KeepActive"), "set_disable_mode", "get_disable_mode"); + + BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE); + BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } TypedArray<String> SoftBody3D::get_configuration_warnings() const { @@ -421,6 +439,7 @@ void SoftBody3D::_draw_soft_mesh() { } void SoftBody3D::prepare_physics_server() { +#ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { if (get_mesh().is_valid()) { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); @@ -430,8 +449,9 @@ void SoftBody3D::prepare_physics_server() { return; } +#endif - if (get_mesh().is_valid()) { + if (get_mesh().is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) { become_mesh_owner(); PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); @@ -527,6 +547,28 @@ bool SoftBody3D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } +void SoftBody3D::set_disable_mode(DisableMode p_mode) { + if (disable_mode == p_mode) { + return; + } + + bool inside_tree = is_inside_tree(); + + if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) { + prepare_physics_server(); + } + + disable_mode = p_mode; + + if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) { + prepare_physics_server(); + } +} + +SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const { + return disable_mode; +} + void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { parent_collision_ignore = p_parent_collision_ignore; } diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 0d0d39d48f..81aa0c10c6 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -67,6 +67,11 @@ class SoftBody3D : public MeshInstance3D { GDCLASS(SoftBody3D, MeshInstance3D); public: + enum DisableMode { + DISABLE_MODE_REMOVE, + DISABLE_MODE_KEEP_ACTIVE, + }; + struct PinnedPoint { int point_index = -1; NodePath spatial_attachment_path; @@ -83,6 +88,8 @@ private: RID physics_rid; + DisableMode disable_mode = DISABLE_MODE_REMOVE; + bool mesh_owner = false; uint32_t collision_mask = 1; uint32_t collision_layer = 1; @@ -137,6 +144,9 @@ public: void set_collision_layer_bit(int p_bit, bool p_value); bool get_collision_layer_bit(int p_bit) const; + void set_disable_mode(DisableMode p_mode); + DisableMode get_disable_mode() const; + void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore); const NodePath &get_parent_collision_ignore() const; @@ -192,4 +202,6 @@ private: int _has_pinned_point(int p_point_index) const; }; +VARIANT_ENUM_CAST(SoftBody3D::DisableMode); + #endif // SOFT_PHYSICS_BODY_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 9ec461d973..13f8002721 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -164,6 +164,8 @@ void SpriteBase3D::_im_update() { _draw(); pending_update = false; + + //texture->draw_rect_region(ci,dst_rect,src_rect,modulate); } void SpriteBase3D::_queue_update() { @@ -204,6 +206,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -313,6 +316,9 @@ void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect); ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh); + ClassDB::bind_method(D_METHOD("_queue_update"), &SpriteBase3D::_queue_update); + ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); @@ -343,21 +349,89 @@ SpriteBase3D::SpriteBase3D() { flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED; } - immediate = RenderingServer::get_singleton()->immediate_create(); - set_base(immediate); + material = RenderingServer::get_singleton()->material_create(); + // Set defaults for material, names need to match up those in StandardMaterial3D + RS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1)); + RS::get_singleton()->material_set_param(material, "specular", 0.5); + RS::get_singleton()->material_set_param(material, "metallic", 0.0); + RS::get_singleton()->material_set_param(material, "roughness", 1.0); + RS::get_singleton()->material_set_param(material, "uv1_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98); + + mesh = RenderingServer::get_singleton()->mesh_create(); + + PackedVector3Array mesh_vertices; + PackedVector3Array mesh_normals; + PackedFloat32Array mesh_tangents; + PackedColorArray mesh_colors; + PackedVector2Array mesh_uvs; + PackedInt32Array indices; + + mesh_vertices.resize(4); + mesh_normals.resize(4); + mesh_tangents.resize(16); + mesh_colors.resize(4); + mesh_uvs.resize(4); + + // create basic mesh and store format information + for (int i = 0; i < 4; i++) { + mesh_normals.write[i] = Vector3(0.0, 0.0, 0.0); + mesh_tangents.write[i * 4 + 0] = 0.0; + mesh_tangents.write[i * 4 + 1] = 0.0; + mesh_tangents.write[i * 4 + 2] = 0.0; + mesh_tangents.write[i * 4 + 3] = 0.0; + mesh_colors.write[i] = Color(1.0, 1.0, 1.0, 1.0); + mesh_uvs.write[i] = Vector2(0.0, 0.0); + mesh_vertices.write[i] = Vector3(0.0, 0.0, 0.0); + } + + indices.resize(6); + indices.write[0] = 0; + indices.write[1] = 1; + indices.write[2] = 2; + indices.write[3] = 0; + indices.write[4] = 2; + indices.write[5] = 3; + + Array mesh_array; + mesh_array.resize(RS::ARRAY_MAX); + mesh_array[RS::ARRAY_VERTEX] = mesh_vertices; + mesh_array[RS::ARRAY_NORMAL] = mesh_normals; + mesh_array[RS::ARRAY_TANGENT] = mesh_tangents; + mesh_array[RS::ARRAY_COLOR] = mesh_colors; + mesh_array[RS::ARRAY_TEX_UV] = mesh_uvs; + mesh_array[RS::ARRAY_INDEX] = indices; + + RS::SurfaceData sd; + RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array); + + mesh_surface_format = sd.format; + vertex_buffer = sd.vertex_data; + attribute_buffer = sd.attribute_data; + + sd.material = material; + + RS::get_singleton()->mesh_surface_make_offsets_from_format(sd.format, sd.vertex_count, sd.index_count, mesh_surface_offsets, vertex_stride, attrib_stride, skin_stride); + RS::get_singleton()->mesh_add_surface(mesh, sd); + set_base(mesh); } SpriteBase3D::~SpriteBase3D() { - RenderingServer::get_singleton()->free(immediate); + RenderingServer::get_singleton()->free(mesh); + RenderingServer::get_singleton()->free(material); } /////////////////////////////////////////// void Sprite3D::_draw() { - RID immediate = get_immediate(); - - RS::get_singleton()->immediate_clear(immediate); + if (get_base() != get_mesh()) { + set_base(get_mesh()); + } if (!texture.is_valid()) { + set_base(RID()); return; } Vector2 tsize = texture->get_size(); @@ -366,7 +440,7 @@ void Sprite3D::_draw() { } Rect2 base_rect; - if (region_enabled) { + if (region) { base_rect = region_rect; } else { base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); @@ -399,6 +473,7 @@ void Sprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -426,6 +501,7 @@ void Sprite3D::_draw() { SWAP(uvs[0], uvs[1]); SWAP(uvs[2], uvs[3]); } + if (is_flipped_v()) { SWAP(uvs[0], uvs[3]); SWAP(uvs[1], uvs[2]); @@ -442,11 +518,6 @@ void Sprite3D::_draw() { tangent = Plane(1, 0, 0, 1); } - RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - RS::get_singleton()->immediate_set_material(immediate, mat); - - RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); - int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -466,31 +537,80 @@ void Sprite3D::_draw() { AABB aabb; - for (int i = 0; i < 6; i++) { - static const int index[6] = { 0, 1, 2, 0, 2, 3 }; + // Everything except position and UV is compressed + uint8_t *vertex_write_buffer = vertex_buffer.ptrw(); + uint8_t *attribute_write_buffer = attribute_buffer.ptrw(); + + uint32_t v_normal; + { + Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); + + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + + v_normal = value; + } + uint32_t v_tangent; + { + Plane t = tangent; + uint32_t value = 0; + value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023); + value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; + value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; + if (t.d > 0) { + value |= 3 << 30; + } + v_tangent = value; + } - RS::get_singleton()->immediate_normal(immediate, normal); - RS::get_singleton()->immediate_tangent(immediate, tangent); - RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[index[i]]); + uint8_t v_color[4] = { + uint8_t(CLAMP(color.r * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.g * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.b * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.a * 255.0, 0.0, 255.0)) + }; + for (int i = 0; i < 4; i++) { Vector3 vtx; - vtx[x_axis] = vertices[index[i]][0]; - vtx[y_axis] = vertices[index[i]][1]; - RS::get_singleton()->immediate_vertex(immediate, vtx); + vtx[x_axis] = vertices[i][0]; + vtx[y_axis] = vertices[i][1]; if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); } + + float v_uv[2] = { uvs[i].x, uvs[i].y }; + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8); + + float v_vertex[3] = { vtx.x, vtx.y, vtx.z }; + + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4); + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 4); } + + RID mesh = get_mesh(); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer); + + RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb); set_aabb(aabb); - RS::get_singleton()->immediate_end(immediate); -} -void Sprite3D::_texture_changed() { - _queue_update(); + RID shader_rid; + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + if (last_shader != shader_rid) { + RS::get_singleton()->material_set_shader(get_material(), shader_rid); + last_shader = shader_rid; + } + if (last_texture != texture->get_rid()) { + RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid()); + last_texture = texture->get_rid(); + } } void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) { @@ -498,38 +618,36 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) { return; } if (texture.is_valid()) { - texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed)); + texture->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update")); } texture = p_texture; if (texture.is_valid()) { - texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed)); + texture->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update")); } _queue_update(); - emit_signal(SceneStringNames::get_singleton()->texture_changed); } Ref<Texture2D> Sprite3D::get_texture() const { return texture; } -void Sprite3D::set_region_enabled(bool p_region_enabled) { - if (p_region_enabled == region_enabled) { +void Sprite3D::set_region_enabled(bool p_region) { + if (p_region == region) { return; } - region_enabled = p_region_enabled; + region = p_region; _queue_update(); - notify_property_list_changed(); } bool Sprite3D::is_region_enabled() const { - return region_enabled; + return region; } void Sprite3D::set_region_rect(const Rect2 &p_region_rect) { bool changed = region_rect != p_region_rect; region_rect = p_region_rect; - if (region_enabled && changed) { + if (region && changed) { _queue_update(); } } @@ -596,7 +714,7 @@ Rect2 Sprite3D::get_item_rect() const { Size2i s; - if (region_enabled) { + if (region) { s = region_rect.size; } else { s = texture->get_size(); @@ -625,10 +743,6 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { if (property.name == "frame_coords") { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - - if (!region_enabled && property.name == "region_rect") { - property.usage = PROPERTY_USAGE_NOEDITOR; - } } void Sprite3D::_bind_methods() { @@ -653,32 +767,28 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite3D::set_hframes); ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); ADD_GROUP("Animation", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_SIGNAL(MethodInfo("frame_changed")); - ADD_SIGNAL(MethodInfo("texture_changed")); } Sprite3D::Sprite3D() { - region_enabled = false; - frame = 0; - vframes = 1; - hframes = 1; } //////////////////////////////////////// void AnimatedSprite3D::_draw() { - RID immediate = get_immediate(); - RS::get_singleton()->immediate_clear(immediate); + if (get_base() != get_mesh()) { + set_base(get_mesh()); + } if (frames.is_null()) { return; @@ -694,7 +804,8 @@ void AnimatedSprite3D::_draw() { Ref<Texture2D> texture = frames->get_frame(animation, frame); if (!texture.is_valid()) { - return; //no texture no life + set_base(RID()); + return; //no texuture no life } Vector2 tsize = texture->get_size(); if (tsize.x == 0 || tsize.y == 0) { @@ -729,6 +840,7 @@ void AnimatedSprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -772,12 +884,6 @@ void AnimatedSprite3D::_draw() { tangent = Plane(1, 0, 0, -1); } - RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - - RS::get_singleton()->immediate_set_material(immediate, mat); - - RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); - int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -797,30 +903,79 @@ void AnimatedSprite3D::_draw() { AABB aabb; - for (int i = 0; i < 6; i++) { - static const int indices[6] = { - 0, 1, 2, - 0, 2, 3 - }; + // Everything except position and UV is compressed + uint8_t *vertex_write_buffer = vertex_buffer.ptrw(); + uint8_t *attribute_write_buffer = attribute_buffer.ptrw(); + + uint32_t v_normal; + { + Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); + + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + + v_normal = value; + } + uint32_t v_tangent; + { + Plane t = tangent; + uint32_t value = 0; + value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023); + value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; + value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; + if (t.d > 0) { + value |= 3 << 30; + } + v_tangent = value; + } - RS::get_singleton()->immediate_normal(immediate, normal); - RS::get_singleton()->immediate_tangent(immediate, tangent); - RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[indices[i]]); + uint8_t v_color[4] = { + uint8_t(CLAMP(color.r * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.g * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.b * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(color.a * 255.0, 0.0, 255.0)) + }; + for (int i = 0; i < 4; i++) { Vector3 vtx; - vtx[x_axis] = vertices[indices[i]][0]; - vtx[y_axis] = vertices[indices[i]][1]; - RS::get_singleton()->immediate_vertex(immediate, vtx); + vtx[x_axis] = vertices[i][0]; + vtx[y_axis] = vertices[i][1]; if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); } + + float v_uv[2] = { uvs[i].x, uvs[i].y }; + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8); + + float v_vertex[3] = { vtx.x, vtx.y, vtx.z }; + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4); + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 4); } + + RID mesh = get_mesh(); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer); + + RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb); set_aabb(aabb); - RS::get_singleton()->immediate_end(immediate); + + RID shader_rid; + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + if (last_shader != shader_rid) { + RS::get_singleton()->material_set_shader(get_material(), shader_rid); + last_shader = shader_rid; + } + if (last_texture != texture->get_rid()) { + RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid()); + last_texture = texture->get_rid(); + } } void AnimatedSprite3D::_validate_property(PropertyInfo &property) const { @@ -914,11 +1069,11 @@ void AnimatedSprite3D::_notification(int p_what) { void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) { if (frames.is_valid()) { - frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed)); + frames->disconnect("changed", Callable(this, "_res_changed")); } frames = p_frames; if (frames.is_valid()) { - frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed)); + frames->connect("changed", Callable(this, "_res_changed")); } if (!frames.is_valid()) { @@ -944,9 +1099,8 @@ void AnimatedSprite3D::set_frame(int p_frame) { if (frames->has_animation(animation)) { int limit = frames->get_frame_count(animation); - if (p_frame >= limit) { + if (p_frame >= limit) p_frame = limit - 1; - } } if (p_frame < 0) { @@ -960,7 +1114,6 @@ void AnimatedSprite3D::set_frame(int p_frame) { frame = p_frame; _reset_timeout(); _queue_update(); - emit_signal(SceneStringNames::get_singleton()->frame_changed); } @@ -1061,8 +1214,7 @@ StringName AnimatedSprite3D::get_animation() const { } TypedArray<String> AnimatedSprite3D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); - + TypedArray<String> warnings = SpriteBase3D::get_configuration_warnings(); if (frames.is_null()) { warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.")); } @@ -1087,11 +1239,13 @@ void AnimatedSprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame); + ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite3D::_res_changed); + ADD_SIGNAL(MethodInfo("frame_changed")); ADD_SIGNAL(MethodInfo("animation_finished")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); } diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index e3dd117804..404ef57e6a 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -31,8 +31,8 @@ #ifndef SPRITE_3D_H #define SPRITE_3D_H +#include "scene/2d/animated_sprite_2d.h" #include "scene/3d/visual_instance_3d.h" -#include "scene/resources/sprite_frames.h" class SpriteBase3D : public GeometryInstance3D { GDCLASS(SpriteBase3D, GeometryInstance3D); @@ -75,9 +75,10 @@ private: float pixel_size = 0.01; AABB aabb; - RID immediate; + RID mesh; + RID material; - bool flags[FLAG_MAX]; + bool flags[FLAG_MAX] = {}; AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED; bool pending_update = false; @@ -91,7 +92,17 @@ protected: static void _bind_methods(); virtual void _draw() = 0; _FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; } - _FORCE_INLINE_ RID &get_immediate() { return immediate; } + _FORCE_INLINE_ RID &get_mesh() { return mesh; } + _FORCE_INLINE_ RID &get_material() { return material; } + + uint32_t mesh_surface_offsets[RS::ARRAY_MAX]; + PackedByteArray vertex_buffer; + PackedByteArray attribute_buffer; + uint32_t vertex_stride; + uint32_t attrib_stride; + uint32_t skin_stride; + uint32_t mesh_surface_format; + void _queue_update(); public: @@ -107,7 +118,7 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region_enabled(bool p_region_enabled); + void set_region_enabled(bool p_region); bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); @@ -147,15 +158,16 @@ class Sprite3D : public SpriteBase3D { GDCLASS(Sprite3D, SpriteBase3D); Ref<Texture2D> texture; - bool region_enabled; + bool region = false; Rect2 region_rect; - int frame; + int frame = 0; - int vframes; - int hframes; + int vframes = 1; + int hframes = 1; - void _texture_changed(); + RID last_shader; + RID last_texture; protected: virtual void _draw() override; @@ -167,7 +179,7 @@ public: void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; - void set_region_enabled(bool p_region_enabled); + void set_region_enabled(bool p_region); bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); @@ -199,14 +211,9 @@ class AnimatedSprite3D : public SpriteBase3D { StringName animation = "default"; int frame = 0; - bool centered = true; - - float timeout = 0.0; - - bool hflip = true; - bool vflip = true; + bool centered = false; - Color modulate; + float timeout = 0; void _res_changed(); @@ -214,6 +221,9 @@ class AnimatedSprite3D : public SpriteBase3D { void _set_playing(bool p_playing); bool _is_playing() const; + RID last_shader; + RID last_texture; + protected: virtual void _draw() override; static void _bind_methods(); @@ -236,10 +246,11 @@ public: virtual Rect2 get_item_rect() const override; - TypedArray<String> get_configuration_warnings() const override; + virtual TypedArray<String> get_configuration_warnings() const override; AnimatedSprite3D(); }; VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags); VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode); + #endif // SPRITE_3D_H diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 0d88769b70..b0e37b81a5 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -79,26 +79,29 @@ public: }; void VehicleWheel3D::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent()); - if (!cb) { - return; - } - body = cb; - local_xform = get_transform(); - cb->wheels.push_back(this); - - m_chassisConnectionPointCS = get_transform().origin; - m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized(); - m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized(); - } - if (p_what == NOTIFICATION_EXIT_TREE) { - VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent()); - if (!cb) { - return; - } - cb->wheels.erase(this); - body = nullptr; + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent()); + if (!cb) { + return; + } + body = cb; + local_xform = get_transform(); + cb->wheels.push_back(this); + + m_chassisConnectionPointCS = get_transform().origin; + m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized(); + m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized(); + } break; + + case NOTIFICATION_EXIT_TREE: { + VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent()); + if (!cb) { + return; + } + cb->wheels.erase(this); + body = nullptr; + } break; } } diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index b963cf5702..770996820d 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -77,7 +77,7 @@ bool RootMotionView::get_zero_y() const { void RootMotionView::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - RS::get_singleton()->immediate_set_material(immediate, StandardMaterial3D::get_material_rid_for_2d(false, true, false, false, false)); + immediate_material = StandardMaterial3D::get_material_for_2d(false, true, false, false, false); first = true; } @@ -119,11 +119,12 @@ void RootMotionView::_notification(int p_what) { } accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size); - RS::get_singleton()->immediate_clear(immediate); + immediate->clear_surfaces(); int cells_in_radius = int((radius / cell_size) + 1.0); - RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_LINES); + immediate->surface_begin(Mesh::PRIMITIVE_LINES, immediate_material); + for (int i = -cells_in_radius; i < cells_in_radius; i++) { for (int j = -cells_in_radius; j < cells_in_radius; j++) { Vector3 from(i * cell_size, 0, j * cell_size); @@ -138,21 +139,21 @@ void RootMotionView::_notification(int p_what) { c_i.a *= MAX(0, 1.0 - from_i.length() / radius); c_j.a *= MAX(0, 1.0 - from_j.length() / radius); - RS::get_singleton()->immediate_color(immediate, c); - RS::get_singleton()->immediate_vertex(immediate, from); + immediate->surface_set_color(c); + immediate->surface_add_vertex(from); - RS::get_singleton()->immediate_color(immediate, c_i); - RS::get_singleton()->immediate_vertex(immediate, from_i); + immediate->surface_set_color(c_i); + immediate->surface_add_vertex(from_i); - RS::get_singleton()->immediate_color(immediate, c); - RS::get_singleton()->immediate_vertex(immediate, from); + immediate->surface_set_color(c); + immediate->surface_add_vertex(from); - RS::get_singleton()->immediate_color(immediate, c_j); - RS::get_singleton()->immediate_vertex(immediate, from_j); + immediate->surface_set_color(c_j); + immediate->surface_add_vertex(from_j); } } - RS::get_singleton()->immediate_end(immediate); + immediate->surface_end(); } } @@ -188,12 +189,13 @@ void RootMotionView::_bind_methods() { } RootMotionView::RootMotionView() { - set_process_internal(true); - immediate = RenderingServer::get_singleton()->immediate_create(); - set_base(immediate); + if (Engine::get_singleton()->is_editor_hint()) { + set_process_internal(true); + } + immediate.instantiate(); + set_base(immediate->get_rid()); } RootMotionView::~RootMotionView() { set_base(RID()); - RenderingServer::get_singleton()->free(immediate); } diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h index 4cd3c7b443..55fd2d2b73 100644 --- a/scene/animation/root_motion_view.h +++ b/scene/animation/root_motion_view.h @@ -32,12 +32,12 @@ #define ROOT_MOTION_VIEW_H #include "scene/3d/visual_instance_3d.h" - +#include "scene/resources/immediate_mesh.h" class RootMotionView : public VisualInstance3D { GDCLASS(RootMotionView, VisualInstance3D); public: - RID immediate; + Ref<ImmediateMesh> immediate; NodePath path; float cell_size = 1.0; float radius = 10.0; @@ -46,6 +46,8 @@ public: bool first = true; bool zero_y = true; + Ref<Material> immediate_material; + Transform3D accumulated; private: diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9479b1339d..ac092d9862 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -403,6 +403,7 @@ void Node::set_process_mode(ProcessMode p_mode) { } bool prev_can_process = can_process(); + bool prev_enabled = _is_enabled(); data.process_mode = p_mode; @@ -417,6 +418,7 @@ void Node::set_process_mode(ProcessMode p_mode) { } bool next_can_process = can_process(); + bool next_enabled = _is_enabled(); int pause_notification = 0; @@ -426,7 +428,16 @@ void Node::set_process_mode(ProcessMode p_mode) { pause_notification = NOTIFICATION_UNPAUSED; } - _propagate_process_owner(data.process_owner, pause_notification); + int enabled_notification = 0; + + if (prev_enabled && !next_enabled) { + enabled_notification = NOTIFICATION_DISABLED; + } else if (!prev_enabled && next_enabled) { + enabled_notification = NOTIFICATION_ENABLED; + } + + _propagate_process_owner(data.process_owner, pause_notification, enabled_notification); + #ifdef TOOLS_ENABLED // This is required for the editor to update the visibility of disabled nodes // It's very expensive during runtime to change, so editor-only @@ -455,17 +466,21 @@ Node::ProcessMode Node::get_process_mode() const { return data.process_mode; } -void Node::_propagate_process_owner(Node *p_owner, int p_notification) { +void Node::_propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification) { data.process_owner = p_owner; - if (p_notification != 0) { - notification(p_notification); + if (p_pause_notification != 0) { + notification(p_pause_notification); + } + + if (p_enabled_notification != 0) { + notification(p_enabled_notification); } for (int i = 0; i < data.children.size(); i++) { Node *c = data.children[i]; if (c->data.process_mode == PROCESS_MODE_INHERIT) { - c->_propagate_process_owner(p_owner, p_notification); + c->_propagate_process_owner(p_owner, p_pause_notification, p_enabled_notification); } } } @@ -669,6 +684,27 @@ bool Node::_can_process(bool p_paused) const { } } +bool Node::_is_enabled() const { + ProcessMode process_mode; + + if (data.process_mode == PROCESS_MODE_INHERIT) { + if (!data.process_owner) { + process_mode = PROCESS_MODE_PAUSABLE; + } else { + process_mode = data.process_owner->data.process_mode; + } + } else { + process_mode = data.process_mode; + } + + return (process_mode != PROCESS_MODE_DISABLED); +} + +bool Node::is_enabled() const { + ERR_FAIL_COND_V(!is_inside_tree(), false); + return _is_enabled(); +} + float Node::get_physics_process_delta_time() const { if (data.tree) { return data.tree->get_physics_process_time(); @@ -2628,6 +2664,8 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS); BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE); + BIND_CONSTANT(NOTIFICATION_DISABLED); + BIND_CONSTANT(NOTIFICATION_ENABLED); BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE); BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE); diff --git a/scene/main/node.h b/scene/main/node.h index f685eac86a..fc5af43829 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -166,7 +166,7 @@ private: void _propagate_after_exit_tree(); void _propagate_validate_owner(); void _print_stray_nodes(); - void _propagate_process_owner(Node *p_owner, int p_notification); + void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification); Array _get_node_and_resource(const NodePath &p_path); void _duplicate_signals(const Node *p_original, Node *p_copy) const; @@ -184,6 +184,7 @@ private: void _propagate_pause_notification(bool p_enable); _FORCE_INLINE_ bool _can_process(bool p_paused) const; + _FORCE_INLINE_ bool _is_enabled() const; protected: void _block() { data.blocked++; } @@ -227,6 +228,8 @@ public: NOTIFICATION_INTERNAL_PROCESS = 25, NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26, NOTIFICATION_POST_ENTER_TREE = 27, + NOTIFICATION_DISABLED = 28, + NOTIFICATION_ENABLED = 29, //keep these linked to node NOTIFICATION_WM_MOUSE_ENTER = 1002, @@ -385,6 +388,7 @@ public: ProcessMode get_process_mode() const; bool can_process() const; bool can_process_notification(int p_what) const; + bool is_enabled() const; void request_ready(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8d0283d536..d069d5e963 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -147,6 +147,7 @@ #include "scene/resources/font.h" #include "scene/resources/gradient.h" #include "scene/resources/height_map_shape_3d.h" +#include "scene/resources/immediate_mesh.h" #include "scene/resources/line_shape_2d.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" @@ -204,7 +205,6 @@ #include "scene/3d/decal.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/gpu_particles_collision_3d.h" -#include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" @@ -459,7 +459,6 @@ void register_scene_types() { ClassDB::register_class<MeshInstance3D>(); ClassDB::register_class<OccluderInstance3D>(); ClassDB::register_class<Occluder3D>(); - ClassDB::register_class<ImmediateGeometry3D>(); ClassDB::register_virtual_class<SpriteBase3D>(); ClassDB::register_class<Sprite3D>(); ClassDB::register_class<AnimatedSprite3D>(); @@ -718,6 +717,7 @@ void register_scene_types() { ClassDB::register_virtual_class<Mesh>(); ClassDB::register_class<ArrayMesh>(); + ClassDB::register_class<ImmediateMesh>(); ClassDB::register_class<MultiMesh>(); ClassDB::register_class<SurfaceTool>(); ClassDB::register_class<MeshDataTool>(); diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp new file mode 100644 index 0000000000..ebe65605f8 --- /dev/null +++ b/scene/resources/immediate_mesh.cpp @@ -0,0 +1,416 @@ +/*************************************************************************/ +/* immediate_mesh.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "immediate_mesh.h" + +void ImmediateMesh::surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material) { + ERR_FAIL_COND_MSG(surface_active, "Already creating a new surface."); + active_surface_data.primitive = p_primitive; + active_surface_data.material = p_material; + surface_active = true; +} +void ImmediateMesh::surface_set_color(const Color &p_color) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + + if (!uses_colors) { + colors.resize(vertices.size()); + for (uint32_t i = 0; i < colors.size(); i++) { + colors[i] = p_color; + } + uses_colors = true; + } + + current_color = p_color; +} +void ImmediateMesh::surface_set_normal(const Vector3 &p_normal) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + + if (!uses_normals) { + normals.resize(vertices.size()); + for (uint32_t i = 0; i < normals.size(); i++) { + normals[i] = p_normal; + } + uses_normals = true; + } + + current_normal = p_normal; +} +void ImmediateMesh::surface_set_tangent(const Plane &p_tangent) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + if (!uses_tangents) { + tangents.resize(vertices.size()); + for (uint32_t i = 0; i < tangents.size(); i++) { + tangents[i] = p_tangent; + } + uses_tangents = true; + } + + current_tangent = p_tangent; +} +void ImmediateMesh::surface_set_uv(const Vector2 &p_uv) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + if (!uses_uvs) { + uvs.resize(vertices.size()); + for (uint32_t i = 0; i < uvs.size(); i++) { + uvs[i] = p_uv; + } + uses_uvs = true; + } + + current_uv = p_uv; +} +void ImmediateMesh::surface_set_uv2(const Vector2 &p_uv2) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + if (!uses_uv2s) { + uv2s.resize(vertices.size()); + for (uint32_t i = 0; i < uv2s.size(); i++) { + uv2s[i] = p_uv2; + } + uses_uv2s = true; + } + + current_uv2 = p_uv2; +} +void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + ERR_FAIL_COND_MSG(vertices.size() && active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface."); + + if (uses_colors) { + colors.push_back(current_color); + } + if (uses_normals) { + normals.push_back(current_normal); + } + if (uses_tangents) { + tangents.push_back(current_tangent); + } + if (uses_uvs) { + uvs.push_back(current_uv); + } + if (uses_uv2s) { + uv2s.push_back(current_uv2); + } + vertices.push_back(p_vertex); +} + +void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + ERR_FAIL_COND_MSG(vertices.size() && !active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface."); + + if (uses_colors) { + colors.push_back(current_color); + } + if (uses_normals) { + normals.push_back(current_normal); + } + if (uses_tangents) { + tangents.push_back(current_tangent); + } + if (uses_uvs) { + uvs.push_back(current_uv); + } + if (uses_uv2s) { + uv2s.push_back(current_uv2); + } + Vector3 v(p_vertex.x, p_vertex.y, 0); + vertices.push_back(v); + + active_surface_data.vertex_2d = true; +} +void ImmediateMesh::surface_end() { + ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); + ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface cant be created."); + + uint32_t format = ARRAY_FORMAT_VERTEX; + + uint32_t vertex_stride = 0; + if (active_surface_data.vertex_2d) { + format |= ARRAY_FLAG_USE_2D_VERTICES; + vertex_stride = sizeof(float) * 2; + } else { + vertex_stride = sizeof(float) * 3; + } + + uint32_t normal_offset = 0; + if (uses_normals) { + format |= ARRAY_FORMAT_NORMAL; + normal_offset = vertex_stride; + vertex_stride += sizeof(uint32_t); + } + uint32_t tangent_offset = 0; + if (uses_tangents) { + format |= ARRAY_FORMAT_TANGENT; + tangent_offset += vertex_stride; + vertex_stride += sizeof(uint32_t); + } + + AABB aabb; + + { + surface_vertex_create_cache.resize(vertex_stride * vertices.size()); + uint8_t *surface_vertex_ptr = surface_vertex_create_cache.ptrw(); + for (uint32_t i = 0; i < vertices.size(); i++) { + { + float *vtx = (float *)&surface_vertex_ptr[i * vertex_stride]; + vtx[0] = vertices[i].x; + vtx[1] = vertices[i].y; + if (!active_surface_data.vertex_2d) { + vtx[2] = vertices[i].z; + } + if (i == 0) { + aabb.position = vertices[i]; + } else { + aabb.expand_to(vertices[i]); + } + } + if (uses_normals) { + uint32_t *normal = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + normal_offset]; + + Vector3 n = normals[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); + + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + + *normal = value; + } + if (uses_tangents) { + uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + tangent_offset]; + Plane t = tangents[i]; + uint32_t value = 0; + value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023); + value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; + value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; + if (t.d > 0) { + value |= 3 << 30; + } + + *tangent = value; + } + } + } + + if (uses_colors || uses_uvs || uses_uv2s) { + uint32_t attribute_stride = 0; + + if (uses_colors) { + format |= ARRAY_FORMAT_COLOR; + attribute_stride += sizeof(uint8_t) * 4; + } + uint32_t uv_offset = 0; + if (uses_uvs) { + format |= ARRAY_FORMAT_TEX_UV; + uv_offset = attribute_stride; + attribute_stride += sizeof(float) * 2; + } + uint32_t uv2_offset = 0; + if (uses_uv2s) { + format |= ARRAY_FORMAT_TEX_UV2; + uv2_offset = attribute_stride; + attribute_stride += sizeof(float) * 2; + } + + surface_attribute_create_cache.resize(vertices.size() * attribute_stride); + + uint8_t *surface_attribute_ptr = surface_attribute_create_cache.ptrw(); + + for (uint32_t i = 0; i < vertices.size(); i++) { + if (uses_colors) { + uint8_t *color8 = (uint8_t *)&surface_attribute_ptr[i * attribute_stride]; + + color8[0] = uint8_t(CLAMP(colors[i].r * 255.0, 0.0, 255.0)); + color8[1] = uint8_t(CLAMP(colors[i].g * 255.0, 0.0, 255.0)); + color8[2] = uint8_t(CLAMP(colors[i].b * 255.0, 0.0, 255.0)); + color8[3] = uint8_t(CLAMP(colors[i].a * 255.0, 0.0, 255.0)); + } + if (uses_uvs) { + float *uv = (float *)&surface_attribute_ptr[i * attribute_stride + uv_offset]; + + uv[0] = uvs[i].x; + uv[1] = uvs[i].y; + } + + if (uses_uv2s) { + float *uv2 = (float *)&surface_attribute_ptr[i * attribute_stride + uv2_offset]; + + uv2[0] = uv2s[i].x; + uv2[1] = uv2s[i].y; + } + } + } + + RS::SurfaceData sd; + + sd.primitive = RS::PrimitiveType(active_surface_data.primitive); + sd.format = format; + sd.vertex_data = surface_vertex_create_cache; + if (uses_colors || uses_uvs || uses_uv2s) { + sd.attribute_data = surface_attribute_create_cache; + } + sd.vertex_count = vertices.size(); + sd.aabb = aabb; + if (active_surface_data.material.is_valid()) { + sd.material = active_surface_data.material->get_rid(); + } + + RS::get_singleton()->mesh_add_surface(mesh, sd); + + active_surface_data.aabb = aabb; + + active_surface_data.format = format; + active_surface_data.array_len = vertices.size(); + + surfaces.push_back(active_surface_data); + + colors.clear(); + normals.clear(); + tangents.clear(); + uvs.clear(); + uv2s.clear(); + vertices.clear(); + + uses_colors = false; + uses_normals = false; + uses_tangents = false; + uses_uvs = false; + uses_uv2s = false; + + surface_active = false; +} + +void ImmediateMesh::clear_surfaces() { + RS::get_singleton()->mesh_clear(mesh); + surfaces.clear(); + surface_active = false; + + colors.clear(); + normals.clear(); + tangents.clear(); + uvs.clear(); + uv2s.clear(); + vertices.clear(); + + uses_colors = false; + uses_normals = false; + uses_tangents = false; + uses_uvs = false; + uses_uv2s = false; +} + +int ImmediateMesh::get_surface_count() const { + return surfaces.size(); +} +int ImmediateMesh::surface_get_array_len(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), -1); + return surfaces[p_idx].array_len; +} +int ImmediateMesh::surface_get_array_index_len(int p_idx) const { + return 0; +} +bool ImmediateMesh::surface_is_softbody_friendly(int p_idx) const { + return false; +} +Array ImmediateMesh::surface_get_arrays(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, int(surfaces.size()), Array()); + return RS::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); +} +Array ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const { + return Array(); +} +Dictionary ImmediateMesh::surface_get_lods(int p_surface) const { + return Dictionary(); +} +uint32_t ImmediateMesh::surface_get_format(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), 0); + return surfaces[p_idx].format; +} +Mesh::PrimitiveType ImmediateMesh::surface_get_primitive_type(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), PRIMITIVE_MAX); + return surfaces[p_idx].primitive; +} +void ImmediateMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { + ERR_FAIL_INDEX(p_idx, int(surfaces.size())); + surfaces[p_idx].material = p_material; + RID mat; + if (p_material.is_valid()) { + mat = p_material->get_rid(); + } + RS::get_singleton()->mesh_surface_set_material(mesh, p_idx, mat); +} +Ref<Material> ImmediateMesh::surface_get_material(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), Ref<Material>()); + return surfaces[p_idx].material; +} +int ImmediateMesh::get_blend_shape_count() const { + return 0; +} +StringName ImmediateMesh::get_blend_shape_name(int p_index) const { + return StringName(); +} +void ImmediateMesh::set_blend_shape_name(int p_index, const StringName &p_name) { +} + +AABB ImmediateMesh::get_aabb() const { + AABB aabb; + for (uint32_t i = 0; i < surfaces.size(); i++) { + if (i == 0) { + aabb = surfaces[i].aabb; + } else { + aabb.merge(surfaces[i].aabb); + } + } + return aabb; +} + +void ImmediateMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("surface_begin", "primitive", "material"), &ImmediateMesh::surface_begin, DEFVAL(Ref<Material>())); + ClassDB::bind_method(D_METHOD("surface_set_color", "color"), &ImmediateMesh::surface_set_color); + ClassDB::bind_method(D_METHOD("surface_set_normal", "normal"), &ImmediateMesh::surface_set_normal); + ClassDB::bind_method(D_METHOD("surface_set_tangent", "tangent"), &ImmediateMesh::surface_set_tangent); + ClassDB::bind_method(D_METHOD("surface_set_uv", "uv"), &ImmediateMesh::surface_set_uv); + ClassDB::bind_method(D_METHOD("surface_set_uv2", "uv2"), &ImmediateMesh::surface_set_uv2); + ClassDB::bind_method(D_METHOD("surface_add_vertex", "vertex"), &ImmediateMesh::surface_add_vertex); + ClassDB::bind_method(D_METHOD("surface_add_vertex_2d", "vertex"), &ImmediateMesh::surface_add_vertex_2d); + ClassDB::bind_method(D_METHOD("surface_end"), &ImmediateMesh::surface_end); + + ClassDB::bind_method(D_METHOD("clear_surfaces"), &ImmediateMesh::clear_surfaces); +} + +RID ImmediateMesh::get_rid() const { + return mesh; +} + +ImmediateMesh::ImmediateMesh() { + mesh = RS::get_singleton()->mesh_create(); +} +ImmediateMesh::~ImmediateMesh() { + RS::get_singleton()->free(mesh); +} diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h new file mode 100644 index 0000000000..7010d40719 --- /dev/null +++ b/scene/resources/immediate_mesh.h @@ -0,0 +1,117 @@ +/*************************************************************************/ +/* immediate_mesh.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef IMMEDIATE_MESH_H +#define IMMEDIATE_MESH_H + +#include "core/templates/local_vector.h" +#include "scene/resources/mesh.h" + +class ImmediateMesh : public Mesh { + GDCLASS(ImmediateMesh, Mesh) + + RID mesh; + + bool uses_colors = false; + bool uses_normals = false; + bool uses_tangents = false; + bool uses_uvs = false; + bool uses_uv2s = false; + + Color current_color; + Vector3 current_normal; + Plane current_tangent; + Vector2 current_uv; + Vector2 current_uv2; + + LocalVector<Color> colors; + LocalVector<Vector3> normals; + LocalVector<Plane> tangents; + LocalVector<Vector2> uvs; + LocalVector<Vector2> uv2s; + LocalVector<Vector3> vertices; + + struct Surface { + PrimitiveType primitive; + Ref<Material> material; + bool vertex_2d = false; + int array_len = 0; + uint32_t format = 0; + AABB aabb; + }; + + LocalVector<Surface> surfaces; + + bool surface_active = false; + Surface active_surface_data; + + Vector<uint8_t> surface_vertex_create_cache; + Vector<uint8_t> surface_attribute_create_cache; + +protected: + static void _bind_methods(); + +public: + void surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material = Ref<Material>()); + void surface_set_color(const Color &p_color); + void surface_set_normal(const Vector3 &p_normal); + void surface_set_tangent(const Plane &p_tangent); + void surface_set_uv(const Vector2 &p_uv); + void surface_set_uv2(const Vector2 &p_uv2); + void surface_add_vertex(const Vector3 &p_vertex); + void surface_add_vertex_2d(const Vector2 &p_vertex); + void surface_end(); + + void clear_surfaces(); + + virtual int get_surface_count() const override; + virtual int surface_get_array_len(int p_idx) const override; + virtual int surface_get_array_index_len(int p_idx) const override; + virtual bool surface_is_softbody_friendly(int p_idx) const override; + virtual Array surface_get_arrays(int p_surface) const override; + virtual Array surface_get_blend_shape_arrays(int p_surface) const override; + virtual Dictionary surface_get_lods(int p_surface) const override; + virtual uint32_t surface_get_format(int p_idx) const override; + virtual PrimitiveType surface_get_primitive_type(int p_idx) const override; + virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override; + virtual Ref<Material> surface_get_material(int p_idx) const override; + virtual int get_blend_shape_count() const override; + virtual StringName get_blend_shape_name(int p_index) const override; + virtual void set_blend_shape_name(int p_index, const StringName &p_name) override; + + virtual AABB get_aabb() const override; + + virtual RID get_rid() const override; + + ImmediateMesh(); + ~ImmediateMesh(); +}; + +#endif // IMMEDIATEMESH_H diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index cb66d5724d..d391540a0b 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -2077,7 +2077,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() return refraction_texture_channel; } -RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) { +Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, RID *r_shader_rid) { int version = 0; if (p_shaded) { version = 1; @@ -2102,7 +2102,10 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b } if (materials_for_2d[version].is_valid()) { - return materials_for_2d[version]->get_rid(); + if (r_shader_rid) { + *r_shader_rid = materials_for_2d[version]->get_shader_rid(); + } + return materials_for_2d[version]; } Ref<StandardMaterial3D> material; @@ -2120,7 +2123,11 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b materials_for_2d[version] = material; - return materials_for_2d[version]->get_rid(); + if (r_shader_rid) { + *r_shader_rid = materials_for_2d[version]->get_shader_rid(); + } + + return materials_for_2d[version]; } void BaseMaterial3D::set_on_top_of_alpha() { @@ -2189,6 +2196,8 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const { } RID BaseMaterial3D::get_shader_rid() const { + MutexLock lock(material_mutex); + ((BaseMaterial3D *)this)->_update_shader(); ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } diff --git a/scene/resources/material.h b/scene/resources/material.h index dc3ecdb5de..cd91d05a60 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -738,7 +738,7 @@ public: static void finish_shaders(); static void flush_changes(); - static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false); + static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, RID *r_shader_rid = nullptr); virtual RID get_shader_rid() const override; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index cf59c6fa22..ce942817c0 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1335,9 +1335,21 @@ String ArrayMesh::surface_get_name(int p_idx) const { return surfaces[p_idx].name; } -void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { +void ArrayMesh::surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { ERR_FAIL_INDEX(p_surface, surfaces.size()); - RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, p_surface, p_offset, p_data); + emit_changed(); +} + +void ArrayMesh::surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + ERR_FAIL_INDEX(p_surface, surfaces.size()); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, p_surface, p_offset, p_data); + emit_changed(); +} + +void ArrayMesh::surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + ERR_FAIL_INDEX(p_surface, surfaces.size()); + RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data); emit_changed(); } @@ -1635,7 +1647,9 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces); - ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region); + ClassDB::bind_method(D_METHOD("surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region); + ClassDB::bind_method(D_METHOD("surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region); + ClassDB::bind_method(D_METHOD("surface_update_skin_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_skin_region); ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 2dfb46782b..02cab9a5e1 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -233,7 +233,9 @@ public: void set_blend_shape_mode(BlendShapeMode p_mode); BlendShapeMode get_blend_shape_mode() const; - void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); + void surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); + void surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); + void surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); int get_surface_count() const override; diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index d4c25b6253..bc5aae2b48 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -324,7 +324,9 @@ public: void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {} RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; } - void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} + void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {} void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } @@ -365,23 +367,6 @@ public: void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {} int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; } - /* IMMEDIATE API */ - - RID immediate_allocate() override { return RID(); } - void immediate_initialize(RID p_rid) override {} - void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {} - void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {} - void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {} - void immediate_tangent(RID p_immediate, const Plane &p_tangent) override {} - void immediate_color(RID p_immediate, const Color &p_color) override {} - void immediate_uv(RID p_immediate, const Vector2 &tex_uv) override {} - void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) override {} - void immediate_end(RID p_immediate) override {} - void immediate_clear(RID p_immediate) override {} - void immediate_set_material(RID p_immediate, RID p_material) override {} - RID immediate_get_material(RID p_immediate) const override { return RID(); } - AABB immediate_get_aabb(RID p_immediate) const override { return AABB(); } - /* SKELETON API */ RID skeleton_allocate() override { return RID(); } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index a5a4b0e2d1..1db81d8584 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -2655,7 +2655,7 @@ RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) cons return mesh->blend_shape_mode; } -void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { +void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); @@ -2666,6 +2666,30 @@ void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, in RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); } +void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r); +} + +void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r); +} + void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); @@ -3234,8 +3258,8 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf case RS::ARRAY_COLOR: { vd.offset = attribute_stride; - vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - attribute_stride += sizeof(int16_t) * 4; + vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + attribute_stride += sizeof(int8_t) * 4; buffer = s->attribute_buffer; } break; case RS::ARRAY_TEX_UV: { diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 5de5593204..e09b1d6b16 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -1457,7 +1457,9 @@ public: virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode); virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data); virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; @@ -1746,24 +1748,6 @@ public: return multimesh->uniform_set_2d; } - /* IMMEDIATE API */ - - RID immediate_allocate() { return RID(); } - void immediate_initialize(RID p_immediate) {} - - virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {} - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {} - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) {} - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) {} - virtual void immediate_color(RID p_immediate, const Color &p_color) {} - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {} - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {} - virtual void immediate_end(RID p_immediate) {} - virtual void immediate_clear(RID p_immediate) {} - virtual void immediate_set_material(RID p_immediate, RID p_material) {} - virtual RID immediate_get_material(RID p_immediate) const { return RID(); } - virtual AABB immediate_get_aabb(RID p_immediate) const { return AABB(); } - /* SKELETON API */ RID skeleton_allocate(); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 5aaecb83c4..7e7139463b 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -478,7 +478,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { switch (instance->base_type) { case RS::INSTANCE_MESH: case RS::INSTANCE_MULTIMESH: - case RS::INSTANCE_IMMEDIATE: case RS::INSTANCE_PARTICLES: { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); scene_render->geometry_instance_free(geom->geometry_instance); @@ -590,7 +589,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { } break; case RS::INSTANCE_MESH: case RS::INSTANCE_MULTIMESH: - case RS::INSTANCE_IMMEDIATE: case RS::INSTANCE_PARTICLES: { InstanceGeometryData *geom = memnew(InstanceGeometryData); instance->base_data = geom; @@ -888,7 +886,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) { } inline bool is_geometry_instance(RenderingServer::InstanceType p_type) { - return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE; + return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES; } void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { @@ -1529,7 +1527,6 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { switch (p_instance->base_type) { case RS::INSTANCE_MESH: case RS::INSTANCE_MULTIMESH: - case RS::INSTANCE_IMMEDIATE: case RS::INSTANCE_PARTICLES: { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); idata.instance_geometry = geom->geometry_instance; @@ -1748,14 +1745,6 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { } } break; - case RenderingServer::INSTANCE_IMMEDIATE: { - if (p_instance->custom_aabb) { - new_aabb = *p_instance->custom_aabb; - } else { - new_aabb = RSG::storage->immediate_get_aabb(p_instance->base); - } - - } break; case RenderingServer::INSTANCE_PARTICLES: { if (p_instance->custom_aabb) { new_aabb = *p_instance->custom_aabb; @@ -3681,25 +3670,6 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker); } - } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) { - RID mat = RSG::storage->immediate_get_material(p_instance->base); - - if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) { - can_cast_shadows = false; - } - - if (mat.is_valid() && RSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - if (mat.is_valid()) { - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - } - - if (mat.is_valid()) { - RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); - } - } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { bool cast_shadows = false; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index f22c582f48..62b23acedf 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -230,7 +230,9 @@ public: virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; @@ -288,24 +290,6 @@ public: virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - /* IMMEDIATE API */ - - virtual RID immediate_allocate() = 0; - virtual void immediate_initialize(RID p_rid) = 0; - - virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0; - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; - virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_end(RID p_immediate) = 0; - virtual void immediate_clear(RID p_immediate) = 0; - virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; - virtual RID immediate_get_material(RID p_immediate) const = 0; - virtual AABB immediate_get_aabb(RID p_immediate) const = 0; - /* SKELETON API */ virtual RID skeleton_allocate() = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index b9afeafbab..22c1f6d909 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -290,7 +290,9 @@ public: FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode) FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID) - FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &) + FUNC4(mesh_surface_update_vertex_region, RID, int, int, const Vector<uint8_t> &) + FUNC4(mesh_surface_update_attribute_region, RID, int, int, const Vector<uint8_t> &) + FUNC4(mesh_surface_update_skin_region, RID, int, int, const Vector<uint8_t> &) FUNC3(mesh_surface_set_material, RID, int, RID) FUNC2RC(RID, mesh_surface_get_material, RID, int) @@ -333,21 +335,6 @@ public: FUNC2(multimesh_set_visible_instances, RID, int) FUNC1RC(int, multimesh_get_visible_instances, RID) - /* IMMEDIATE API */ - - FUNCRIDSPLIT(immediate) - FUNC3(immediate_begin, RID, PrimitiveType, RID) - FUNC2(immediate_vertex, RID, const Vector3 &) - FUNC2(immediate_normal, RID, const Vector3 &) - FUNC2(immediate_tangent, RID, const Plane &) - FUNC2(immediate_color, RID, const Color &) - FUNC2(immediate_uv, RID, const Vector2 &) - FUNC2(immediate_uv2, RID, const Vector2 &) - FUNC1(immediate_end, RID) - FUNC1(immediate_clear, RID) - FUNC2(immediate_set_material, RID, RID) - FUNC1RC(RID, immediate_get_material, RID) - /* SKELETON API */ FUNCRIDSPLIT(skeleton) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index f25f255321..75ae850acb 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -438,13 +438,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); const Color *src = array.ptr(); - uint16_t color16[4]; for (int i = 0; i < p_vertex_array_len; i++) { - color16[0] = Math::make_half_float(src[i].r); - color16[1] = Math::make_half_float(src[i].g); - color16[2] = Math::make_half_float(src[i].b); - color16[3] = Math::make_half_float(src[i].a); - memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], color16, 8); + uint8_t color8[4] = { + uint8_t(CLAMP(src[i].r * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(src[i].g * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(src[i].b * 255.0, 0.0, 255.0)), + uint8_t(CLAMP(src[i].a * 255.0, 0.0, 255.0)) + }; + memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], color8, 4); } } break; case RS::ARRAY_TEX_UV: { @@ -761,7 +762,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i elem_size = 4; } break; case RS::ARRAY_COLOR: { - elem_size = 8; + elem_size = 4; } break; case RS::ARRAY_TEX_UV: { elem_size = 8; @@ -1123,8 +1124,9 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t Color *w = arr.ptrw(); for (int32_t j = 0; j < p_vertex_len; j++) { - const uint16_t *v = (const uint16_t *)&ar[j * attrib_elem_size + offsets[i]]; - w[j] = Color(Math::half_to_float(v[0]), Math::half_to_float(v[1]), Math::half_to_float(v[2]), Math::half_to_float(v[3])); + const uint8_t *v = (const uint8_t *)&ar[j * attrib_elem_size + offsets[i]]; + + w[j] = Color(v[0] / 255.0, v[1] / 255.0, v[2] / 255.0, v[3] / 255.0); } ret[i] = arr; @@ -1482,7 +1484,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &RenderingServer::mesh_get_blend_shape_count); ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &RenderingServer::mesh_set_blend_shape_mode); ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &RenderingServer::mesh_get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_region); + ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &RenderingServer::mesh_surface_set_material); ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &RenderingServer::mesh_surface_get_material); ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &RenderingServer::mesh_surface_get_arrays); @@ -1510,21 +1512,6 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &RenderingServer::multimesh_get_visible_instances); ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &RenderingServer::multimesh_set_buffer); ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &RenderingServer::multimesh_get_buffer); -#ifndef _3D_DISABLED - ClassDB::bind_method(D_METHOD("immediate_create"), &RenderingServer::immediate_create); - ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &RenderingServer::immediate_begin, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("immediate_vertex", "immediate", "vertex"), &RenderingServer::immediate_vertex); - ClassDB::bind_method(D_METHOD("immediate_vertex_2d", "immediate", "vertex"), &RenderingServer::immediate_vertex_2d); - ClassDB::bind_method(D_METHOD("immediate_normal", "immediate", "normal"), &RenderingServer::immediate_normal); - ClassDB::bind_method(D_METHOD("immediate_tangent", "immediate", "tangent"), &RenderingServer::immediate_tangent); - ClassDB::bind_method(D_METHOD("immediate_color", "immediate", "color"), &RenderingServer::immediate_color); - ClassDB::bind_method(D_METHOD("immediate_uv", "immediate", "tex_uv"), &RenderingServer::immediate_uv); - ClassDB::bind_method(D_METHOD("immediate_uv2", "immediate", "tex_uv"), &RenderingServer::immediate_uv2); - ClassDB::bind_method(D_METHOD("immediate_end", "immediate"), &RenderingServer::immediate_end); - ClassDB::bind_method(D_METHOD("immediate_clear", "immediate"), &RenderingServer::immediate_clear); - ClassDB::bind_method(D_METHOD("immediate_set_material", "immediate", "material"), &RenderingServer::immediate_set_material); - ClassDB::bind_method(D_METHOD("immediate_get_material", "immediate"), &RenderingServer::immediate_get_material); -#endif ClassDB::bind_method(D_METHOD("skeleton_create"), &RenderingServer::skeleton_create); ClassDB::bind_method(D_METHOD("skeleton_allocate_data", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate_data, DEFVAL(false)); @@ -2113,7 +2100,6 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(INSTANCE_NONE); BIND_ENUM_CONSTANT(INSTANCE_MESH); BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH); - BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE); BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); BIND_ENUM_CONSTANT(INSTANCE_PARTICLES_COLLISION); BIND_ENUM_CONSTANT(INSTANCE_LIGHT); @@ -2253,10 +2239,6 @@ void RenderingServer::mesh_add_surface_from_planes(RID p_mesh, const Vector<Plan mesh_add_surface_from_mesh_data(p_mesh, mdata); } -void RenderingServer::immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex) { - immediate_vertex(p_immediate, Vector3(p_vertex.x, p_vertex.y, 0)); -} - RID RenderingServer::instance_create2(RID p_base, RID p_scenario) { RID instance = instance_create(); instance_set_base(instance, p_base); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 0a568eeb13..431d1a827c 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -342,7 +342,9 @@ public: virtual void mesh_set_blend_shape_mode(RID p_mesh, BlendShapeMode p_mode) = 0; virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; @@ -390,22 +392,6 @@ public: virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - /* IMMEDIATE API */ - - virtual RID immediate_create() = 0; - virtual void immediate_begin(RID p_immediate, PrimitiveType p_rimitive, RID p_texture = RID()) = 0; - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; - virtual void immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex); - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; - virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_end(RID p_immediate) = 0; - virtual void immediate_clear(RID p_immediate) = 0; - virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; - virtual RID immediate_get_material(RID p_immediate) const = 0; - /* SKELETON API */ virtual RID skeleton_create() = 0; @@ -1146,7 +1132,6 @@ public: INSTANCE_NONE, INSTANCE_MESH, INSTANCE_MULTIMESH, - INSTANCE_IMMEDIATE, INSTANCE_PARTICLES, INSTANCE_PARTICLES_COLLISION, INSTANCE_LIGHT, @@ -1158,7 +1143,7 @@ public: INSTANCE_VISIBLITY_NOTIFIER, INSTANCE_MAX, - INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES) + INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_PARTICLES) }; virtual RID instance_create2(RID p_base, RID p_scenario); |