Particle internal refactor and additions for more artistic control

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Co-authored-by: Mew Pur Pur <85438892+MewPurPur@users.noreply.github.com>
Co-authored-by: Clay John <claynjohn@gmail.com>
This commit is contained in:
QbieShay 2023-08-13 13:08:52 +02:00
parent 6916349697
commit c228fe1a0d
24 changed files with 1232 additions and 518 deletions

View File

@ -50,6 +50,10 @@
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8"> <member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
Number of particles emitted in one emission cycle. Number of particles emitted in one emission cycle.
</member> </member>
<member name="amount_ratio" type="float" setter="set_amount_ratio" getter="get_amount_ratio" default="1.0">
The ratio of particles that should actually be emitted. If set to a value lower than [code]1.0[/code], this will set the amount of emitted particles throughout the lifetime to [code]amount * amount_ratio[/code]. Unlike changing [member amount], changing [member amount_ratio] while emitting does not affect already-emitted particles and doesn't cause the particle system to restart. [member amount_ratio] can be used to create effects that make the number of emitted particles vary over time.
[b]Note:[/b] Reducing the [member amount_ratio] has no performance benefit, since resources need to be allocated and processed for the total [member amount] of particles regardless of the [member amount_ratio].
</member>
<member name="collision_base_size" type="float" setter="set_collision_base_size" getter="get_collision_base_size" default="1.0"> <member name="collision_base_size" type="float" setter="set_collision_base_size" getter="get_collision_base_size" default="1.0">
Multiplier for particle's collision radius. [code]1.0[/code] corresponds to the size of the sprite. Multiplier for particle's collision radius. [code]1.0[/code] corresponds to the size of the sprite.
</member> </member>
@ -68,6 +72,10 @@
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true"> <member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true">
If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect. If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect.
</member> </member>
<member name="interp_to_end" type="float" setter="set_interp_to_end" getter="get_interp_to_end" default="0.0">
Causes all the particles in this node to interpolate towards the end of their lifetime.
[b]Note[/b]: This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
</member>
<member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true"> <member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true">
Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate. Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate.
</member> </member>

View File

@ -63,6 +63,10 @@
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8"> <member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
Number of particles to emit. Number of particles to emit.
</member> </member>
<member name="amount_ratio" type="float" setter="set_amount_ratio" getter="get_amount_ratio" default="1.0">
The ratio of particles that should actually be emitted. If set to a value lower than [code]1.0[/code], this will set the amount of emitted particles throughout the lifetime to [code]amount * amount_ratio[/code]. Unlike changing [member amount], changing [member amount_ratio] while emitting does not affect already-emitted particles and doesn't cause the particle system to restart. [member amount_ratio] can be used to create effects that make the number of emitted particles vary over time.
[b]Note:[/b] Reducing the [member amount_ratio] has no performance benefit, since resources need to be allocated and processed for the total [member amount] of particles regardless of the [member amount_ratio].
</member>
<member name="collision_base_size" type="float" setter="set_collision_base_size" getter="get_collision_base_size" default="0.01"> <member name="collision_base_size" type="float" setter="set_collision_base_size" getter="get_collision_base_size" default="0.01">
</member> </member>
<member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles3D.DrawOrder" default="0"> <member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles3D.DrawOrder" default="0">
@ -98,6 +102,10 @@
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true"> <member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true">
If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect. If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect.
</member> </member>
<member name="interp_to_end" type="float" setter="set_interp_to_end" getter="get_interp_to_end" default="0.0">
Causes all the particles in this node to interpolate towards the end of their lifetime.
[b]Note[/b]: This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
</member>
<member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true"> <member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true">
Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate. Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate.
</member> </member>

View File

