mirror of
https://github.com/godotengine/godot.git
synced 2025-03-07 23:32:58 +08:00
Implemented tools around particles seed randomization.
The purpose of this code is to expose the necessary functions for users and engine devs to develop tooling for properly timing and seeking inside particles. Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro> Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Co-authored-by: Tomasz Chabora <kobewi4e@gmail.com> Co-authored-by: Rémi Verschelde <rverschelde@gmail.com>
This commit is contained in:
parent
bdf625bd54
commit
e9eb0b6082
@ -46,10 +46,20 @@
|
||||
Returns the enabled state of the given particle flag (see [enum ParticleFlags] for options).
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_particles_process">
|
||||
<return type="void" />
|
||||
<param index="0" name="process_time" type="float" />
|
||||
<description>
|
||||
Requests the particles to process for extra process time during a single frame.
|
||||
Useful for particle playback, if used in combination with [member use_fixed_seed] or by calling [method restart] with parameter [code]keep_seed[/code] set to [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="restart">
|
||||
<return type="void" />
|
||||
<param index="0" name="keep_seed" type="bool" default="false" />
|
||||
<description>
|
||||
Restarts the particle emitter.
|
||||
If [param keep_seed] is [code]true[/code], the current random seed will be preserved. Useful for seeking and playback.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_param_curve">
|
||||
@ -263,6 +273,9 @@
|
||||
Each particle's vertical scale will vary along this [Curve]. Should be a unit [Curve].
|
||||
[member split_scale] must be enabled.
|
||||
</member>
|
||||
<member name="seed" type="int" setter="set_seed" getter="get_seed" default="0">
|
||||
Sets the random seed used by the particle system. Only effective if [member use_fixed_seed] is [code]true[/code].
|
||||
</member>
|
||||
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
|
||||
Particle system's running speed scaling ratio. A value of [code]0[/code] can be used to pause the particles.
|
||||
</member>
|
||||
@ -284,6 +297,9 @@
|
||||
<member name="texture" type="Texture2D" setter="set_texture" getter="get_texture">
|
||||
Particle texture. If [code]null[/code], particles will be squares.
|
||||
</member>
|
||||
<member name="use_fixed_seed" type="bool" setter="set_use_fixed_seed" getter="get_use_fixed_seed" default="false">
|
||||
If [code]true[/code], particles will use the same seed for every simulation using the seed defined in [member seed]. This is useful for situations where the visual outcome should be consistent across replays, for example when using Movie Maker mode.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="finished">
|
||||
|
@ -52,10 +52,20 @@
|
||||
Returns the enabled state of the given particle flag (see [enum ParticleFlags] for options).
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_particles_process">
|
||||
<return type="void" />
|
||||
<param index="0" name="process_time" type="float" />
|
||||
<description>
|
||||
Requests the particles to process for extra process time during a single frame.
|
||||
Useful for particle playback, if used in combination with [member use_fixed_seed] or by calling [method restart] with parameter [code]keep_seed[/code] set to [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="restart">
|
||||
<return type="void" />
|
||||
<param index="0" name="keep_seed" type="bool" default="false" />
|
||||
<description>
|
||||
Restarts the particle emitter.
|
||||
If [param keep_seed] is [code]true[/code], the current random seed will be preserved. Useful for seeking and playback.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_param_curve">
|
||||
@ -301,6 +311,9 @@
|
||||
<member name="scale_curve_z" type="Curve" setter="set_scale_curve_z" getter="get_scale_curve_z">
|
||||
Curve for the scale over life, along the z axis.
|
||||
</member>
|
||||
<member name="seed" type="int" setter="set_seed" getter="get_seed" default="0">
|
||||
Sets the random seed used by the particle system. Only effective if [member use_fixed_seed] is [code]true[/code].
|
||||
</member>
|
||||
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
|
||||
Particle system's running speed scaling ratio. A value of [code]0[/code] can be used to pause the particles.
|
||||
</member>
|
||||
@ -319,6 +332,9 @@
|
||||
<member name="tangential_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
|
||||
Minimum tangent acceleration.
|
||||
</member>
|
||||
<member name="use_fixed_seed" type="bool" setter="set_use_fixed_seed" getter="get_use_fixed_seed" default="false">
|
||||
If [code]true[/code], particles will use the same seed for every simulation using the seed defined in [member seed]. This is useful for situations where the visual outcome should be consistent across replays, for example when using Movie Maker mode.
|
||||
</member>
|
||||
<member name="visibility_aabb" type="AABB" setter="set_visibility_aabb" getter="get_visibility_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
|
||||
The [AABB] that determines the node's region which needs to be visible on screen for the particle system to be active.
|
||||
Grow the box if particles suddenly appear/disappear when the node enters/exits the screen. The [AABB] can be grown via code or with the [b]Particles → Generate AABB[/b] editor tool.
|
||||
|
@ -41,11 +41,21 @@
|
||||
[b]Note:[/b] [method emit_particle] is only supported on the Forward+ and Mobile rendering methods, not Compatibility.
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_particles_process">
|
||||
<return type="void" />
|
||||
<param index="0" name="process_time" type="float" />
|
||||
<description>
|
||||
Requests the particles to process for extra process time during a single frame.
|
||||
Useful for particle playback, if used in combination with [member use_fixed_seed] or by calling [method restart] with parameter [code]keep_seed[/code] set to [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="restart">
|
||||
<return type="void" />
|
||||
<param index="0" name="keep_seed" type="bool" default="false" />
|
||||
<description>
|
||||
Restarts the particle emission cycle, clearing existing particles. To avoid particles vanishing from the viewport, wait for the [signal finished] signal before calling.
|
||||
[b]Note:[/b] The [signal finished] signal is only emitted by [member one_shot] emitters.
|
||||
If [param keep_seed] is [code]true[/code], the current random seed will be preserved. Useful for seeking and playback.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
@ -105,6 +115,9 @@
|
||||
<member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0">
|
||||
Emission lifetime randomness ratio.
|
||||
</member>
|
||||
<member name="seed" type="int" setter="set_seed" getter="get_seed" default="0">
|
||||
Sets the random seed used by the particle system. Only effective if [member use_fixed_seed] is [code]true[/code].
|
||||
</member>
|
||||
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
|
||||
Particle system's running speed scaling ratio. A value of [code]0[/code] can be used to pause the particles.
|
||||
</member>
|
||||
@ -129,6 +142,9 @@
|
||||
<member name="trail_sections" type="int" setter="set_trail_sections" getter="get_trail_sections" default="8">
|
||||
The number of sections to use for the particle trail rendering. Higher values can result in smoother trail curves, at the cost of performance due to increased mesh complexity. See also [member trail_section_subdivisions]. Only effective if [member trail_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="use_fixed_seed" type="bool" setter="set_use_fixed_seed" getter="get_use_fixed_seed" default="false">
|
||||
If [code]true[/code], particles will use the same seed for every simulation using the seed defined in [member seed]. This is useful for situations where the visual outcome should be consistent across replays, for example when using Movie Maker mode.
|
||||
</member>
|
||||
<member name="visibility_rect" type="Rect2" setter="set_visibility_rect" getter="get_visibility_rect" default="Rect2(-100, -100, 200, 200)">
|
||||
The [Rect2] that determines the node's region which needs to be visible on screen for the particle system to be active.
|
||||
Grow the rect if particles suddenly appear/disappear when the node enters/exits the screen. The [Rect2] can be grown via code or with the [b]Particles → Generate Visibility Rect[/b] editor tool.
|
||||
|
@ -46,11 +46,21 @@
|
||||
Returns the [Mesh] that is drawn at index [param pass].
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_particles_process">
|
||||
<return type="void" />
|
||||
<param index="0" name="process_time" type="float" />
|
||||
<description>
|
||||
Requests the particles to process for extra process time during a single frame.
|
||||
Useful for particle playback, if used in combination with [member use_fixed_seed] or by calling [method restart] with parameter [code]keep_seed[/code] set to [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="restart">
|
||||
<return type="void" />
|
||||
<param index="0" name="keep_seed" type="bool" default="false" />
|
||||
<description>
|
||||
Restarts the particle emission cycle, clearing existing particles. To avoid particles vanishing from the viewport, wait for the [signal finished] signal before calling.
|
||||
[b]Note:[/b] The [signal finished] signal is only emitted by [member one_shot] emitters.
|
||||
If [param keep_seed] is [code]true[/code], the current random seed will be preserved. Useful for seeking and playback.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_draw_pass_mesh">
|
||||
@ -136,6 +146,9 @@
|
||||
<member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0">
|
||||
Emission randomness ratio.
|
||||
</member>
|
||||
<member name="seed" type="int" setter="set_seed" getter="get_seed" default="0">
|
||||
Sets the random seed used by the particle system. Only effective if [member use_fixed_seed] is [code]true[/code].
|
||||
</member>
|
||||
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
|
||||
Speed scaling ratio. A value of [code]0[/code] can be used to pause the particles.
|
||||
</member>
|
||||
@ -153,6 +166,9 @@
|
||||
</member>
|
||||
<member name="transform_align" type="int" setter="set_transform_align" getter="get_transform_align" enum="GPUParticles3D.TransformAlign" default="0">
|
||||
</member>
|
||||
<member name="use_fixed_seed" type="bool" setter="set_use_fixed_seed" getter="get_use_fixed_seed" default="false">
|
||||
If [code]true[/code], particles will use the same seed for every simulation using the seed defined in [member seed]. This is useful for situations where the visual outcome should be consistent across replays, for example when using Movie Maker mode.
|
||||
</member>
|
||||
<member name="visibility_aabb" type="AABB" setter="set_visibility_aabb" getter="get_visibility_aabb" default="AABB(-4, -4, -4, 8, 8, 8)">
|
||||
The [AABB] that determines the node's region which needs to be visible on screen for the particle system to be active. [member GeometryInstance3D.extra_cull_margin] is added on each of the AABB's axes. Particle collisions and attraction will only occur within this area.
|
||||
Grow the box if particles suddenly appear/disappear when the node enters/exits the screen. The [AABB] can be grown via code or with the [b]Particles → Generate AABB[/b] editor tool.
|
||||
|
@ -2935,6 +2935,13 @@
|
||||
Add particle system to list of particle systems that need to be updated. Update will take place on the next frame, or on the next call to [method instances_cull_aabb], [method instances_cull_convex], or [method instances_cull_ray].
|
||||
</description>
|
||||
</method>
|
||||
<method name="particles_request_process_time">
|
||||
<return type="void" />
|
||||
<param index="0" name="particles" type="RID" />
|
||||
<param index="1" name="time" type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="particles_restart">
|
||||
<return type="void" />
|
||||
<param index="0" name="particles" type="RID" />
|
||||
|
@ -223,6 +223,19 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->pre_process_time = p_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->request_process_time = p_request_process_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_seed(RID p_particles, uint32_t p_seed) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->random_seed = p_seed;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
@ -507,7 +520,6 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
||||
|
||||
if (p_particles->clear) {
|
||||
p_particles->cycle_number = 0;
|
||||
p_particles->random_seed = Math::rand();
|
||||
} else if (new_phase < p_particles->phase) {
|
||||
if (p_particles->one_shot) {
|
||||
p_particles->emitting = false;
|
||||
@ -1136,6 +1148,24 @@ void ParticlesStorage::update_particles() {
|
||||
}
|
||||
}
|
||||
|
||||
if (particles->request_process_time > 0.0) {
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
float tmp_scale = particles->speed_scale;
|
||||
particles->speed_scale = 1.0;
|
||||
double todo = particles->request_process_time;
|
||||
while (todo >= 0) {
|
||||
_particles_process(particles, frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
particles->speed_scale = tmp_scale;
|
||||
particles->request_process_time = 0.0;
|
||||
}
|
||||
|
||||
// Copy particles to instance buffer and pack Color/Custom.
|
||||
// We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
|
||||
if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
|
@ -157,6 +157,7 @@ private:
|
||||
int amount = 0;
|
||||
double lifetime = 1.0;
|
||||
double pre_process_time = 0.0;
|
||||
real_t request_process_time = 0.0;
|
||||
real_t explosiveness = 0.0;
|
||||
real_t randomness = 0.0;
|
||||
bool restart_request = false;
|
||||
@ -246,6 +247,7 @@ private:
|
||||
|
||||
Particles() :
|
||||
update_list(this) {
|
||||
random_seed = Math::rand();
|
||||
}
|
||||
};
|
||||
|
||||
@ -325,6 +327,7 @@ public:
|
||||
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_pre_process_time(RID p_particles, double p_time) override;
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override;
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
|
||||
@ -340,6 +343,7 @@ public:
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
|
||||
|
@ -268,3 +268,13 @@ GH-98441
|
||||
Validate extension JSON: Error: Field 'global_enums/KeyModifierMask/values/KEY_MODIFIER_MASK': value changed value in new API, from 5.32677e+08 to 2130706432.
|
||||
|
||||
Key modifier mask value corrected. API change documented for compatibility.
|
||||
|
||||
|
||||
GH-92089
|
||||
--------
|
||||
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/CPUParticles2D/methods/restart': arguments
|
||||
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/CPUParticles3D/methods/restart': arguments
|
||||
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/GPUParticles2D/methods/restart': arguments
|
||||
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/GPUParticles3D/methods/restart': arguments
|
||||
|
||||
Added an optional keep_seed parameter to restart particles, to avoid modifying the seed to do particle seeking.
|
||||
|
41
scene/2d/cpu_particles_2d.compat.inc
Normal file
41
scene/2d/cpu_particles_2d.compat.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* cpu_particles_2d.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DISABLE_DEPRECATED
|
||||
|
||||
void CPUParticles2D::_restart_bind_compat_92089() {
|
||||
restart(false);
|
||||
}
|
||||
|
||||
void CPUParticles2D::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("restart"), &CPUParticles2D::_restart_bind_compat_92089);
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
@ -29,6 +29,7 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include "cpu_particles_2d.h"
|
||||
#include "cpu_particles_2d.compat.inc"
|
||||
|
||||
#include "scene/2d/gpu_particles_2d.h"
|
||||
#include "scene/resources/atlas_texture.h"
|
||||
@ -261,7 +262,7 @@ PackedStringArray CPUParticles2D::get_configuration_warnings() const {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void CPUParticles2D::restart() {
|
||||
void CPUParticles2D::restart(bool p_keep_seed) {
|
||||
time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
@ -275,6 +276,9 @@ void CPUParticles2D::restart() {
|
||||
w[i].active = false;
|
||||
}
|
||||
}
|
||||
if (!p_keep_seed && !use_fixed_seed) {
|
||||
seed = Math::rand();
|
||||
}
|
||||
|
||||
set_emitting(true);
|
||||
}
|
||||
@ -506,6 +510,30 @@ bool CPUParticles2D::get_split_scale() {
|
||||
return split_scale;
|
||||
}
|
||||
|
||||
void CPUParticles2D::set_use_fixed_seed(bool p_use_fixed_seed) {
|
||||
if (p_use_fixed_seed == use_fixed_seed) {
|
||||
return;
|
||||
}
|
||||
use_fixed_seed = p_use_fixed_seed;
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool CPUParticles2D::get_use_fixed_seed() const {
|
||||
return use_fixed_seed;
|
||||
}
|
||||
|
||||
void CPUParticles2D::set_seed(uint32_t p_seed) {
|
||||
seed = p_seed;
|
||||
}
|
||||
|
||||
uint32_t CPUParticles2D::get_seed() const {
|
||||
return seed;
|
||||
}
|
||||
|
||||
void CPUParticles2D::request_particles_process(real_t p_requested_process_time) {
|
||||
_requested_process_time = p_requested_process_time;
|
||||
}
|
||||
|
||||
void CPUParticles2D::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name == "emitting") {
|
||||
p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE;
|
||||
@ -537,6 +565,10 @@ void CPUParticles2D::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name.begins_with("scale_curve_") && !split_scale) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
|
||||
if (p_property.name == "seed" && !use_fixed_seed) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t idhash(uint32_t x) {
|
||||
@ -579,25 +611,28 @@ void CPUParticles2D::_update_internal() {
|
||||
return;
|
||||
}
|
||||
_set_do_redraw(true);
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
|
||||
double todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
double todo = _requested_process_time;
|
||||
_requested_process_time = 0;
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
todo += pre_process_time;
|
||||
}
|
||||
real_t tmp_speed = speed_scale;
|
||||
speed_scale = 1.0;
|
||||
while (todo > 0) {
|
||||
_particles_process(frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
speed_scale = tmp_speed;
|
||||
|
||||
todo = 0.0;
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
double frame_time = 1.0 / fixed_fps;
|
||||
double decr = frame_time;
|
||||
|
||||
double ldelta = delta;
|
||||
@ -606,13 +641,12 @@ void CPUParticles2D::_update_internal() {
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
double todo = frame_remainder + ldelta;
|
||||
todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
todo -= decr;
|
||||
}
|
||||
|
||||
frame_remainder = todo;
|
||||
|
||||
} else {
|
||||
@ -667,13 +701,13 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
double restart_phase = double(i) / double(pcount);
|
||||
|
||||
if (randomness_ratio > 0.0) {
|
||||
uint32_t seed = cycle;
|
||||
uint32_t _seed = cycle;
|
||||
if (restart_phase >= system_phase) {
|
||||
seed -= uint32_t(1);
|
||||
_seed -= uint32_t(1);
|
||||
}
|
||||
seed *= uint32_t(pcount);
|
||||
seed += uint32_t(i);
|
||||
double random = double(idhash(seed) % uint32_t(65536)) / 65536.0;
|
||||
_seed *= uint32_t(pcount);
|
||||
_seed += uint32_t(i);
|
||||
double random = double(idhash(_seed) % uint32_t(65536)) / 65536.0;
|
||||
restart_phase += randomness_ratio * random * 1.0 / double(pcount);
|
||||
}
|
||||
|
||||
@ -734,22 +768,23 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv);
|
||||
}
|
||||
|
||||
p.seed = Math::rand();
|
||||
p.seed = seed + uint32_t(i) + i + cycle;
|
||||
uint32_t _seed = p.seed;
|
||||
|
||||
p.angle_rand = Math::randf();
|
||||
p.scale_rand = Math::randf();
|
||||
p.hue_rot_rand = Math::randf();
|
||||
p.anim_offset_rand = Math::randf();
|
||||
p.angle_rand = rand_from_seed(_seed);
|
||||
p.scale_rand = rand_from_seed(_seed);
|
||||
p.hue_rot_rand = rand_from_seed(_seed);
|
||||
p.anim_offset_rand = rand_from_seed(_seed);
|
||||
|
||||
if (color_initial_ramp.is_valid()) {
|
||||
p.start_color_rand = color_initial_ramp->get_color_at_offset(Math::randf());
|
||||
p.start_color_rand = color_initial_ramp->get_color_at_offset(rand_from_seed(_seed));
|
||||
} else {
|
||||
p.start_color_rand = Color(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
real_t angle1_rad = direction.angle() + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread);
|
||||
real_t angle1_rad = direction.angle() + Math::deg_to_rad((rand_from_seed(_seed) * 2.0 - 1.0) * spread);
|
||||
Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad));
|
||||
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf());
|
||||
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)rand_from_seed(_seed));
|
||||
|
||||
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
|
||||
p.rotation = Math::deg_to_rad(base_angle);
|
||||
@ -757,7 +792,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
p.custom[0] = 0.0; // unused
|
||||
p.custom[1] = 0.0; // phase [0..1]
|
||||
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand);
|
||||
p.custom[3] = (1.0 - Math::randf() * lifetime_randomness);
|
||||
p.custom[3] = (1.0 - rand_from_seed(_seed) * lifetime_randomness);
|
||||
p.transform = Transform2D();
|
||||
p.time = 0;
|
||||
p.lifetime = lifetime * p.custom[3];
|
||||
@ -768,17 +803,17 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
//do none
|
||||
} break;
|
||||
case EMISSION_SHAPE_SPHERE: {
|
||||
real_t t = Math_TAU * Math::randf();
|
||||
real_t radius = emission_sphere_radius * Math::randf();
|
||||
real_t t = Math_TAU * rand_from_seed(_seed);
|
||||
real_t radius = emission_sphere_radius * rand_from_seed(_seed);
|
||||
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
|
||||
} break;
|
||||
case EMISSION_SHAPE_SPHERE_SURFACE: {
|
||||
real_t s = Math::randf(), t = Math_TAU * Math::randf();
|
||||
real_t s = rand_from_seed(_seed), t = Math_TAU * rand_from_seed(_seed);
|
||||
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
|
||||
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
|
||||
} break;
|
||||
case EMISSION_SHAPE_RECTANGLE: {
|
||||
p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_rect_extents;
|
||||
p.transform[2] = Vector2(rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0) * emission_rect_extents;
|
||||
} break;
|
||||
case EMISSION_SHAPE_POINTS:
|
||||
case EMISSION_SHAPE_DIRECTED_POINTS: {
|
||||
@ -819,8 +854,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
p.active = false;
|
||||
tv = 1.0;
|
||||
} else {
|
||||
uint32_t alt_seed = p.seed;
|
||||
|
||||
uint32_t _seed = p.seed;
|
||||
p.time += local_delta;
|
||||
p.custom[1] = p.time / lifetime;
|
||||
tv = p.time / p.lifetime;
|
||||
@ -878,18 +912,18 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
Vector2 pos = p.transform[2];
|
||||
|
||||
//apply linear acceleration
|
||||
force += p.velocity.length() > 0.0 ? p.velocity.normalized() * tex_linear_accel * Math::lerp(parameters_min[PARAM_LINEAR_ACCEL], parameters_max[PARAM_LINEAR_ACCEL], rand_from_seed(alt_seed)) : Vector2();
|
||||
force += p.velocity.length() > 0.0 ? p.velocity.normalized() * tex_linear_accel * Math::lerp(parameters_min[PARAM_LINEAR_ACCEL], parameters_max[PARAM_LINEAR_ACCEL], rand_from_seed(_seed)) : Vector2();
|
||||
//apply radial acceleration
|
||||
Vector2 org = emission_xform[2];
|
||||
Vector2 diff = pos - org;
|
||||
force += diff.length() > 0.0 ? diff.normalized() * (tex_radial_accel)*Math::lerp(parameters_min[PARAM_RADIAL_ACCEL], parameters_max[PARAM_RADIAL_ACCEL], rand_from_seed(alt_seed)) : Vector2();
|
||||
force += diff.length() > 0.0 ? diff.normalized() * (tex_radial_accel)*Math::lerp(parameters_min[PARAM_RADIAL_ACCEL], parameters_max[PARAM_RADIAL_ACCEL], rand_from_seed(_seed)) : Vector2();
|
||||
//apply tangential acceleration;
|
||||
Vector2 yx = Vector2(diff.y, diff.x);
|
||||
force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * (tex_tangential_accel * Math::lerp(parameters_min[PARAM_TANGENTIAL_ACCEL], parameters_max[PARAM_TANGENTIAL_ACCEL], rand_from_seed(alt_seed))) : Vector2();
|
||||
force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * (tex_tangential_accel * Math::lerp(parameters_min[PARAM_TANGENTIAL_ACCEL], parameters_max[PARAM_TANGENTIAL_ACCEL], rand_from_seed(_seed))) : Vector2();
|
||||
//apply attractor forces
|
||||
p.velocity += force * local_delta;
|
||||
//orbit velocity
|
||||
real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed));
|
||||
real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(_seed));
|
||||
if (orbit_amount != 0.0) {
|
||||
real_t ang = orbit_amount * local_delta * Math_TAU;
|
||||
// Not sure why the ParticleProcessMaterial code uses a clockwise rotation matrix,
|
||||
@ -904,7 +938,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
|
||||
if (parameters_max[PARAM_DAMPING] + tex_damping > 0.0) {
|
||||
real_t v = p.velocity.length();
|
||||
real_t damp = tex_damping * Math::lerp(parameters_min[PARAM_DAMPING], parameters_max[PARAM_DAMPING], rand_from_seed(alt_seed));
|
||||
real_t damp = tex_damping * Math::lerp(parameters_min[PARAM_DAMPING], parameters_max[PARAM_DAMPING], rand_from_seed(_seed));
|
||||
v -= damp * local_delta;
|
||||
if (v < 0.0) {
|
||||
p.velocity = Vector2();
|
||||
@ -913,9 +947,9 @@ void CPUParticles2D::_particles_process(double p_delta) {
|
||||
}
|
||||
}
|
||||
real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
|
||||
base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed));
|
||||
base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(_seed));
|
||||
p.rotation = Math::deg_to_rad(base_angle); //angle
|
||||
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed));
|
||||
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(_seed));
|
||||
}
|
||||
//apply color
|
||||
//apply hue rotation
|
||||
@ -1267,6 +1301,7 @@ void CPUParticles2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles2D::set_fixed_fps);
|
||||
ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles2D::set_fractional_delta);
|
||||
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &CPUParticles2D::set_speed_scale);
|
||||
ClassDB::bind_method(D_METHOD("request_particles_process", "process_time"), &CPUParticles2D::request_particles_process);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles2D::is_emitting);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles2D::get_amount);
|
||||
@ -1280,6 +1315,11 @@ void CPUParticles2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles2D::get_fixed_fps);
|
||||
ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles2D::get_fractional_delta);
|
||||
ClassDB::bind_method(D_METHOD("get_speed_scale"), &CPUParticles2D::get_speed_scale);
|
||||
ClassDB::bind_method(D_METHOD("set_use_fixed_seed", "use_fixed_seed"), &CPUParticles2D::set_use_fixed_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_use_fixed_seed"), &CPUParticles2D::get_use_fixed_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &CPUParticles2D::set_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_seed"), &CPUParticles2D::get_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &CPUParticles2D::set_draw_order);
|
||||
|
||||
@ -1288,7 +1328,7 @@ void CPUParticles2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_texture", "texture"), &CPUParticles2D::set_texture);
|
||||
ClassDB::bind_method(D_METHOD("get_texture"), &CPUParticles2D::get_texture);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("restart"), &CPUParticles2D::restart);
|
||||
ClassDB::bind_method(D_METHOD("restart", "keep_seed"), &CPUParticles2D::restart, DEFVAL(false));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); // FIXME: Evaluate support for `exp` in integer properties, or remove this.
|
||||
@ -1299,6 +1339,8 @@ void CPUParticles2D::_bind_methods() {
|
||||
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, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_fixed_seed"), "set_use_fixed_seed", "get_use_fixed_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed", PROPERTY_HINT_RANGE, "0," + itos(UINT32_MAX) + ",1"), "set_seed", "get_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
|
||||
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, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
||||
|
@ -133,6 +133,7 @@ private:
|
||||
|
||||
double lifetime = 1.0;
|
||||
double pre_process_time = 0.0;
|
||||
double _requested_process_time = 0.0;
|
||||
real_t explosiveness_ratio = 0.0;
|
||||
real_t randomness_ratio = 0.0;
|
||||
double lifetime_randomness = 0.0;
|
||||
@ -140,6 +141,8 @@ private:
|
||||
bool local_coords = false;
|
||||
int fixed_fps = 0;
|
||||
bool fractional_delta = true;
|
||||
uint32_t seed = 0;
|
||||
bool use_fixed_seed = false;
|
||||
|
||||
Transform2D inv_emission_transform;
|
||||
|
||||
@ -195,6 +198,11 @@ protected:
|
||||
void _notification(int p_what);
|
||||
void _validate_property(PropertyInfo &p_property) const;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _restart_bind_compat_92089();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
public:
|
||||
void set_emitting(bool p_emitting);
|
||||
void set_amount(int p_amount);
|
||||
@ -230,6 +238,14 @@ public:
|
||||
void set_texture(const Ref<Texture2D> &p_texture);
|
||||
Ref<Texture2D> get_texture() const;
|
||||
|
||||
void set_use_fixed_seed(bool p_use_fixed_seed);
|
||||
bool get_use_fixed_seed() const;
|
||||
|
||||
void set_seed(uint32_t p_seed);
|
||||
uint32_t get_seed() const;
|
||||
|
||||
void request_particles_process(real_t p_requested_process_time);
|
||||
|
||||
///////////////////
|
||||
|
||||
void set_direction(Vector2 p_direction);
|
||||
@ -284,7 +300,7 @@ public:
|
||||
|
||||
PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
void restart();
|
||||
void restart(bool p_keep_seed = false);
|
||||
|
||||
void convert_from_particles(Node *p_particles);
|
||||
|
||||
|
41
scene/2d/gpu_particles_2d.compat.inc
Normal file
41
scene/2d/gpu_particles_2d.compat.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* gpu_particles_2d.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DISABLE_DEPRECATED
|
||||
|
||||
void GPUParticles2D::_restart_bind_compat_92089() {
|
||||
restart(false);
|
||||
}
|
||||
|
||||
void GPUParticles2D::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("restart"), &GPUParticles2D::_restart_bind_compat_92089);
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
@ -29,6 +29,7 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include "gpu_particles_2d.h"
|
||||
#include "gpu_particles_2d.compat.inc"
|
||||
|
||||
#include "scene/2d/cpu_particles_2d.h"
|
||||
#include "scene/resources/atlas_texture.h"
|
||||
@ -323,6 +324,31 @@ float GPUParticles2D::get_interp_to_end() const {
|
||||
return interp_to_end_factor;
|
||||
}
|
||||
|
||||
void GPUParticles2D::set_use_fixed_seed(bool p_use_fixed_seed) {
|
||||
if (p_use_fixed_seed == use_fixed_seed) {
|
||||
return;
|
||||
}
|
||||
use_fixed_seed = p_use_fixed_seed;
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool GPUParticles2D::get_use_fixed_seed() const {
|
||||
return use_fixed_seed;
|
||||
}
|
||||
|
||||
void GPUParticles2D::set_seed(uint32_t p_seed) {
|
||||
seed = p_seed;
|
||||
RS::get_singleton()->particles_set_seed(particles, p_seed);
|
||||
}
|
||||
|
||||
uint32_t GPUParticles2D::get_seed() const {
|
||||
return seed;
|
||||
}
|
||||
|
||||
void GPUParticles2D::request_particles_process(real_t p_requested_process_time) {
|
||||
RS::get_singleton()->particles_request_process_time(particles, p_requested_process_time);
|
||||
}
|
||||
|
||||
PackedStringArray GPUParticles2D::get_configuration_warnings() const {
|
||||
PackedStringArray warnings = Node2D::get_configuration_warnings();
|
||||
|
||||
@ -381,6 +407,9 @@ Ref<Texture2D> GPUParticles2D::get_texture() const {
|
||||
}
|
||||
|
||||
void GPUParticles2D::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name == "seed" && !use_fixed_seed) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
if (p_property.name == "emitting") {
|
||||
p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE;
|
||||
}
|
||||
@ -440,7 +469,10 @@ float GPUParticles2D::get_amount_ratio() const {
|
||||
return amount_ratio;
|
||||
}
|
||||
|
||||
void GPUParticles2D::restart() {
|
||||
void GPUParticles2D::restart(bool p_keep_seed) {
|
||||
if (!p_keep_seed && !use_fixed_seed) {
|
||||
set_seed(Math::rand());
|
||||
}
|
||||
RS::get_singleton()->particles_restart(particles);
|
||||
RS::get_singleton()->particles_set_emitting(particles, true);
|
||||
|
||||
@ -767,6 +799,8 @@ void GPUParticles2D::_bind_methods() {
|
||||
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("request_particles_process", "process_time"), &GPUParticles2D::request_particles_process);
|
||||
|
||||
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_lifetime"), &GPUParticles2D::get_lifetime);
|
||||
@ -792,7 +826,7 @@ void GPUParticles2D::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("capture_rect"), &GPUParticles2D::capture_rect);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles2D::restart);
|
||||
ClassDB::bind_method(D_METHOD("restart", "keep_seed"), &GPUParticles2D::restart, DEFVAL(false));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles2D::set_sub_emitter);
|
||||
ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles2D::get_sub_emitter);
|
||||
@ -816,6 +850,12 @@ void GPUParticles2D::_bind_methods() {
|
||||
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);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_fixed_seed", "use_fixed_seed"), &GPUParticles2D::set_use_fixed_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_use_fixed_seed"), &GPUParticles2D::get_use_fixed_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &GPUParticles2D::set_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_seed"), &GPUParticles2D::get_seed);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("finished"));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting");
|
||||
@ -831,6 +871,8 @@ void GPUParticles2D::_bind_methods() {
|
||||
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, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_fixed_seed", PROPERTY_HINT_ENUM), "set_use_fixed_seed", "get_use_fixed_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed", PROPERTY_HINT_RANGE, "0," + itos(UINT32_MAX) + ",1"), "set_seed", "get_seed");
|
||||
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, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
||||
|
@ -66,6 +66,8 @@ private:
|
||||
float interp_to_end_factor = 0;
|
||||
Vector3 previous_velocity;
|
||||
Vector2 previous_position;
|
||||
uint32_t seed = 0;
|
||||
bool use_fixed_seed = false;
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool show_visibility_rect = false;
|
||||
#endif
|
||||
@ -101,6 +103,11 @@ protected:
|
||||
void _notification(int p_what);
|
||||
void _update_collision_size();
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _restart_bind_compat_92089();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
public:
|
||||
void set_emitting(bool p_emitting);
|
||||
void set_amount(int p_amount);
|
||||
@ -119,6 +126,7 @@ public:
|
||||
void set_trail_sections(int p_sections);
|
||||
void set_trail_section_subdivisions(int p_subdivisions);
|
||||
void set_interp_to_end(float p_interp);
|
||||
void request_particles_process(real_t p_requested_process_time);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void set_show_visibility_rect(bool p_show_visibility_rect);
|
||||
@ -166,6 +174,12 @@ public:
|
||||
void set_sub_emitter(const NodePath &p_path);
|
||||
NodePath get_sub_emitter() const;
|
||||
|
||||
void set_use_fixed_seed(bool p_use_fixed_seed);
|
||||
bool get_use_fixed_seed() const;
|
||||
|
||||
void set_seed(uint32_t p_seed);
|
||||
uint32_t get_seed() const;
|
||||
|
||||
enum EmitFlags {
|
||||
EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION,
|
||||
EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE,
|
||||
@ -176,7 +190,7 @@ public:
|
||||
|
||||
void emit_particle(const Transform2D &p_transform, const Vector2 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
|
||||
|
||||
void restart();
|
||||
void restart(bool p_keep_seed = false);
|
||||
Rect2 capture_rect() const;
|
||||
void convert_from_particles(Node *p_particles);
|
||||
|
||||
|
41
scene/3d/cpu_particles_3d.compat.inc
Normal file
41
scene/3d/cpu_particles_3d.compat.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* cpu_particles_3d.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DISABLE_DEPRECATED
|
||||
|
||||
void CPUParticles3D::_restart_bind_compat_92089() {
|
||||
restart(false);
|
||||
}
|
||||
|
||||
void CPUParticles3D::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("restart"), &CPUParticles3D::_restart_bind_compat_92089);
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
@ -29,6 +29,7 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include "cpu_particles_3d.h"
|
||||
#include "cpu_particles_3d.compat.inc"
|
||||
|
||||
#include "scene/3d/camera_3d.h"
|
||||
#include "scene/3d/gpu_particles_3d.h"
|
||||
@ -231,7 +232,7 @@ PackedStringArray CPUParticles3D::get_configuration_warnings() const {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void CPUParticles3D::restart() {
|
||||
void CPUParticles3D::restart(bool p_keep_seed) {
|
||||
time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
@ -245,6 +246,9 @@ void CPUParticles3D::restart() {
|
||||
w[i].active = false;
|
||||
}
|
||||
}
|
||||
if (!p_keep_seed && !use_fixed_seed) {
|
||||
seed = Math::rand();
|
||||
}
|
||||
|
||||
set_emitting(true);
|
||||
}
|
||||
@ -549,6 +553,30 @@ AABB CPUParticles3D::capture_aabb() const {
|
||||
return RS::get_singleton()->multimesh_get_aabb(multimesh);
|
||||
}
|
||||
|
||||
void CPUParticles3D::set_use_fixed_seed(bool p_use_fixed_seed) {
|
||||
if (p_use_fixed_seed == use_fixed_seed) {
|
||||
return;
|
||||
}
|
||||
use_fixed_seed = p_use_fixed_seed;
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool CPUParticles3D::get_use_fixed_seed() const {
|
||||
return use_fixed_seed;
|
||||
}
|
||||
|
||||
void CPUParticles3D::set_seed(uint32_t p_seed) {
|
||||
seed = p_seed;
|
||||
}
|
||||
|
||||
uint32_t CPUParticles3D::get_seed() const {
|
||||
return seed;
|
||||
}
|
||||
|
||||
void CPUParticles3D::request_particles_process(real_t p_requested_process_time) {
|
||||
_requested_process_time = p_requested_process_time;
|
||||
}
|
||||
|
||||
void CPUParticles3D::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name == "emitting") {
|
||||
p_property.hint = one_shot ? PROPERTY_HINT_ONESHOT : PROPERTY_HINT_NONE;
|
||||
@ -581,6 +609,10 @@ void CPUParticles3D::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name.begins_with("scale_curve_") && !split_scale) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
|
||||
if (p_property.name == "seed" && !use_fixed_seed) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t idhash(uint32_t x) {
|
||||
@ -626,25 +658,27 @@ void CPUParticles3D::_update_internal() {
|
||||
|
||||
bool processed = false;
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
|
||||
double todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
processed = true;
|
||||
todo -= frame_time;
|
||||
}
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
double todo = _requested_process_time;
|
||||
_requested_process_time = 0.;
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
todo += pre_process_time;
|
||||
}
|
||||
real_t tmp_speed = speed_scale;
|
||||
speed_scale = 1.0;
|
||||
while (todo > 0) {
|
||||
_particles_process(frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
speed_scale = tmp_speed;
|
||||
todo = 0.0;
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
double frame_time = 1.0 / fixed_fps;
|
||||
double decr = frame_time;
|
||||
|
||||
double ldelta = delta;
|
||||
@ -653,7 +687,7 @@ void CPUParticles3D::_update_internal() {
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
double todo = frame_remainder + ldelta;
|
||||
todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
@ -717,13 +751,13 @@ void CPUParticles3D::_particles_process(double p_delta) {
|
||||
double restart_phase = double(i) / double(pcount);
|
||||
|
||||
if (randomness_ratio > 0.0) {
|
||||
uint32_t seed = cycle;
|
||||
uint32_t _seed = cycle;
|
||||
if (restart_phase >= system_phase) {
|
||||
seed -= uint32_t(1);
|
||||
_seed -= uint32_t(1);
|
||||
}
|
||||
seed *= uint32_t(pcount);
|
||||
seed += uint32_t(i);
|
||||
double random = double(idhash(seed) % uint32_t(65536)) / 65536.0;
|
||||
_seed *= uint32_t(pcount);
|
||||
_seed += uint32_t(i);
|
||||
double random = double(idhash(_seed) % uint32_t(65536)) / 65536.0;
|
||||
restart_phase += randomness_ratio * random * 1.0 / double(pcount);
|
||||
}
|
||||
|
||||
@ -784,27 +818,27 @@ void CPUParticles3D::_particles_process(double p_delta) {
|
||||
tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv);
|
||||
}
|
||||
|
||||
p.seed = Math::rand();
|
||||
|
||||
p.angle_rand = Math::randf();
|
||||
p.scale_rand = Math::randf();
|
||||
p.hue_rot_rand = Math::randf();
|
||||
p.anim_offset_rand = Math::randf();
|
||||
p.seed = seed;
|
||||
uint32_t _seed = seed + uint32_t(1) + i + cycle;
|
||||
p.angle_rand = rand_from_seed(_seed);
|
||||
p.scale_rand = rand_from_seed(_seed);
|
||||
p.hue_rot_rand = rand_from_seed(_seed);
|
||||
p.anim_offset_rand = rand_from_seed(_seed);
|
||||
|
||||
if (color_initial_ramp.is_valid()) {
|
||||
p.start_color_rand = color_initial_ramp->get_color_at_offset(Math::randf());
|
||||
p.start_color_rand = color_initial_ramp->get_color_at_offset(rand_from_seed(_seed));
|
||||
} else {
|
||||
p.start_color_rand = Color(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
||||
real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread);
|
||||
real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((rand_from_seed(_seed) * 2.0 - 1.0) * spread);
|
||||
Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0);
|
||||
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf());
|
||||
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rand_from_seed(_seed));
|
||||
} else {
|
||||
//initiate velocity spread in 3D
|
||||
real_t angle1_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread);
|
||||
real_t angle2_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread);
|
||||
real_t angle1_rad = Math::deg_to_rad((rand_from_seed(_seed) * (real_t)2.0 - (real_t)1.0) * spread);
|
||||
real_t angle2_rad = Math::deg_to_rad((rand_from_seed(_seed) * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread);
|
||||
|
||||
Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad));
|
||||
Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad));
|
||||
@ -824,14 +858,14 @@ void CPUParticles3D::_particles_process(double p_delta) {
|
||||
binormal.normalize();
|
||||
Vector3 normal = binormal.cross(direction_nrm);
|
||||
spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;
|
||||
p.velocity = spread_direction * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf());
|
||||
p.velocity = spread_direction * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rand_from_seed(_seed));
|
||||
}
|
||||
|
||||
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
|
||||
p.custom[0] = Math::deg_to_rad(base_angle); //angle
|
||||
p.custom[1] = 0.0; //phase
|
||||
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand); //animation offset (0-1)
|
||||
p.custom[3] = (1.0 - Math::randf() * lifetime_randomness);
|
||||
p.custom[3] = (1.0 - rand_from_seed(_seed) * lifetime_randomness);
|
||||
p.transform = Transform3D();
|
||||
p.time = 0;
|
||||
p.lifetime = lifetime * p.custom[3];
|
||||
@ -842,20 +876,20 @@ void CPUParticles3D::_particles_process(double p_delta) {
|
||||
//do none
|
||||
} break;
|
||||
case EMISSION_SHAPE_SPHERE: {
|
||||
real_t s = 2.0 * Math::randf() - 1.0;
|
||||
real_t t = Math_TAU * Math::randf();
|
||||
real_t x = Math::randf();
|
||||
real_t s = 2.0 * rand_from_seed(_seed) - 1.0;
|
||||
real_t t = Math_TAU * rand_from_seed(_seed);
|
||||
real_t x = rand_from_seed(_seed);
|
||||
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
|
||||
p.transform.origin = Vector3(0, 0, 0).lerp(Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s), x);
|
||||
} break;
|
||||
case EMISSION_SHAPE_SPHERE_SURFACE: {
|
||||
real_t s = 2.0 * Math::randf() - 1.0;
|
||||
real_t t = Math_TAU * Math::randf();
|
||||
real_t s = 2.0 * rand_from_seed(_seed) - 1.0;
|
||||
real_t t = Math_TAU * rand_from_seed(_seed);
|
||||
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
|
||||
p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s);
|
||||
} break;
|
||||
case EMISSION_SHAPE_BOX: {
|
||||
p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_box_extents;
|
||||
p.transform.origin = Vector3(rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0) * emission_box_extents;
|
||||
} break;
|
||||
case EMISSION_SHAPE_POINTS:
|
||||
case EMISSION_SHAPE_DIRECTED_POINTS: {
|
||||
@ -899,11 +933,11 @@ void CPUParticles3D::_particles_process(double p_delta) {
|
||||
case EMISSION_SHAPE_RING: {
|
||||
real_t radius_clamped = MAX(0.001, emission_ring_radius);
|
||||
real_t top_radius = MAX(radius_clamped - Math::tan(Math::deg_to_rad(90.0 - emission_ring_cone_angle)) * emission_ring_height, 0.0);
|
||||
real_t y_pos = Math::randf();
|
||||
real_t y_pos = rand_from_seed(_seed);
|
||||
real_t skew = MAX(MIN(radius_clamped, top_radius) / MAX(radius_clamped, top_radius), 0.5);
|
||||
y_pos = radius_clamped < top_radius ? Math::pow(y_pos, skew) : 1.0 - Math::pow(y_pos, skew);
|
||||
real_t ring_random_angle = Math::randf() * Math_TAU;
|
||||
real_t ring_random_radius = Math::sqrt(Math::randf() * (radius_clamped * radius_clamped - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);
|
||||
real_t ring_random_angle = rand_from_seed(_seed) * Math_TAU;
|
||||
real_t ring_random_radius = Math::sqrt(rand_from_seed(_seed) * (radius_clamped * radius_clamped - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);
|
||||
ring_random_radius = Math::lerp(ring_random_radius, ring_random_radius * (top_radius / radius_clamped), y_pos);
|
||||
Vector3 axis = emission_ring_axis == Vector3(0.0, 0.0, 0.0) ? Vector3(0.0, 0.0, 1.0) : emission_ring_axis.normalized();
|
||||
Vector3 ortho_axis;
|
||||
@ -1489,7 +1523,14 @@ void CPUParticles3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CPUParticles3D::set_mesh);
|
||||
ClassDB::bind_method(D_METHOD("get_mesh"), &CPUParticles3D::get_mesh);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart);
|
||||
ClassDB::bind_method(D_METHOD("set_use_fixed_seed", "use_fixed_seed"), &CPUParticles3D::set_use_fixed_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_use_fixed_seed"), &CPUParticles3D::get_use_fixed_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &CPUParticles3D::set_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_seed"), &CPUParticles3D::get_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("restart", "keep_seed"), &CPUParticles3D::restart, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("request_particles_process", "process_time"), &CPUParticles3D::request_particles_process);
|
||||
ClassDB::bind_method(D_METHOD("capture_aabb"), &CPUParticles3D::capture_aabb);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting");
|
||||
@ -1498,9 +1539,12 @@ void CPUParticles3D::_bind_methods() {
|
||||
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::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,10.0,0.01,or_greater,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, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_fixed_seed"), "set_use_fixed_seed", "get_use_fixed_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed", PROPERTY_HINT_RANGE, "0," + itos(UINT32_MAX) + ",1"), "set_seed", "get_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
|
||||
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, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
||||
|
@ -134,6 +134,7 @@ private:
|
||||
|
||||
double lifetime = 1.0;
|
||||
double pre_process_time = 0.0;
|
||||
double _requested_process_time = 0.0;
|
||||
real_t explosiveness_ratio = 0.0;
|
||||
real_t randomness_ratio = 0.0;
|
||||
double lifetime_randomness = 0.0;
|
||||
@ -142,6 +143,8 @@ private:
|
||||
bool local_coords = false;
|
||||
int fixed_fps = 0;
|
||||
bool fractional_delta = true;
|
||||
uint32_t seed = 0;
|
||||
bool use_fixed_seed = false;
|
||||
|
||||
Transform3D inv_emission_transform;
|
||||
|
||||
@ -202,6 +205,11 @@ protected:
|
||||
void _notification(int p_what);
|
||||
void _validate_property(PropertyInfo &p_property) const;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _restart_bind_compat_92089();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
public:
|
||||
AABB get_aabb() const override;
|
||||
|
||||
@ -241,6 +249,14 @@ public:
|
||||
void set_mesh(const Ref<Mesh> &p_mesh);
|
||||
Ref<Mesh> get_mesh() const;
|
||||
|
||||
void set_use_fixed_seed(bool p_use_fixed_seed = false);
|
||||
bool get_use_fixed_seed() const;
|
||||
|
||||
void set_seed(uint32_t p_seed);
|
||||
uint32_t get_seed() const;
|
||||
|
||||
void request_particles_process(real_t p_requested_process_time);
|
||||
|
||||
///////////////////
|
||||
|
||||
void set_direction(Vector3 p_direction);
|
||||
@ -310,7 +326,7 @@ public:
|
||||
|
||||
PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
void restart();
|
||||
void restart(bool p_keep_seed = false);
|
||||
|
||||
void convert_from_particles(Node *p_particles);
|
||||
|
||||
|
41
scene/3d/gpu_particles_3d.compat.inc
Normal file
41
scene/3d/gpu_particles_3d.compat.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* gpu_particles_3d.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DISABLE_DEPRECATED
|
||||
|
||||
void GPUParticles3D::_restart_bind_compat_92089() {
|
||||
restart(false);
|
||||
}
|
||||
|
||||
void GPUParticles3D::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("restart"), &GPUParticles3D::_restart_bind_compat_92089);
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
@ -29,6 +29,7 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include "gpu_particles_3d.h"
|
||||
#include "gpu_particles_3d.compat.inc"
|
||||
|
||||
#include "scene/3d/cpu_particles_3d.h"
|
||||
#include "scene/resources/curve_texture.h"
|
||||
@ -91,11 +92,32 @@ void GPUParticles3D::set_one_shot(bool p_one_shot) {
|
||||
|
||||
if (is_emitting()) {
|
||||
if (!one_shot) {
|
||||
RenderingServer::get_singleton()->particles_restart(particles);
|
||||
restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_use_fixed_seed(bool p_use_fixed_seed) {
|
||||
if (p_use_fixed_seed == use_fixed_seed) {
|
||||
return;
|
||||
}
|
||||
use_fixed_seed = p_use_fixed_seed;
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool GPUParticles3D::get_use_fixed_seed() const {
|
||||
return use_fixed_seed;
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_seed(uint32_t p_seed) {
|
||||
seed = p_seed;
|
||||
RS::get_singleton()->particles_set_seed(particles, p_seed);
|
||||
}
|
||||
|
||||
uint32_t GPUParticles3D::get_seed() const {
|
||||
return seed;
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_pre_process_time(double p_time) {
|
||||
pre_process_time = p_time;
|
||||
RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time);
|
||||
@ -397,7 +419,10 @@ PackedStringArray GPUParticles3D::get_configuration_warnings() const {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void GPUParticles3D::restart() {
|
||||
void GPUParticles3D::restart(bool p_keep_seed) {
|
||||
if (!p_keep_seed && !use_fixed_seed) {
|
||||
set_seed(Math::rand());
|
||||
}
|
||||
RenderingServer::get_singleton()->particles_restart(particles);
|
||||
RenderingServer::get_singleton()->particles_set_emitting(particles, true);
|
||||
|
||||
@ -426,6 +451,13 @@ void GPUParticles3D::_validate_property(PropertyInfo &p_property) const {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (p_property.name == "seed" && !use_fixed_seed) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUParticles3D::request_particles_process(real_t p_requested_process_time) {
|
||||
RS::get_singleton()->particles_request_process_time(particles, p_requested_process_time);
|
||||
}
|
||||
|
||||
void GPUParticles3D::emit_particle(const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
|
||||
@ -724,6 +756,12 @@ void GPUParticles3D::_bind_methods() {
|
||||
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_use_fixed_seed", "use_fixed_seed"), &GPUParticles3D::set_use_fixed_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_use_fixed_seed"), &GPUParticles3D::get_use_fixed_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &GPUParticles3D::set_seed);
|
||||
ClassDB::bind_method(D_METHOD("get_seed"), &GPUParticles3D::get_seed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_draw_order"), &GPUParticles3D::get_draw_order);
|
||||
@ -737,7 +775,7 @@ void GPUParticles3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_skin", "skin"), &GPUParticles3D::set_skin);
|
||||
ClassDB::bind_method(D_METHOD("get_skin"), &GPUParticles3D::get_skin);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart);
|
||||
ClassDB::bind_method(D_METHOD("restart", "keep_seed"), &GPUParticles3D::restart, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter);
|
||||
@ -759,6 +797,8 @@ void GPUParticles3D::_bind_methods() {
|
||||
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);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("request_particles_process", "process_time"), &GPUParticles3D::request_particles_process);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("finished"));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting");
|
||||
@ -774,9 +814,12 @@ void GPUParticles3D::_bind_methods() {
|
||||
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, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_fixed_seed"), "set_use_fixed_seed", "get_use_fixed_seed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed", PROPERTY_HINT_RANGE, "0," + itos(UINT32_MAX) + ",1"), "set_seed", "get_seed");
|
||||
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, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
||||
|
||||
ADD_GROUP("Collision", "collision_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater,suffix:m"), "set_collision_base_size", "get_collision_base_size");
|
||||
ADD_GROUP("Drawing", "");
|
||||
@ -839,6 +882,8 @@ GPUParticles3D::GPUParticles3D() {
|
||||
set_speed_scale(1);
|
||||
set_collision_base_size(collision_base_size);
|
||||
set_transform_align(TRANSFORM_ALIGN_DISABLED);
|
||||
set_use_fixed_seed(false);
|
||||
set_seed(0);
|
||||
}
|
||||
|
||||
GPUParticles3D::~GPUParticles3D() {
|
||||
|
@ -78,6 +78,8 @@ private:
|
||||
bool interpolate = true;
|
||||
NodePath sub_emitter;
|
||||
real_t collision_base_size = 0.01;
|
||||
uint32_t seed = 0;
|
||||
bool use_fixed_seed = false;
|
||||
|
||||
bool trail_enabled = false;
|
||||
double trail_lifetime = 0.3;
|
||||
@ -107,6 +109,11 @@ protected:
|
||||
void _notification(int p_what);
|
||||
void _validate_property(PropertyInfo &p_property) const;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _restart_bind_compat_92089();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
public:
|
||||
AABB get_aabb() const override;
|
||||
|
||||
@ -175,7 +182,14 @@ public:
|
||||
void set_transform_align(TransformAlign p_align);
|
||||
TransformAlign get_transform_align() const;
|
||||
|
||||
void restart();
|
||||
void restart(bool p_keep_seed = false);
|
||||
|
||||
void set_use_fixed_seed(bool p_use_fixed_seed);
|
||||
bool get_use_fixed_seed() const;
|
||||
|
||||
void set_seed(uint32_t p_seed);
|
||||
uint32_t get_seed() const;
|
||||
void request_particles_process(real_t p_requested_process_time);
|
||||
|
||||
enum EmitFlags {
|
||||
EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION,
|
||||
|
@ -51,8 +51,10 @@ public:
|
||||
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_pre_process_time(RID p_particles, double p_time) override {}
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override {}
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override {}
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
|
||||
virtual void particles_set_speed_scale(RID p_particles, double p_scale) override {}
|
||||
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
|
||||
|
@ -367,6 +367,13 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->pre_process_time = p_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->request_process_time = p_request_process_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
@ -522,6 +529,12 @@ void ParticlesStorage::particles_restart(RID p_particles) {
|
||||
particles->restart_request = true;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_seed(RID p_particles, uint32_t p_seed) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->random_seed = p_seed;
|
||||
}
|
||||
|
||||
void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) {
|
||||
ERR_FAIL_COND(particles->emission_buffer != nullptr);
|
||||
|
||||
@ -812,7 +825,6 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
||||
|
||||
if (p_particles->clear) {
|
||||
p_particles->cycle_number = 0;
|
||||
p_particles->random_seed = Math::rand();
|
||||
} else if (new_phase < p_particles->phase) {
|
||||
if (p_particles->one_shot) {
|
||||
p_particles->emitting = false;
|
||||
@ -1517,8 +1529,12 @@ void ParticlesStorage::update_particles() {
|
||||
}
|
||||
|
||||
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
|
||||
double todo = particles->request_process_time;
|
||||
if (particles->clear) {
|
||||
todo += particles->pre_process_time;
|
||||
}
|
||||
|
||||
if (particles->clear && particles->pre_process_time > 0.0) {
|
||||
if (todo > 0.0) {
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
@ -1526,12 +1542,15 @@ void ParticlesStorage::update_particles() {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
|
||||
double todo = particles->pre_process_time;
|
||||
|
||||
float tmp_scale = particles->speed_scale;
|
||||
// We need this otherwise the speed scale of the particle system influences the TODO.
|
||||
particles->speed_scale = 1.0;
|
||||
while (todo >= 0) {
|
||||
_particles_process(particles, frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
particles->request_process_time = 0.0;
|
||||
particles->speed_scale = tmp_scale;
|
||||
}
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
@ -1550,7 +1569,7 @@ void ParticlesStorage::update_particles() {
|
||||
} else if (delta <= 0.0) { //unlikely but..
|
||||
delta = 0.001;
|
||||
}
|
||||
double todo = particles->frame_remainder + delta;
|
||||
todo = particles->frame_remainder + delta;
|
||||
|
||||
while (todo >= frame_time || particles->clear) {
|
||||
_particles_process(particles, frame_time);
|
||||
|
@ -166,6 +166,7 @@ private:
|
||||
int amount = 0;
|
||||
double lifetime = 1.0;
|
||||
double pre_process_time = 0.0;
|
||||
real_t request_process_time = 0.0;
|
||||
real_t explosiveness = 0.0;
|
||||
real_t randomness = 0.0;
|
||||
bool restart_request = false;
|
||||
@ -261,6 +262,7 @@ private:
|
||||
|
||||
Particles() :
|
||||
update_list(this) {
|
||||
random_seed = Math::rand();
|
||||
}
|
||||
};
|
||||
|
||||
@ -441,6 +443,7 @@ public:
|
||||
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_pre_process_time(RID p_particles, double p_time) override;
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override;
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
|
||||
@ -454,6 +457,7 @@ public:
|
||||
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
|
||||
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
|
||||
|
@ -571,8 +571,10 @@ public:
|
||||
FUNC2(particles_set_lifetime, RID, double)
|
||||
FUNC2(particles_set_one_shot, RID, bool)
|
||||
FUNC2(particles_set_pre_process_time, RID, double)
|
||||
FUNC2(particles_request_process_time, RID, real_t)
|
||||
FUNC2(particles_set_explosiveness_ratio, RID, float)
|
||||
FUNC2(particles_set_randomness_ratio, RID, float)
|
||||
FUNC2(particles_set_seed, RID, uint32_t)
|
||||
FUNC2(particles_set_custom_aabb, RID, const AABB &)
|
||||
FUNC2(particles_set_speed_scale, RID, double)
|
||||
FUNC2(particles_set_use_local_coordinates, RID, bool)
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
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_pre_process_time(RID p_particles, double p_time) = 0;
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) = 0;
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
|
||||
@ -67,6 +68,8 @@ public:
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
|
||||
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) = 0;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
|
||||
|
||||
|
@ -2681,6 +2681,7 @@ void RenderingServer::_bind_methods() {
|
||||
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_pre_process_time", "particles", "time"), &RenderingServer::particles_set_pre_process_time);
|
||||
ClassDB::bind_method(D_METHOD("particles_request_process_time", "particles", "time"), &RenderingServer::particles_request_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_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);
|
||||
|
@ -756,6 +756,7 @@ public:
|
||||
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_pre_process_time(RID p_particles, double p_time) = 0;
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) = 0;
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
|
||||
@ -766,6 +767,7 @@ public:
|
||||
virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
|
||||
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
|
||||
virtual void particles_set_collision_base_size(RID p_particles, float p_size) = 0;
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) = 0;
|
||||
|
||||
enum ParticlesTransformAlign {
|
||||
PARTICLES_TRANSFORM_ALIGN_DISABLED,
|
||||
|
Loading…
Reference in New Issue
Block a user