@ -71,6 +71,9 @@
</method> </method>
</methods> </methods>
<members> <members>
<member name="alpha_curve" type="Texture2D" setter="set_alpha_curve" getter="get_alpha_curve">
The alpha value of each particle's color will be multiplied by this [CurveTexture] over its lifetime.
</member>
<member name="angle_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> <member name="angle_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's rotation will be animated along this [CurveTexture]. Each particle's rotation will be animated along this [CurveTexture].
</member> </member>
@ -151,6 +154,18 @@
<member name="direction" type="Vector3" setter="set_direction" getter="get_direction" default="Vector3(1, 0, 0)"> <member name="direction" type="Vector3" setter="set_direction" getter="get_direction" default="Vector3(1, 0, 0)">
Unit vector specifying the particles' emission direction. Unit vector specifying the particles' emission direction.
</member> </member>
<member name="directional_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
A curve that specifies the velocity along each of the axes of the particle system along its lifetime.
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="directional_velocity_max" type="float" setter="set_param_max" getter="get_param_max">
Maximum directional velocity value, which is multiplied by [member directional_velocity_curve].
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="directional_velocity_min" type="float" setter="set_param_min" getter="get_param_min">
Minimum directional velocity value, which is multiplied by [member directional_velocity_curve].
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="emission_box_extents" type="Vector3" setter="set_emission_box_extents" getter="get_emission_box_extents"> <member name="emission_box_extents" type="Vector3" setter="set_emission_box_extents" getter="get_emission_box_extents">
The box's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_BOX]. The box's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_BOX].
</member> </member>
@ -158,6 +173,10 @@
Particle color will be modulated by color determined by sampling this texture at the same point as the [member emission_point_texture]. Particle color will be modulated by color determined by sampling this texture at the same point as the [member emission_point_texture].
[b]Note:[/b] [member emission_color_texture] multiplies the particle mesh's vertex colors. To have a visible effect on a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member emission_color_texture] will have no visible effect. [b]Note:[/b] [member emission_color_texture] multiplies the particle mesh's vertex colors. To have a visible effect on a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member emission_color_texture] will have no visible effect.
</member> </member>
<member name="emission_curve" type="Texture2D" setter="set_emission_curve" getter="get_emission_curve">
Each particle's color will be multiplied by this [CurveTexture] over its lifetime.
[b]Note:[/b] This property won't have a visible effect unless the render material is marked as unshaded.
</member>
<member name="emission_normal_texture" type="Texture2D" setter="set_emission_normal_texture" getter="get_emission_normal_texture"> <member name="emission_normal_texture" type="Texture2D" setter="set_emission_normal_texture" getter="get_emission_normal_texture">
Particle velocity and rotation will be set by sampling this texture at the same point as the [member emission_point_texture]. Used only in [constant EMISSION_SHAPE_DIRECTED_POINTS]. Can be created automatically from mesh or node by selecting "Create Emission Points from Mesh/Node" under the "Particles" tool in the toolbar. Particle velocity and rotation will be set by sampling this texture at the same point as the [member emission_point_texture]. Used only in [constant EMISSION_SHAPE_DIRECTED_POINTS]. Can be created automatically from mesh or node by selecting "Create Emission Points from Mesh/Node" under the "Particles" tool in the toolbar.
</member> </member>
@ -182,6 +201,12 @@
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticleProcessMaterial.EmissionShape" default="0"> <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticleProcessMaterial.EmissionShape" default="0">
Particles will be emitted inside this region. Use [enum EmissionShape] constants for values. Particles will be emitted inside this region. Use [enum EmissionShape] constants for values.
</member> </member>
<member name="emission_shape_offset" type="Vector3" setter="set_emission_shape_offset" getter="get_emission_shape_offset" default="Vector3(0, 0, 0)">
The offset for the [member emission_shape], in local space.
</member>
<member name="emission_shape_scale" type="Vector3" setter="set_emission_shape_scale" getter="get_emission_shape_scale" default="Vector3(1, 1, 1)">
The scale of the [member emission_shape], in local space.
</member>
<member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius"> <member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius">
The sphere's radius if [member emission_shape] is set to [constant EMISSION_SHAPE_SPHERE]. The sphere's radius if [member emission_shape] is set to [constant EMISSION_SHAPE_SPHERE].
</member> </member>
@ -200,6 +225,9 @@
<member name="hue_variation_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> <member name="hue_variation_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum equivalent of [member hue_variation_max]. Minimum equivalent of [member hue_variation_max].
</member> </member>
<member name="inherit_velocity_ratio" type="float" setter="set_inherit_velocity_ratio" getter="get_inherit_velocity_ratio" default="0.0">
Percentage of the velocity of the respective [GPUParticles2D] or [GPUParticles3D] inherited by each particle when spawning.
</member>
<member name="initial_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0"> <member name="initial_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
Maximum initial velocity magnitude for each particle. Direction comes from [member direction] and [member spread]. Maximum initial velocity magnitude for each particle. Direction comes from [member direction] and [member spread].
</member> </member>
@ -220,17 +248,23 @@
</member> </member>
<member name="orbit_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> <member name="orbit_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's orbital velocity will vary along this [CurveTexture]. Each particle's orbital velocity will vary along this [CurveTexture].
[b]Note:[/b] For 3D orbital velocity, use a [CurveXYZTexture].
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member> </member>
<member name="orbit_velocity_max" type="float" setter="set_param_max" getter="get_param_max"> <member name="orbit_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
Maximum orbital velocity applied to each particle. Makes the particles circle around origin. Specified in number of full rotations around origin per second. Maximum orbital velocity applied to each particle. Makes the particles circle around origin. Specified in number of full rotations around origin per second.
Only available when [member particle_flag_disable_z] is [code]true[/code]. [b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member> </member>
<member name="orbit_velocity_min" type="float" setter="set_param_min" getter="get_param_min"> <member name="orbit_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum equivalent of [member orbit_velocity_max]. Minimum equivalent of [member orbit_velocity_max].
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member> </member>
<member name="particle_flag_align_y" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false"> <member name="particle_flag_align_y" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
Align Y axis of particle with the direction of its velocity. Align Y axis of particle with the direction of its velocity.
</member> </member>
<member name="particle_flag_damping_as_friction" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
Changes the behavior of the damping properties from a linear deceleration to a deceleration based on speed percentage.
</member>
<member name="particle_flag_disable_z" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false"> <member name="particle_flag_disable_z" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
If [code]true[/code], particles will not move on the z axis. If [code]true[/code], particles will not move on the z axis.
</member> </member>
@ -246,6 +280,18 @@
<member name="radial_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> <member name="radial_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum equivalent of [member radial_accel_max]. Minimum equivalent of [member radial_accel_max].
</member> </member>
<member name="radial_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
A [CurveTexture] that defines the velocity over the particle's lifetime away (or toward) the [member velocity_pivot].
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="radial_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
Maximum radial velocity applied to each particle. Makes particles move away from the [member velocity_pivot], or toward it if negative.
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="radial_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum radial velocity applied to each particle. Makes particles move away from the [member velocity_pivot], or toward it if negative.
[b]Note:[/b] Animated velocities will not be affected by damping, use [member velocity_limit_curve] instead.
</member>
<member name="scale_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> <member name="scale_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's scale will vary along this [CurveTexture]. If a [CurveXYZTexture] is supplied instead, the scale will be separated per-axis. Each particle's scale will vary along this [CurveTexture]. If a [CurveXYZTexture] is supplied instead, the scale will be separated per-axis.
</member> </member>
@ -255,6 +301,17 @@
<member name="scale_min" type="float" setter="set_param_min" getter="get_param_min" default="1.0"> <member name="scale_min" type="float" setter="set_param_min" getter="get_param_min" default="1.0">
Minimum equivalent of [member scale_max]. Minimum equivalent of [member scale_max].
</member> </member>
<member name="scale_over_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Either a [CurveTexture] or a [CurveXYZTexture] that scales each particle based on its velocity.
</member>
<member name="scale_over_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
Maximum velocity value reference for [member scale_over_velocity_curve].
[member scale_over_velocity_curve] will be interpolated between [member scale_over_velocity_min] and [member scale_over_velocity_max].
</member>
<member name="scale_over_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum velocity value reference for [member scale_over_velocity_curve].
[member scale_over_velocity_curve] will be interpolated between [member scale_over_velocity_min] and [member scale_over_velocity_max].
</member>
<member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0"> <member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0">
Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees.
</member> </member>
@ -317,6 +374,11 @@
<member name="turbulence_noise_strength" type="float" setter="set_turbulence_noise_strength" getter="get_turbulence_noise_strength" default="1.0"> <member name="turbulence_noise_strength" type="float" setter="set_turbulence_noise_strength" getter="get_turbulence_noise_strength" default="1.0">
The turbulence noise strength. Increasing this will result in a stronger, more contrasting, flow pattern. The turbulence noise strength. Increasing this will result in a stronger, more contrasting, flow pattern.
</member> </member>
<member name="velocity_limit_curve" type="Texture2D" setter="set_velocity_limit_curve" getter="get_velocity_limit_curve">
A [CurveTexture] that defines the maximum velocity of a particle during its lifetime.
</member>
<member name="velocity_pivot" type="Vector3" setter="set_velocity_pivot" getter="get_velocity_pivot" default="Vector3(0, 0, 0)">
</member>
</members> </members>
<constants> <constants>
<constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter"> <constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter">
@ -355,7 +417,16 @@
<constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter"> <constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter">
Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set animation offset properties. Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set animation offset properties.
</constant> </constant>
<constant name="PARAM_MAX" value="15" enum="Parameter"> <constant name="PARAM_RADIAL_VELOCITY" value="15" enum="Parameter">
Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set radial velocity properties.
</constant>
<constant name="PARAM_DIRECTIONAL_VELOCITY" value="16" enum="Parameter">
Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set directional velocity properties.
</constant>
<constant name="PARAM_SCALE_OVER_VELOCITY" value="17" enum="Parameter">
Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set scale over velocity properties.
</constant>
<constant name="PARAM_MAX" value="18" enum="Parameter">
Represents the size of the [enum Parameter] enum. Represents the size of the [enum Parameter] enum.
</constant> </constant>
<constant name="PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="ParticleFlags"> <constant name="PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="ParticleFlags">
@ -367,7 +438,9 @@
<constant name="PARTICLE_FLAG_DISABLE_Z" value="2" enum="ParticleFlags"> <constant name="PARTICLE_FLAG_DISABLE_Z" value="2" enum="ParticleFlags">
Use with [method set_particle_flag] to set [member particle_flag_disable_z]. Use with [method set_particle_flag] to set [member particle_flag_disable_z].
</constant> </constant>
<constant name="PARTICLE_FLAG_MAX" value="3" enum="ParticleFlags"> <constant name="PARTICLE_FLAG_DAMPING_AS_FRICTION" value="3" enum="ParticleFlags">
</constant>
<constant name="PARTICLE_FLAG_MAX" value="4" enum="ParticleFlags">
Represents the size of the [enum ParticleFlags] enum. Represents the size of the [enum ParticleFlags] enum.
</constant> </constant>
<constant name="EMISSION_SHAPE_POINT" value="0" enum="EmissionShape"> <constant name="EMISSION_SHAPE_POINT" value="0" enum="EmissionShape">

View File

@ -2627,6 +2627,14 @@
Sets the number of particles to be drawn and allocates the memory for them. Equivalent to [member GPUParticles3D.amount]. Sets the number of particles to be drawn and allocates the memory for them. Equivalent to [member GPUParticles3D.amount].
</description> </description>
</method> </method>
<method name="particles_set_amount_ratio">
<return type="void" />
<param index="0" name="particles" type="RID" />
<param index="1" name="ratio" type="float" />
<description>
Sets the amount ratio for particles to be emitted. Equivalent to [member GPUParticles3D.amount_ratio].
</description>
</method>
<method name="particles_set_collision_base_size"> <method name="particles_set_collision_base_size">
<return type="void" /> <return type="void" />
<param index="0" name="particles" type="RID" /> <param index="0" name="particles" type="RID" />
@ -2675,6 +2683,14 @@
Sets the [Transform3D] that will be used by the particles when they first emit. Sets the [Transform3D] that will be used by the particles when they first emit.
</description> </description>
</method> </method>
<method name="particles_set_emitter_velocity">
<return type="void" />
<param index="0" name="particles" type="RID" />
<param index="1" name="velocity" type="Vector3" />
<description>
Sets the velocity of a particle node, that will be used by [member ParticleProcessMaterial.inherit_velocity_ratio].
</description>
</method>
<method name="particles_set_emitting"> <method name="particles_set_emitting">
<return type="void" /> <return type="void" />
<param index="0" name="particles" type="RID" /> <param index="0" name="particles" type="RID" />
@ -2707,6 +2723,14 @@
If [code]true[/code], uses fractional delta which smooths the movement of the particles. Equivalent to [member GPUParticles3D.fract_delta]. If [code]true[/code], uses fractional delta which smooths the movement of the particles. Equivalent to [member GPUParticles3D.fract_delta].
</description> </description>
</method> </method>
<method name="particles_set_interp_to_end">
<return type="void" />
<param index="0" name="particles" type="RID" />
<param index="1" name="factor" type="float" />
<description>
Sets the value that informs a [ParticleProcessMaterial] to rush all particles towards the end of their lifetime.
</description>
</method>
<method name="particles_set_interpolate"> <method name="particles_set_interpolate">
<return type="void" /> <return type="void" />
<param index="0" name="particles" type="RID" /> <param index="0" name="particles" type="RID" />

View File

@ -78,7 +78,7 @@ layout(std140) uniform FrameData { //ubo:0
float delta; float delta;
float particle_size; float particle_size;
float pad0; float amount_ratio;
float pad1; float pad1;
float pad2; float pad2;
@ -89,6 +89,9 @@ layout(std140) uniform FrameData { //ubo:0
mat4 emission_transform; mat4 emission_transform;
vec3 emitter_velocity;
float interp_to_end;
Attractor attractors[MAX_ATTRACTORS]; Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS]; Collider colliders[MAX_COLLIDERS];
}; };

View File

@ -1395,6 +1395,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["DELTA"] = "local_delta"; actions.renames["DELTA"] = "local_delta";
actions.renames["NUMBER"] = "particle_number"; actions.renames["NUMBER"] = "particle_number";
actions.renames["INDEX"] = "index"; actions.renames["INDEX"] = "index";
actions.renames["AMOUNT_RATIO"] = "amount_ratio";
//actions.renames["GRAVITY"] = "current_gravity"; //actions.renames["GRAVITY"] = "current_gravity";
actions.renames["EMISSION_TRANSFORM"] = "emission_transform"; actions.renames["EMISSION_TRANSFORM"] = "emission_transform";
actions.renames["RANDOM_SEED"] = "random_seed"; actions.renames["RANDOM_SEED"] = "random_seed";
@ -1407,6 +1408,8 @@ MaterialStorage::MaterialStorage() {
actions.renames["COLLISION_NORMAL"] = "collision_normal"; actions.renames["COLLISION_NORMAL"] = "collision_normal";
actions.renames["COLLISION_DEPTH"] = "collision_depth"; actions.renames["COLLISION_DEPTH"] = "collision_depth";
actions.renames["ATTRACTOR_FORCE"] = "attractor_force"; actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
actions.renames["EMITTER_VELOCITY"] = "emitter_velocity";
actions.renames["INTERPOLATE_TO_END"] = "interp_to_end";
// These are unsupported, but may be used by users. To avoid compile time overhead, we add the stub only when used. // These are unsupported, but may be used by users. To avoid compile time overhead, we add the stub only when used.
actions.renames["FLAG_EMIT_POSITION"] = "uint(1)"; actions.renames["FLAG_EMIT_POSITION"] = "uint(1)";

View File

@ -190,6 +190,13 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
} }
void ParticlesStorage::particles_set_amount_ratio(RID p_particles, float p_amount_ratio) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->amount_ratio = p_amount_ratio;
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
Particles *particles = particles_owner.get_or_null(p_particles); Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles); ERR_FAIL_NULL(particles);
@ -431,6 +438,20 @@ void ParticlesStorage::particles_set_emission_transform(RID p_particles, const T
particles->emission_transform = p_transform; particles->emission_transform = p_transform;
} }
void ParticlesStorage::particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->emitter_velocity = p_velocity;
}
void ParticlesStorage::particles_set_interp_to_end(RID p_particles, float p_interp) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->interp_to_end = p_interp;
}
int ParticlesStorage::particles_get_draw_passes(RID p_particles) const { int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
const Particles *particles = particles_owner.get_or_null(p_particles); const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, 0); ERR_FAIL_NULL_V(particles, 0);
@ -507,9 +528,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
frame_params.cycle = p_particles->cycle_number; frame_params.cycle = p_particles->cycle_number;
frame_params.frame = p_particles->frame_counter++; frame_params.frame = p_particles->frame_counter++;
frame_params.pad0 = 0; frame_params.amount_ratio = p_particles->amount_ratio;
frame_params.pad1 = 0; frame_params.pad1 = 0;
frame_params.pad2 = 0; frame_params.pad2 = 0;
frame_params.interp_to_end = p_particles->interp_to_end;
frame_params.emitter_velocity[0] = p_particles->emitter_velocity.x;
frame_params.emitter_velocity[1] = p_particles->emitter_velocity.y;
frame_params.emitter_velocity[2] = p_particles->emitter_velocity.z;
{ //collision and attractors { //collision and attractors

View File

@ -128,7 +128,7 @@ private:
float delta; float delta;
float particle_size; float particle_size;
float pad0; float amount_ratio;
float pad1; float pad1;
float pad2; float pad2;
@ -138,6 +138,8 @@ private:
uint32_t frame; uint32_t frame;
float emission_transform[16]; float emission_transform[16];
float emitter_velocity[3];
float interp_to_end;
Attractor attractors[MAX_ATTRACTORS]; Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS]; Collider colliders[MAX_COLLIDERS];
@ -149,6 +151,7 @@ private:
double inactive_time = 0.0; double inactive_time = 0.0;
bool emitting = false; bool emitting = false;
bool one_shot = false; bool one_shot = false;
float amount_ratio = 1.0;
int amount = 0; int amount = 0;
double lifetime = 1.0; double lifetime = 1.0;
double pre_process_time = 0.0; double pre_process_time = 0.0;
@ -229,6 +232,8 @@ private:
bool clear = true; bool clear = true;
Transform3D emission_transform; Transform3D emission_transform;
Vector3 emitter_velocity;
float interp_to_end;
HashSet<RID> collisions; HashSet<RID> collisions;
@ -313,6 +318,7 @@ public:
virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override; virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override; virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
virtual void particles_set_amount(RID p_particles, int p_amount) override; virtual void particles_set_amount(RID p_particles, int p_amount) override;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override; virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override; virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override; virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
@ -347,6 +353,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const override; virtual AABB particles_get_aabb(RID p_particles) const override;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp) override;
virtual bool particles_get_emitting(RID p_particles) override; virtual bool particles_get_emitting(RID p_particles) override;
virtual int particles_get_draw_passes(RID p_particles) const override; virtual int particles_get_draw_passes(RID p_particles) const override;

View File

@ -287,3 +287,9 @@ Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/shader_ge
Validate extension JSON: Error: Field 'classes/SurfaceTool/methods/commit/arguments/1': meta changed value in new API, from "uint32" to "uint64". Validate extension JSON: Error: Field 'classes/SurfaceTool/methods/commit/arguments/1': meta changed value in new API, from "uint32" to "uint64".
Surface format was increased to 64 bits from 32 bits. Compatibility methods registered. Surface format was increased to 64 bits from 32 bits. Compatibility methods registered.
GH-79527
--------
Validate extension JSON: Error: Field 'classes/ParticleProcessMaterial/properties/orbit_velocity_curve': type changed value in new API, from "CurveTexture" to "CurveTexture,CurveXYZTexture".
Added accepted curve type from only CurveTexture to CurveXYZTexture.

View File

@ -192,6 +192,11 @@ void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) {
queue_redraw(); queue_redraw();
} }
void GPUParticles2D::set_interp_to_end(float p_interp) {
interp_to_end_factor = CLAMP(p_interp, 0.0, 1.0);
RS::get_singleton()->particles_set_interp_to_end(particles, interp_to_end_factor);
}
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
void GPUParticles2D::set_show_visibility_rect(bool p_show_visibility_rect) { void GPUParticles2D::set_show_visibility_rect(bool p_show_visibility_rect) {
show_visibility_rect = p_show_visibility_rect; show_visibility_rect = p_show_visibility_rect;
@ -318,6 +323,10 @@ bool GPUParticles2D::get_interpolate() const {
return interpolate; return interpolate;
} }
float GPUParticles2D::get_interp_to_end() const {
return interp_to_end_factor;
}
PackedStringArray GPUParticles2D::get_configuration_warnings() const { PackedStringArray GPUParticles2D::get_configuration_warnings() const {
PackedStringArray warnings = Node2D::get_configuration_warnings(); PackedStringArray warnings = Node2D::get_configuration_warnings();
@ -423,6 +432,15 @@ NodePath GPUParticles2D::get_sub_emitter() const {
return sub_emitter; return sub_emitter;
} }
void GPUParticles2D::set_amount_ratio(float p_ratio) {
amount_ratio = p_ratio;
RenderingServer::get_singleton()->particles_set_amount_ratio(particles, p_ratio);
}
float GPUParticles2D::get_amount_ratio() const {
return amount_ratio;
}
void GPUParticles2D::restart() { void GPUParticles2D::restart() {
RS::get_singleton()->particles_restart(particles); RS::get_singleton()->particles_restart(particles);
RS::get_singleton()->particles_set_emitting(particles, true); RS::get_singleton()->particles_set_emitting(particles, true);
@ -670,6 +688,8 @@ void GPUParticles2D::_notification(int p_what) {
} else { } else {
RS::get_singleton()->particles_set_speed_scale(particles, 0); RS::get_singleton()->particles_set_speed_scale(particles, 0);
} }
set_process_internal(true);
previous_position = get_global_position();
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
@ -692,6 +712,12 @@ void GPUParticles2D::_notification(int p_what) {
} break; } break;
case NOTIFICATION_INTERNAL_PROCESS: { case NOTIFICATION_INTERNAL_PROCESS: {
RS::get_singleton()->particles_set_emitter_velocity(particles,
Vector3((get_global_position() - previous_position).x,
(get_global_position() - previous_position).y,
0.0) /
get_process_delta_time());
previous_position = get_global_position();
if (one_shot) { if (one_shot) {
time += get_process_delta_time(); time += get_process_delta_time();
if (time > emission_time) { if (time > emission_time) {
@ -730,6 +756,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles2D::set_process_material); ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles2D::set_process_material);
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles2D::set_speed_scale); ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles2D::set_speed_scale);
ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles2D::set_collision_base_size); ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles2D::set_collision_base_size);
ClassDB::bind_method(D_METHOD("set_interp_to_end", "interp"), &GPUParticles2D::set_interp_to_end);
ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles2D::is_emitting); ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles2D::get_amount); ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles2D::get_amount);
@ -746,6 +773,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles2D::get_process_material); ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles2D::get_process_material);
ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles2D::get_speed_scale); ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles2D::get_speed_scale);
ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles2D::get_collision_base_size); ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles2D::get_collision_base_size);
ClassDB::bind_method(D_METHOD("get_interp_to_end"), &GPUParticles2D::get_interp_to_end);
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles2D::set_draw_order); ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles2D::set_draw_order);
ClassDB::bind_method(D_METHOD("get_draw_order"), &GPUParticles2D::get_draw_order); ClassDB::bind_method(D_METHOD("get_draw_order"), &GPUParticles2D::get_draw_order);
@ -776,11 +804,15 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &GPUParticles2D::convert_from_particles); ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &GPUParticles2D::convert_from_particles);
ClassDB::bind_method(D_METHOD("set_amount_ratio", "ratio"), &GPUParticles2D::set_amount_ratio);
ClassDB::bind_method(D_METHOD("get_amount_ratio"), &GPUParticles2D::get_amount_ratio);
ADD_SIGNAL(MethodInfo("finished")); ADD_SIGNAL(MethodInfo("finished"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false.
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material");
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, "Texture2D"), "set_texture", "get_texture");
@ -794,6 +826,7 @@ void GPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1,suffix:FPS"), "set_fixed_fps", "get_fixed_fps"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1,suffix:FPS"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interpolate"), "set_interpolate", "get_interpolate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interpolate"), "set_interpolate", "get_interpolate");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interp_to_end", PROPERTY_HINT_RANGE, "0.00,1.0,0.001"), "set_interp_to_end", "get_interp_to_end");
ADD_GROUP("Collision", "collision_"); ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size");
ADD_GROUP("Drawing", ""); ADD_GROUP("Drawing", "");
@ -829,6 +862,7 @@ GPUParticles2D::GPUParticles2D() {
set_emitting(true); set_emitting(true);
set_one_shot(false); set_one_shot(false);
set_amount(8); set_amount(8);
set_amount_ratio(1.0);
set_lifetime(1); set_lifetime(1);
set_fixed_fps(0); set_fixed_fps(0);
set_fractional_delta(true); set_fractional_delta(true);

View File

@ -52,6 +52,7 @@ private:
bool signal_canceled = false; bool signal_canceled = false;
bool one_shot = false; bool one_shot = false;
int amount = 0; int amount = 0;
float amount_ratio = 1.0;
double lifetime = 0.0; double lifetime = 0.0;
double pre_process_time = 0.0; double pre_process_time = 0.0;
real_t explosiveness_ratio = 0.0; real_t explosiveness_ratio = 0.0;
@ -62,6 +63,8 @@ private:
int fixed_fps = 0; int fixed_fps = 0;
bool fractional_delta = false; bool fractional_delta = false;
bool interpolate = true; bool interpolate = true;
float interp_to_end_factor = 0;
Vector2 previous_position;
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
bool show_visibility_rect = false; bool show_visibility_rect = false;
#endif #endif
@ -114,6 +117,7 @@ public:
void set_trail_lifetime(double p_seconds); void set_trail_lifetime(double p_seconds);
void set_trail_sections(int p_sections); void set_trail_sections(int p_sections);
void set_trail_section_subdivisions(int p_subdivisions); void set_trail_section_subdivisions(int p_subdivisions);
void set_interp_to_end(float p_interp);
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
void set_show_visibility_rect(bool p_show_visibility_rect); void set_show_visibility_rect(bool p_show_visibility_rect);
@ -136,6 +140,7 @@ public:
double get_trail_lifetime() const; double get_trail_lifetime() const;
int get_trail_sections() const; int get_trail_sections() const;
int get_trail_section_subdivisions() const; int get_trail_section_subdivisions() const;
float get_interp_to_end() const;
void set_fixed_fps(int p_count); void set_fixed_fps(int p_count);
int get_fixed_fps() const; int get_fixed_fps() const;
@ -152,6 +157,9 @@ public:
void set_texture(const Ref<Texture2D> &p_texture); void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const; Ref<Texture2D> get_texture() const;
void set_amount_ratio(float p_ratio);
float get_amount_ratio() const;
PackedStringArray get_configuration_warnings() const override; PackedStringArray get_configuration_warnings() const override;
void set_sub_emitter(const NodePath &p_path); void set_sub_emitter(const NodePath &p_path);

View File

@ -61,6 +61,8 @@ void GPUParticles3D::set_emitting(bool p_emitting) {
} else { } else {
set_process_internal(false); set_process_internal(false);
} }
} else {
set_process_internal(true);
} }
emitting = p_emitting; emitting = p_emitting;
@ -79,20 +81,20 @@ void GPUParticles3D::set_lifetime(double p_lifetime) {
RS::get_singleton()->particles_set_lifetime(particles, lifetime); RS::get_singleton()->particles_set_lifetime(particles, lifetime);
} }
void GPUParticles3D::set_interp_to_end(float p_interp) {
interp_to_end_factor = CLAMP(p_interp, 0.0, 1.0);
RS::get_singleton()->particles_set_interp_to_end(particles, interp_to_end_factor);
}
void GPUParticles3D::set_one_shot(bool p_one_shot) { void GPUParticles3D::set_one_shot(bool p_one_shot) {
one_shot = p_one_shot; one_shot = p_one_shot;
RS::get_singleton()->particles_set_one_shot(particles, one_shot); RS::get_singleton()->particles_set_one_shot(particles, one_shot);
if (is_emitting()) { if (is_emitting()) {
set_process_internal(true);
if (!one_shot) { if (!one_shot) {
RenderingServer::get_singleton()->particles_restart(particles); RenderingServer::get_singleton()->particles_restart(particles);
} }
} }
if (!one_shot) {
set_process_internal(false);
}
} }
void GPUParticles3D::set_pre_process_time(double p_time) { void GPUParticles3D::set_pre_process_time(double p_time) {
@ -154,6 +156,10 @@ double GPUParticles3D::get_lifetime() const {
return lifetime; return lifetime;
} }
float GPUParticles3D::get_interp_to_end() const {
return interp_to_end_factor;
}
bool GPUParticles3D::get_one_shot() const { bool GPUParticles3D::get_one_shot() const {
return one_shot; return one_shot;
} }
@ -401,9 +407,7 @@ void GPUParticles3D::restart() {
time = 0; time = 0;
emission_time = lifetime * (1 - explosiveness_ratio); emission_time = lifetime * (1 - explosiveness_ratio);
active_time = lifetime * (2 - explosiveness_ratio); active_time = lifetime * (2 - explosiveness_ratio);
if (one_shot) { set_process_internal(true);
set_process_internal(true);
}
} }
AABB GPUParticles3D::capture_aabb() const { AABB GPUParticles3D::capture_aabb() const {
@ -456,6 +460,9 @@ void GPUParticles3D::_notification(int p_what) {
// Use internal process when emitting and one_shot is on so that when // Use internal process when emitting and one_shot is on so that when
// the shot ends the editor can properly update. // the shot ends the editor can properly update.
case NOTIFICATION_INTERNAL_PROCESS: { case NOTIFICATION_INTERNAL_PROCESS: {
RS::get_singleton()->particles_set_emitter_velocity(particles, (get_global_position() - previous_position) / get_process_delta_time());
previous_position = get_global_position();
if (one_shot) { if (one_shot) {
time += get_process_delta_time(); time += get_process_delta_time();
if (time > emission_time) { if (time > emission_time) {
@ -477,6 +484,7 @@ void GPUParticles3D::_notification(int p_what) {
} break; } break;
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
set_process_internal(false);
if (sub_emitter != NodePath()) { if (sub_emitter != NodePath()) {
_attach_sub_emitter(); _attach_sub_emitter();
} }
@ -485,6 +493,8 @@ void GPUParticles3D::_notification(int p_what) {
} else { } else {
RS::get_singleton()->particles_set_speed_scale(particles, 0); RS::get_singleton()->particles_set_speed_scale(particles, 0);
} }
previous_position = get_global_transform().origin;
set_process_internal(true);
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
@ -641,6 +651,15 @@ void GPUParticles3D::convert_from_particles(Node *p_particles) {
#undef CONVERT_PARAM #undef CONVERT_PARAM
} }
void GPUParticles3D::set_amount_ratio(float p_ratio) {
amount_ratio = p_ratio;
RS::get_singleton()->particles_set_amount_ratio(particles, p_ratio);
}
float GPUParticles3D::get_amount_ratio() const {
return amount_ratio;
}
void GPUParticles3D::_bind_methods() { void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &GPUParticles3D::set_emitting); ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &GPUParticles3D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &GPUParticles3D::set_amount); ClassDB::bind_method(D_METHOD("set_amount", "amount"), &GPUParticles3D::set_amount);
@ -657,6 +676,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles3D::set_process_material); ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles3D::set_process_material);
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles3D::set_speed_scale); ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles3D::set_speed_scale);
ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles3D::set_collision_base_size); ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles3D::set_collision_base_size);
ClassDB::bind_method(D_METHOD("set_interp_to_end", "interp"), &GPUParticles3D::set_interp_to_end);
ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles3D::is_emitting); ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles3D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles3D::get_amount); ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles3D::get_amount);
@ -673,6 +693,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles3D::get_process_material); ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles3D::get_process_material);
ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles3D::get_speed_scale); ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles3D::get_speed_scale);
ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles3D::get_collision_base_size); ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles3D::get_collision_base_size);
ClassDB::bind_method(D_METHOD("get_interp_to_end"), &GPUParticles3D::get_interp_to_end);
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order); ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order);
@ -706,14 +727,19 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &GPUParticles3D::convert_from_particles); ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &GPUParticles3D::convert_from_particles);
ClassDB::bind_method(D_METHOD("set_amount_ratio", "ratio"), &GPUParticles3D::set_amount_ratio);
ClassDB::bind_method(D_METHOD("get_amount_ratio"), &GPUParticles3D::get_amount_ratio);
ADD_SIGNAL(MethodInfo("finished")); ADD_SIGNAL(MethodInfo("finished"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false.
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
ADD_GROUP("Time", ""); ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interp_to_end", PROPERTY_HINT_RANGE, "0.00,1.0,0.01"), "set_interp_to_end", "get_interp_to_end");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp,suffix:s"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp,suffix:s"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
@ -767,6 +793,7 @@ GPUParticles3D::GPUParticles3D() {
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
set_emitting(true); set_emitting(true);
set_one_shot(false); set_one_shot(false);
set_amount_ratio(1.0);
set_amount(8); set_amount(8);
set_lifetime(1); set_lifetime(1);
set_fixed_fps(30); set_fixed_fps(30);

View File

@ -65,6 +65,7 @@ private:
bool signal_canceled = false; bool signal_canceled = false;
bool one_shot = false; bool one_shot = false;
int amount = 0; int amount = 0;
float amount_ratio = 1.0;
double lifetime = 0.0; double lifetime = 0.0;
double pre_process_time = 0.0; double pre_process_time = 0.0;
real_t explosiveness_ratio = 0.0; real_t explosiveness_ratio = 0.0;
@ -93,6 +94,8 @@ private:
double time = 0.0; double time = 0.0;
double emission_time = 0.0; double emission_time = 0.0;
double active_time = 0.0; double active_time = 0.0;
float interp_to_end_factor = 0;
Vector3 previous_position;
void _attach_sub_emitter(); void _attach_sub_emitter();
@ -120,9 +123,11 @@ public:
void set_collision_base_size(real_t p_ratio); void set_collision_base_size(real_t p_ratio);
void set_trail_enabled(bool p_enabled); void set_trail_enabled(bool p_enabled);
void set_trail_lifetime(double p_seconds); void set_trail_lifetime(double p_seconds);
void set_interp_to_end(float p_interp);
bool is_emitting() const; bool is_emitting() const;
int get_amount() const; int get_amount() const;
double get_lifetime() const; double get_lifetime() const;
bool get_one_shot() const; bool get_one_shot() const;
double get_pre_process_time() const; double get_pre_process_time() const;
@ -135,6 +140,10 @@ public:
real_t get_collision_base_size() const; real_t get_collision_base_size() const;
bool is_trail_enabled() const; bool is_trail_enabled() const;
double get_trail_lifetime() const; double get_trail_lifetime() const;
float get_interp_to_end() const;
void set_amount_ratio(float p_ratio);
float get_amount_ratio() const;
void set_fixed_fps(int p_count); void set_fixed_fps(int p_count);
int get_fixed_fps() const; int get_fixed_fps() const;

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
#define PARTICLE_PROCESS_MATERIAL_H #define PARTICLE_PROCESS_MATERIAL_H
#include "core/templates/rid.h" #include "core/templates/rid.h"
#include "core/templates/self_list.h"
#include "scene/resources/material.h" #include "scene/resources/material.h"
/* /*
@ -61,6 +62,9 @@ public:
PARAM_TURB_INFLUENCE_OVER_LIFE, PARAM_TURB_INFLUENCE_OVER_LIFE,
PARAM_TURB_VEL_INFLUENCE, PARAM_TURB_VEL_INFLUENCE,
PARAM_TURB_INIT_DISPLACEMENT, PARAM_TURB_INIT_DISPLACEMENT,
PARAM_RADIAL_VELOCITY,
PARAM_DIRECTIONAL_VELOCITY,
PARAM_SCALE_OVER_VELOCITY,
PARAM_MAX PARAM_MAX
}; };
@ -69,6 +73,7 @@ public:
PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY,
PARTICLE_FLAG_ROTATE_Y, PARTICLE_FLAG_ROTATE_Y,
PARTICLE_FLAG_DISABLE_Z, PARTICLE_FLAG_DISABLE_Z,
PARTICLE_FLAG_DAMPING_AS_FRICTION,
PARTICLE_FLAG_MAX PARTICLE_FLAG_MAX
}; };
@ -102,35 +107,37 @@ public:
}; };
private: private:
union MaterialKey { struct MaterialKey {
// The bit size of the struct must be kept below or equal to 32 bits. // The bit size of the struct must be kept below or equal to 64 bits.
// Consider this when extending ParticleFlags, EmissionShape, or SubEmitterMode. // Consider this when extending ParticleFlags, EmissionShape, or SubEmitterMode.
struct { uint64_t texture_mask : PARAM_MAX;
uint32_t texture_mask : 16; uint64_t texture_color : 1;
uint32_t texture_color : 1; uint64_t particle_flags : PARTICLE_FLAG_MAX - 1;
uint32_t particle_flags : 4; uint64_t emission_shape : 3;
uint32_t emission_shape : 3; uint64_t invalid_key : 1;
uint32_t invalid_key : 1; uint64_t has_emission_color : 1;
uint32_t has_emission_color : 1; uint64_t sub_emitter : 2;
uint32_t sub_emitter : 2; uint64_t attractor_enabled : 1;
uint32_t attractor_enabled : 1; uint64_t collision_mode : 2;
uint32_t collision_mode : 2; uint64_t collision_scale : 1;
uint32_t collision_scale : 1; uint64_t turbulence_enabled : 1;
uint32_t turbulence_enabled : 1; uint64_t limiter_curve : 1;
}; uint64_t alpha_curve : 1;
uint64_t emission_curve : 1;
uint64_t has_initial_ramp : 1;
uint64_t key = 0; MaterialKey() {
memset(this, 0, sizeof(MaterialKey));
}
static uint32_t hash(const MaterialKey &p_key) { static uint32_t hash(const MaterialKey &p_key) {
return hash_murmur3_one_32(p_key.key); return hash_djb2_buffer((const uint8_t *)&p_key, sizeof(MaterialKey));
} }
bool operator==(const MaterialKey &p_key) const { bool operator==(const MaterialKey &p_key) const {
return key == p_key.key; return memcmp(this, &p_key, sizeof(MaterialKey)) == 0;
} }
bool operator<(const MaterialKey &p_key) const { bool operator<(const MaterialKey &p_key) const {
return key < p_key.key; return memcmp(this, &p_key, sizeof(MaterialKey)) < 0;
} }
}; };
@ -145,17 +152,6 @@ private:
_FORCE_INLINE_ MaterialKey _compute_key() const { _FORCE_INLINE_ MaterialKey _compute_key() const {
MaterialKey mk; MaterialKey mk;
mk.key = 0;
for (int i = 0; i < PARAM_MAX; i++) {
if (tex_parameters[i].is_valid()) {
mk.texture_mask |= (1 << i);
}
}
for (int i = 0; i < PARTICLE_FLAG_MAX; i++) {
if (particle_flags[i]) {
mk.particle_flags |= (1 << i);
}
}
mk.texture_color = color_ramp.is_valid() ? 1 : 0; mk.texture_color = color_ramp.is_valid() ? 1 : 0;
mk.emission_shape = emission_shape; mk.emission_shape = emission_shape;
@ -165,6 +161,21 @@ private:
mk.attractor_enabled = attractor_interaction_enabled; mk.attractor_enabled = attractor_interaction_enabled;
mk.collision_scale = collision_scale; mk.collision_scale = collision_scale;
mk.turbulence_enabled = turbulence_enabled; mk.turbulence_enabled = turbulence_enabled;
mk.limiter_curve = velocity_limit_curve.is_valid() ? 1 : 0;
mk.alpha_curve = alpha_curve.is_valid() ? 1 : 0;
mk.emission_curve = emission_curve.is_valid() ? 1 : 0;
mk.has_initial_ramp = color_initial_ramp.is_valid() ? 1 : 0;
for (int i = 0; i < PARAM_MAX; i++) {
if (tex_parameters[i].is_valid()) {
mk.texture_mask |= ((uint64_t)1 << i);
}
}
for (int i = 0; i < PARTICLE_FLAG_MAX; i++) {
if (particle_flags[i]) {
mk.particle_flags |= ((uint64_t)1 << i);
}
}
return mk; return mk;
} }
@ -180,44 +191,59 @@ private:
StringName initial_angle_min; StringName initial_angle_min;
StringName angular_velocity_min; StringName angular_velocity_min;
StringName orbit_velocity_min; StringName orbit_velocity_min;
StringName radial_velocity_min;
StringName linear_accel_min; StringName linear_accel_min;
StringName radial_accel_min; StringName radial_accel_min;
StringName tangent_accel_min; StringName tangent_accel_min;
StringName damping_min; StringName damping_min;
StringName scale_min; StringName scale_min;
StringName scale_over_velocity_min;
StringName hue_variation_min; StringName hue_variation_min;
StringName anim_speed_min; StringName anim_speed_min;
StringName anim_offset_min; StringName anim_offset_min;
StringName directional_velocity_min;
StringName initial_linear_velocity_max; StringName initial_linear_velocity_max;
StringName initial_angle_max; StringName initial_angle_max;
StringName angular_velocity_max; StringName angular_velocity_max;
StringName orbit_velocity_max; StringName orbit_velocity_max;
StringName radial_velocity_max;
StringName linear_accel_max; StringName linear_accel_max;
StringName radial_accel_max; StringName radial_accel_max;
StringName tangent_accel_max; StringName tangent_accel_max;
StringName damping_max; StringName damping_max;
StringName scale_max; StringName scale_max;
StringName scale_over_velocity_max;
StringName hue_variation_max; StringName hue_variation_max;
StringName anim_speed_max; StringName anim_speed_max;
StringName anim_offset_max; StringName anim_offset_max;
StringName directional_velocity_max;
StringName angle_texture; StringName angle_texture;
StringName angular_velocity_texture; StringName angular_velocity_texture;
StringName orbit_velocity_texture; StringName orbit_velocity_texture;
StringName radial_velocity_texture;
StringName linear_accel_texture; StringName linear_accel_texture;
StringName radial_accel_texture; StringName radial_accel_texture;
StringName tangent_accel_texture; StringName tangent_accel_texture;
StringName damping_texture; StringName damping_texture;
StringName scale_texture; StringName scale_texture;
StringName scale_over_velocity_texture;
StringName hue_variation_texture; StringName hue_variation_texture;
StringName anim_speed_texture; StringName anim_speed_texture;
StringName anim_offset_texture; StringName anim_offset_texture;
StringName velocity_limiter_texture;
StringName directional_velocity_texture;
StringName color; StringName color;
StringName color_ramp; StringName color_ramp;
StringName alpha_ramp;
StringName emission_ramp;
StringName color_initial_ramp; StringName color_initial_ramp;
StringName velocity_limit_curve;
StringName velocity_pivot;
StringName emission_sphere_radius; StringName emission_sphere_radius;
StringName emission_box_extents; StringName emission_box_extents;
StringName emission_texture_point_count; StringName emission_texture_point_count;
@ -228,6 +254,8 @@ private:
StringName emission_ring_height; StringName emission_ring_height;
StringName emission_ring_radius; StringName emission_ring_radius;
StringName emission_ring_inner_radius; StringName emission_ring_inner_radius;
StringName emission_shape_offset;
StringName emission_shape_scale;
StringName turbulence_enabled; StringName turbulence_enabled;
StringName turbulence_noise_strength; StringName turbulence_noise_strength;
@ -241,6 +269,7 @@ private:
StringName turbulence_initial_displacement_max; StringName turbulence_initial_displacement_max;
StringName gravity; StringName gravity;
StringName inherit_emitter_velocity_ratio;
StringName lifetime_randomness; StringName lifetime_randomness;
@ -272,7 +301,13 @@ private:
Ref<Texture2D> tex_parameters[PARAM_MAX]; Ref<Texture2D> tex_parameters[PARAM_MAX];
Color color; Color color;
Ref<Texture2D> color_ramp; Ref<Texture2D> color_ramp;
Ref<Texture2D> alpha_curve;
Ref<Texture2D> emission_curve;
Ref<Texture2D> color_initial_ramp; Ref<Texture2D> color_initial_ramp;
Ref<Texture2D> velocity_limit_curve;
bool directional_velocity_global = false;
Vector3 velocity_pivot;
bool particle_flags[PARTICLE_FLAG_MAX]; bool particle_flags[PARTICLE_FLAG_MAX];
@ -287,6 +322,8 @@ private:
real_t emission_ring_radius = 0.0f; real_t emission_ring_radius = 0.0f;
real_t emission_ring_inner_radius = 0.0f; real_t emission_ring_inner_radius = 0.0f;
int emission_point_count = 1; int emission_point_count = 1;
Vector3 emission_shape_offset;
Vector3 emission_shape_scale;
bool anim_loop = false; bool anim_loop = false;
@ -300,6 +337,7 @@ private:
Vector3 gravity; Vector3 gravity;
double lifetime_randomness = 0.0; double lifetime_randomness = 0.0;
double inherit_emitter_velocity_ratio = 0.0;
SubEmitterMode sub_emitter_mode; SubEmitterMode sub_emitter_mode;
double sub_emitter_frequency = 0.0; double sub_emitter_frequency = 0.0;
@ -328,6 +366,9 @@ public:
void set_flatness(float p_flatness); void set_flatness(float p_flatness);
float get_flatness() const; float get_flatness() const;
void set_velocity_pivot(const Vector3 &p_pivot);
Vector3 get_velocity_pivot();
void set_param_min(Parameter p_param, float p_value); void set_param_min(Parameter p_param, float p_value);
float get_param_min(Parameter p_param) const; float get_param_min(Parameter p_param) const;
@ -337,6 +378,11 @@ public:
void set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture); void set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_param_texture(Parameter p_param) const; Ref<Texture2D> get_param_texture(Parameter p_param) const;
void set_velocity_limit_curve(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_velocity_limit_curve() const;
void set_alpha_curve(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_alpha_curve() const;
void set_color(const Color &p_color); void set_color(const Color &p_color);
Color get_color() const; Color get_color() const;
@ -346,6 +392,9 @@ public:
void set_color_initial_ramp(const Ref<Texture2D> &p_texture); void set_color_initial_ramp(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_color_initial_ramp() const; Ref<Texture2D> get_color_initial_ramp() const;
void set_emission_curve(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_emission_curve() const;
void set_particle_flag(ParticleFlags p_particle_flag, bool p_enable); void set_particle_flag(ParticleFlags p_particle_flag, bool p_enable);
bool get_particle_flag(ParticleFlags p_particle_flag) const; bool get_particle_flag(ParticleFlags p_particle_flag) const;
@ -391,6 +440,9 @@ public:
void set_lifetime_randomness(double p_lifetime); void set_lifetime_randomness(double p_lifetime);
double get_lifetime_randomness() const; double get_lifetime_randomness() const;
void set_inherit_velocity_ratio(double p_ratio);
double get_inherit_velocity_ratio();
void set_attractor_interaction_enabled(bool p_enable); void set_attractor_interaction_enabled(bool p_enable);
bool is_attractor_interaction_enabled() const; bool is_attractor_interaction_enabled() const;
@ -425,6 +477,12 @@ public:
void set_sub_emitter_keep_velocity(bool p_enable); void set_sub_emitter_keep_velocity(bool p_enable);
bool get_sub_emitter_keep_velocity() const; bool get_sub_emitter_keep_velocity() const;
void set_emission_shape_offset(const Vector3 &p_emission_shape_offset);
Vector3 get_emission_shape_offset() const;
void set_emission_shape_scale(const Vector3 &p_emission_shape_scale);
Vector3 get_emission_shape_scale() const;
virtual RID get_shader_rid() const override; virtual RID get_shader_rid() const override;
virtual Shader::Mode get_shader_mode() const override; virtual Shader::Mode get_shader_mode() const override;

View File

@ -47,6 +47,7 @@ public:
virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {} virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {}
virtual void particles_set_amount(RID p_particles, int p_amount) override {} virtual void particles_set_amount(RID p_particles, int p_amount) override {}
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override {}
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {} virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {} virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {} virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {}
@ -81,6 +82,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); } virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {} virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override {}
virtual void particles_set_interp_to_end(RID p_particles, float p_interp) override {}
virtual bool particles_get_emitting(RID p_particles) override { return false; } virtual bool particles_get_emitting(RID p_particles) override { return false; }
virtual int particles_get_draw_passes(RID p_particles) const override { return 0; } virtual int particles_get_draw_passes(RID p_particles) const override { return 0; }

View File

@ -67,7 +67,7 @@ struct FrameParams {
float delta; float delta;
uint frame; uint frame;
uint pad0; float amount_ratio;
uint pad1; uint pad1;
uint pad2; uint pad2;
@ -77,6 +77,8 @@ struct FrameParams {
float particle_size; float particle_size;
mat4 emission_transform; mat4 emission_transform;
vec3 emitter_velocity;
float interp_to_end;
Attractor attractors[MAX_ATTRACTORS]; Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS]; Collider colliders[MAX_COLLIDERS];

View File

@ -72,6 +72,7 @@ ParticlesStorage::ParticlesStorage() {
actions.renames["ACTIVE"] = "particle_active"; actions.renames["ACTIVE"] = "particle_active";
actions.renames["RESTART"] = "restart"; actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "PARTICLE.custom"; actions.renames["CUSTOM"] = "PARTICLE.custom";
actions.renames["AMOUNT_RATIO"] = "FRAME.amount_ratio";
for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
String udname = "USERDATA" + itos(i + 1); String udname = "USERDATA" + itos(i + 1);
actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1); actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
@ -88,6 +89,8 @@ ParticlesStorage::ParticlesStorage() {
actions.renames["INDEX"] = "index"; actions.renames["INDEX"] = "index";
//actions.renames["GRAVITY"] = "current_gravity"; //actions.renames["GRAVITY"] = "current_gravity";
actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform"; actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
actions.renames["EMITTER_VELOCITY"] = "FRAME.emitter_velocity";
actions.renames["INTERPOLATE_TO_END"] = "FRAME.interp_to_end";
actions.renames["RANDOM_SEED"] = "FRAME.random_seed"; actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION"; actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE"; actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
@ -329,6 +332,13 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
} }
void ParticlesStorage::particles_set_amount_ratio(RID p_particles, float p_amount_ratio) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->amount_ratio = p_amount_ratio;
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
Particles *particles = particles_owner.get_or_null(p_particles); Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles); ERR_FAIL_NULL(particles);
@ -651,6 +661,20 @@ void ParticlesStorage::particles_set_emission_transform(RID p_particles, const T
particles->emission_transform = p_transform; particles->emission_transform = p_transform;
} }
void ParticlesStorage::particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->emitter_velocity = p_velocity;
}
void ParticlesStorage::particles_set_interp_to_end(RID p_particles, float p_interp) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->interp_to_end = p_interp;
}
int ParticlesStorage::particles_get_draw_passes(RID p_particles) const { int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
const Particles *particles = particles_owner.get_or_null(p_particles); const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, 0); ERR_FAIL_NULL_V(particles, 0);
@ -791,9 +815,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
frame_params.cycle = p_particles->cycle_number; frame_params.cycle = p_particles->cycle_number;
frame_params.frame = p_particles->frame_counter++; frame_params.frame = p_particles->frame_counter++;
frame_params.pad0 = 0; frame_params.amount_ratio = p_particles->amount_ratio;
frame_params.pad1 = 0; frame_params.pad1 = 0;
frame_params.pad2 = 0; frame_params.pad2 = 0;
frame_params.emitter_velocity[0] = p_particles->emitter_velocity.x;
frame_params.emitter_velocity[1] = p_particles->emitter_velocity.y;
frame_params.emitter_velocity[2] = p_particles->emitter_velocity.z;
frame_params.interp_to_end = p_particles->interp_to_end;
{ //collision and attractors { //collision and attractors

View File

@ -123,7 +123,7 @@ private:
float delta; float delta;
uint32_t frame; uint32_t frame;
uint32_t pad0; float amount_ratio;
uint32_t pad1; uint32_t pad1;
uint32_t pad2; uint32_t pad2;
@ -134,6 +134,9 @@ private:
float emission_transform[16]; float emission_transform[16];
float emitter_velocity[3];
float interp_to_end;
Attractor attractors[MAX_ATTRACTORS]; Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS]; Collider colliders[MAX_COLLIDERS];
}; };
@ -235,6 +238,9 @@ private:
bool force_sub_emit = false; bool force_sub_emit = false;
Transform3D emission_transform; Transform3D emission_transform;
Vector3 emitter_velocity;
float interp_to_end = 0.0;
float amount_ratio = 1.0;
Vector<uint8_t> emission_buffer_data; Vector<uint8_t> emission_buffer_data;
@ -425,6 +431,7 @@ public:
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override; virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
virtual void particles_set_amount(RID p_particles, int p_amount) override; virtual void particles_set_amount(RID p_particles, int p_amount) override;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override; virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override; virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override; virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
@ -460,6 +467,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const override; virtual AABB particles_get_aabb(RID p_particles) const override;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override; virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) override;
virtual bool particles_get_emitting(RID p_particles) override; virtual bool particles_get_emitting(RID p_particles) override;
virtual int particles_get_draw_passes(RID p_particles) const override; virtual int particles_get_draw_passes(RID p_particles) const override;

View File

@ -490,6 +490,7 @@ public:
FUNC2(particles_set_emitting, RID, bool) FUNC2(particles_set_emitting, RID, bool)
FUNC1R(bool, particles_get_emitting, RID) FUNC1R(bool, particles_get_emitting, RID)
FUNC2(particles_set_amount, RID, int) FUNC2(particles_set_amount, RID, int)
FUNC2(particles_set_amount_ratio, RID, float)
FUNC2(particles_set_lifetime, RID, double) FUNC2(particles_set_lifetime, RID, double)
FUNC2(particles_set_one_shot, RID, bool) FUNC2(particles_set_one_shot, RID, bool)
FUNC2(particles_set_pre_process_time, RID, double) FUNC2(particles_set_pre_process_time, RID, double)
@ -521,6 +522,8 @@ public:
FUNC1R(AABB, particles_get_current_aabb, RID) FUNC1R(AABB, particles_get_current_aabb, RID)
FUNC2(particles_set_emission_transform, RID, const Transform3D &) FUNC2(particles_set_emission_transform, RID, const Transform3D &)
FUNC2(particles_set_emitter_velocity, RID, const Vector3 &)
FUNC2(particles_set_interp_to_end, RID, float)
/* PARTICLES COLLISION */ /* PARTICLES COLLISION */

View File

@ -348,6 +348,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMITTER_VELOCITY"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INTERPOLATE_TO_END"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT);
@ -359,6 +361,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["AMOUNT_RATIO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_PARTICLES].functions["start"].main_function = true; shader_modes[RS::SHADER_PARTICLES].functions["start"].main_function = true;
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
@ -379,6 +382,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMITTER_VELOCITY"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INTERPOLATE_TO_END"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT);
@ -389,6 +394,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_DEPTH"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_DEPTH"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ATTRACTOR_FORCE"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ATTRACTOR_FORCE"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["AMOUNT_RATIO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_PARTICLES].functions["process"].main_function = true; shader_modes[RS::SHADER_PARTICLES].functions["process"].main_function = true;
{ {

View File

@ -49,6 +49,7 @@ public:
virtual bool particles_get_emitting(RID p_particles) = 0; virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0; virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) = 0;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0; virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0; virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
@ -85,6 +86,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const = 0; virtual AABB particles_get_aabb(RID p_particles) const = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) = 0;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) = 0;
virtual int particles_get_draw_passes(RID p_particles) const = 0; virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;

View File

@ -2497,11 +2497,14 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting); ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting);
ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &RenderingServer::particles_get_emitting); ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &RenderingServer::particles_get_emitting);
ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &RenderingServer::particles_set_amount); ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &RenderingServer::particles_set_amount);
ClassDB::bind_method(D_METHOD("particles_set_amount_ratio", "particles", "ratio"), &RenderingServer::particles_set_amount_ratio);
ClassDB::bind_method(D_METHOD("particles_set_lifetime", "particles", "lifetime"), &RenderingServer::particles_set_lifetime); ClassDB::bind_method(D_METHOD("particles_set_lifetime", "particles", "lifetime"), &RenderingServer::particles_set_lifetime);
ClassDB::bind_method(D_METHOD("particles_set_one_shot", "particles", "one_shot"), &RenderingServer::particles_set_one_shot); ClassDB::bind_method(D_METHOD("particles_set_one_shot", "particles", "one_shot"), &RenderingServer::particles_set_one_shot);
ClassDB::bind_method(D_METHOD("particles_set_pre_process_time", "particles", "time"), &RenderingServer::particles_set_pre_process_time); ClassDB::bind_method(D_METHOD("particles_set_pre_process_time", "particles", "time"), &RenderingServer::particles_set_pre_process_time);
ClassDB::bind_method(D_METHOD("particles_set_explosiveness_ratio", "particles", "ratio"), &RenderingServer::particles_set_explosiveness_ratio); ClassDB::bind_method(D_METHOD("particles_set_explosiveness_ratio", "particles", "ratio"), &RenderingServer::particles_set_explosiveness_ratio);
ClassDB::bind_method(D_METHOD("particles_set_randomness_ratio", "particles", "ratio"), &RenderingServer::particles_set_randomness_ratio); ClassDB::bind_method(D_METHOD("particles_set_randomness_ratio", "particles", "ratio"), &RenderingServer::particles_set_randomness_ratio);
ClassDB::bind_method(D_METHOD("particles_set_interp_to_end", "particles", "factor"), &RenderingServer::particles_set_interp_to_end);
ClassDB::bind_method(D_METHOD("particles_set_emitter_velocity", "particles", "velocity"), &RenderingServer::particles_set_emitter_velocity);
ClassDB::bind_method(D_METHOD("particles_set_custom_aabb", "particles", "aabb"), &RenderingServer::particles_set_custom_aabb); ClassDB::bind_method(D_METHOD("particles_set_custom_aabb", "particles", "aabb"), &RenderingServer::particles_set_custom_aabb);
ClassDB::bind_method(D_METHOD("particles_set_speed_scale", "particles", "scale"), &RenderingServer::particles_set_speed_scale); ClassDB::bind_method(D_METHOD("particles_set_speed_scale", "particles", "scale"), &RenderingServer::particles_set_speed_scale);
ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &RenderingServer::particles_set_use_local_coordinates); ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &RenderingServer::particles_set_use_local_coordinates);

View File

@ -660,6 +660,7 @@ public:
virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0; virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0; virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0; virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) = 0;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0; virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0; virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
@ -717,6 +718,8 @@ public:
virtual AABB particles_get_current_aabb(RID p_particles) = 0; virtual AABB particles_get_current_aabb(RID p_particles) = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic. virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic.
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) = 0;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp) = 0;
/* PARTICLES COLLISION API */ /* PARTICLES COLLISION API */