Merge pull request #109142 from QbieShay/qbe/particle-process-windown

Extra particle tools for seeking
This commit is contained in:
Thaddeus Crews
2026-04-01 18:10:08 -05:00
28 changed files with 277 additions and 91 deletions
+2 -1
View File
@@ -49,9 +49,10 @@
<method name="request_particles_process">
<return type="void" />
<param index="0" name="process_time" type="float" />
<param index="1" name="process_time_residual" type="float" default="0.0" />
<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].
[param process_time] defines the time that the particles will process while emitting is on. [param process_time_residual] defines the time that particles will process with emitting turned off for the simulation. When combined with [member speed_scale] set to [code]0.0[/code], this is useful to be able to seek a particle system timeline.
</description>
</method>
<method name="restart">
+2 -1
View File
@@ -55,9 +55,10 @@
<method name="request_particles_process">
<return type="void" />
<param index="0" name="process_time" type="float" />
<param index="1" name="process_time_residual" type="float" default="0.0" />
<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].
[param process_time] defines the time that the particles will process while emitting is on. [param process_time_residual] defines the time that particles will process with emitting turned off for the simulation. When combined with [member speed_scale] set to [code]0.0[/code], this is useful to be able to seek a particle system timeline.
</description>
</method>
<method name="restart">
+2 -1
View File
@@ -44,9 +44,10 @@
<method name="request_particles_process">
<return type="void" />
<param index="0" name="process_time" type="float" />
<param index="1" name="process_time_residual" type="float" default="0" />
<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].
[param process_time] defines the time that the particles will process while emitting is on. [param process_time_residual] defines the time that particles will process with emitting turned off for the simulation. When combined with [member speed_scale] set to [code]0.0[/code], this is useful to be able to seek a particle system timeline.
</description>
</method>
<method name="restart">
+2 -1
View File
@@ -49,9 +49,10 @@
<method name="request_particles_process">
<return type="void" />
<param index="0" name="process_time" type="float" />
<param index="1" name="process_time_residual" type="float" default="0.0" />
<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].
[param process_time] defines the time that the particles will process while emitting is on. [param process_time_residual] defines the time that particles will process with emitting turned off for the simulation. When combined with [member speed_scale] set to [code]0.0[/code], this is useful to be able to seek a particle system timeline.
</description>
</method>
<method name="restart">
+4 -2
View File
@@ -3103,9 +3103,11 @@
<method name="particles_request_process_time">
<return type="void" />
<param index="0" name="particles" type="RID" />
<param index="1" name="time" type="float" />
<param index="1" name="process_time" type="float" />
<param index="2" name="process_time_residual" type="float" default="0.0" />
<description>
Requests particles to process for extra process time during a single frame.
Requests the particles to process for extra process time during a single frame.
[param process_time] defines the time that the particles will process while emitting is on. [param process_time_residual] defines the time that particles will process with emitting turned off for the simulation. When combined with the particles' speed scale set to [code]0.0[/code], this is useful to be able to seek a particle system timeline.
</description>
</method>
<method name="particles_restart">
+45 -13
View File
@@ -223,10 +223,11 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
particles->pre_process_time = p_time;
}
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->request_process_time = p_request_process_time;
particles->request_process_time_residual = p_request_process_time_residual;
}
void ParticlesStorage::particles_set_seed(RID p_particles, uint32_t p_seed) {
@@ -1063,6 +1064,7 @@ void ParticlesStorage::update_particles() {
particles->prev_phase = 0;
particles->clear = true;
particles->restart_request = false;
particles->frame_remainder = 0.0;
}
if (particles->inactive && !particles->emitting) {
@@ -1112,20 +1114,50 @@ void ParticlesStorage::update_particles() {
fixed_fps = particles->fixed_fps;
}
if (particles->clear && particles->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;
// Request process and pre-process block
{
float todo = particles->clear ? particles->pre_process_time : 0;
todo = todo > particles->request_process_time ? todo : particles->request_process_time;
todo = todo > particles->request_process_time_residual ? todo : particles->request_process_time_residual;
if (todo > 0.0) {
real_t 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;
// We need this otherwise the speed scale of the particle system influences the `todo`.
particles->speed_scale = 1.0;
if (particles->clear) {
todo = particles->pre_process_time;
while (todo > 0.00001) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (particles->request_process_time > 0.0) {
todo = particles->request_process_time;
while (todo > 0.0) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (particles->request_process_time_residual > 0.0) {
particles->emitting = false;
todo = particles->request_process_time_residual;
while (todo > 0.0) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
particles->speed_scale = tmp_scale;
}
double todo = particles->pre_process_time;
while (todo >= 0) {
_particles_process(particles, frame_time);
todo -= frame_time;
}
particles->request_process_time = 0.0;
particles->request_process_time_residual = 0.0;
}
double time_scale = MAX(particles->speed_scale, 0.0);
+2 -1
View File
@@ -157,6 +157,7 @@ private:
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t request_process_time = 0.0;
real_t request_process_time_residual = 0.0;
real_t explosiveness = 0.0;
real_t randomness = 0.0;
bool restart_request = false;
@@ -331,7 +332,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_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual) 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;
@@ -0,0 +1,10 @@
GH-109142
---------
Validate extension JSON: Error: Field 'classes/CPUParticles3D/methods/request_particles_process/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/CPUParticles2D/methods/request_particles_process/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/GPUParticles2D/methods/request_particles_process/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/GPUParticles3D/methods/request_particles_process/arguments': size changed value in new API, from 1 to 2.
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/particles_request_process_time/arguments': size changed value in new API, from 2 to 3.
Optional argument added. Compatibility methods registered.
+5
View File
@@ -38,8 +38,13 @@ void CPUParticles2D::_restart_bind_compat_92089() {
restart(false);
}
void CPUParticles2D::_request_particles_process_bind_compat_109142(real_t p_time) {
request_particles_process(p_time, 0.);
}
void CPUParticles2D::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("restart"), &CPUParticles2D::_restart_bind_compat_92089);
ClassDB::bind_compatibility_method(D_METHOD("request_particles_process", "process_time"), &CPUParticles2D::_request_particles_process_bind_compat_109142);
}
#endif // DISABLE_DEPRECATED
+52 -20
View File
@@ -632,8 +632,10 @@ 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::request_particles_process(real_t p_request_process_time, real_t p_request_process_time_residual) {
_request_process_time = p_request_process_time;
_request_process_time_residual = p_request_process_time_residual;
_update_internal();
}
void CPUParticles2D::_validate_property(PropertyInfo &p_property) const {
@@ -724,28 +726,58 @@ void CPUParticles2D::_update_internal() {
cycle = 0;
return;
}
_set_do_redraw(true);
{
float todo = time == 0 ? pre_process_time : 0;
todo = todo > _request_process_time ? todo : _request_process_time;
todo = todo > _request_process_time_residual ? todo : _request_process_time_residual;
if (todo > 0.0) {
real_t frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
float tmp_scale = speed_scale;
// We need this otherwise the speed scale of the particle system influences the `todo`.
speed_scale = 1.0;
if (time == 0) {
todo = pre_process_time;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (_request_process_time > 0.0) {
todo = _request_process_time;
emitting = true;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (_request_process_time_residual > 0.0) {
emitting = false;
todo = _request_process_time_residual;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
speed_scale = tmp_scale;
}
_request_process_time = 0;
_request_process_time_residual = 0;
}
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 decr = frame_time;
@@ -755,7 +787,7 @@ void CPUParticles2D::_update_internal() {
} else if (ldelta <= 0.0) { //unlikely but..
ldelta = 0.001;
}
todo = frame_remainder + ldelta;
double todo = frame_remainder + ldelta;
while (todo >= frame_time) {
_particles_process(frame_time);
@@ -975,7 +1007,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
} else if (!p.active) {
continue;
} else if (p.time > p.lifetime) {
} else if (p.time >= p.lifetime) {
p.active = false;
tv = 1.0;
} else {
@@ -1466,7 +1498,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("request_particles_process", "process_time", "process_time_residual"), &CPUParticles2D::request_particles_process, DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles2D::get_amount);
+4 -2
View File
@@ -129,7 +129,8 @@ private:
double lifetime = 1.0;
double pre_process_time = 0.0;
double _requested_process_time = 0.0;
real_t _request_process_time = 0.0;
real_t _request_process_time_residual = 0.0;
real_t explosiveness_ratio = 0.0;
real_t randomness_ratio = 0.0;
double lifetime_randomness = 0.0;
@@ -218,6 +219,7 @@ protected:
#ifndef DISABLE_DEPRECATED
void _restart_bind_compat_92089();
void _request_particles_process_bind_compat_109142(real_t p_time);
static void _bind_compatibility_methods();
#endif
@@ -265,7 +267,7 @@ public:
#endif
uint32_t get_seed() const;
void request_particles_process(real_t p_requested_process_time);
void request_particles_process(real_t p_requested_process_time, real_t p_requested_process_time_residual = 0.);
///////////////////
+5
View File
@@ -38,8 +38,13 @@ void GPUParticles2D::_restart_bind_compat_92089() {
restart(false);
}
void GPUParticles2D::_request_particles_process_bind_compat_109142(real_t p_time) {
request_particles_process(p_time, 0.);
}
void GPUParticles2D::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("restart"), &GPUParticles2D::_restart_bind_compat_92089);
ClassDB::bind_compatibility_method(D_METHOD("request_particles_process", "process_time"), &GPUParticles2D::_request_particles_process_bind_compat_109142);
}
#endif // DISABLE_DEPRECATED
+10 -3
View File
@@ -371,8 +371,15 @@ 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);
void GPUParticles2D::request_particles_process(real_t p_requested_process_time, real_t p_request_process_time_residual) {
RS::get_singleton()->particles_request_process_time(particles, p_requested_process_time, p_request_process_time_residual);
if (p_requested_process_time > 0.0) {
emitting = true;
RS::get_singleton()->particles_set_emitting(particles, true);
}
if (p_request_process_time_residual > 0.0) {
emitting = false;
}
}
PackedStringArray GPUParticles2D::get_configuration_warnings() const {
@@ -884,7 +891,7 @@ 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("request_particles_process", "process_time", "process_time_residual"), &GPUParticles2D::request_particles_process, DEFVAL(0));
ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles2D::get_amount);
+2 -1
View File
@@ -107,6 +107,7 @@ protected:
#ifndef DISABLE_DEPRECATED
void _restart_bind_compat_92089();
void _request_particles_process_bind_compat_109142(real_t p_time);
static void _bind_compatibility_methods();
#endif
@@ -128,7 +129,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);
void request_particles_process(real_t p_requested_process_time, real_t p_requested_process_time_residual);
#ifdef TOOLS_ENABLED
void set_show_gizmos(bool p_show_gizmos);
+5
View File
@@ -38,8 +38,13 @@ void CPUParticles3D::_restart_bind_compat_92089() {
restart(false);
}
void CPUParticles3D::_request_particles_process_bind_compat_109142(real_t p_time) {
request_particles_process(p_time, 0.);
}
void CPUParticles3D::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("restart"), &CPUParticles3D::_restart_bind_compat_92089);
ClassDB::bind_compatibility_method(D_METHOD("request_particles_process", "process_time"), &CPUParticles3D::_request_particles_process_bind_compat_109142);
}
#endif // DISABLE_DEPRECATED
+52 -17
View File
@@ -587,8 +587,10 @@ 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::request_particles_process(real_t p_request_process_time, real_t p_request_process_time_residual) {
_request_process_time = p_request_process_time;
_request_process_time_residual = p_request_process_time_residual;
_update_internal();
}
void CPUParticles3D::_validate_property(PropertyInfo &p_property) const {
@@ -672,25 +674,58 @@ void CPUParticles3D::_update_internal() {
bool processed = false;
{
float todo = time == 0 ? pre_process_time : 0;
todo = todo > _request_process_time ? todo : _request_process_time;
todo = todo > _request_process_time_residual ? todo : _request_process_time_residual;
if (todo > 0.0) {
real_t frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
float tmp_scale = speed_scale;
// We need this otherwise the speed scale of the particle system influences the TODO.
speed_scale = 1.0;
if (time == 0) {
todo = pre_process_time;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (_request_process_time > 0.0) {
todo = _request_process_time;
emitting = true;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (_request_process_time_residual > 0.0) {
emitting = false;
todo = _request_process_time_residual;
while (todo > 0.0) {
_particles_process(frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
speed_scale = tmp_scale;
processed = true;
}
_request_process_time = 0;
_request_process_time_residual = 0;
}
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 decr = frame_time;
@@ -701,7 +736,7 @@ void CPUParticles3D::_update_internal() {
} else if (ldelta <= 0.0) { //unlikely but..
ldelta = 0.001;
}
todo = frame_remainder + ldelta;
double todo = frame_remainder + ldelta;
while (todo >= frame_time) {
_particles_process(frame_time);
@@ -1549,7 +1584,7 @@ void CPUParticles3D::_bind_methods() {
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("request_particles_process", "process_time", "process_time_residual"), &CPUParticles3D::request_particles_process, DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("capture_aabb"), &CPUParticles3D::capture_aabb);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting", PROPERTY_HINT_ONESHOT), "set_emitting", "is_emitting");
+4 -2
View File
@@ -138,7 +138,8 @@ private:
double lifetime = 1.0;
double pre_process_time = 0.0;
double _requested_process_time = 0.0;
real_t _request_process_time = 0.0;
real_t _request_process_time_residual = 0.0;
real_t explosiveness_ratio = 0.0;
real_t randomness_ratio = 0.0;
double lifetime_randomness = 0.0;
@@ -213,6 +214,7 @@ protected:
#ifndef DISABLE_DEPRECATED
void _restart_bind_compat_92089();
void _request_particles_process_bind_compat_109142(real_t p_time);
static void _bind_compatibility_methods();
#endif
@@ -261,7 +263,7 @@ public:
void set_seed(uint32_t p_seed);
uint32_t get_seed() const;
void request_particles_process(real_t p_requested_process_time);
void request_particles_process(real_t p_requested_process_time, real_t p_request_process_time_residual = 0.0f);
///////////////////
+5
View File
@@ -38,8 +38,13 @@ void GPUParticles3D::_restart_bind_compat_92089() {
restart(false);
}
void GPUParticles3D::_request_particles_process_bind_compat_109142(real_t p_time) {
request_particles_process(p_time, 0.);
}
void GPUParticles3D::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("restart"), &GPUParticles3D::_restart_bind_compat_92089);
ClassDB::bind_compatibility_method(D_METHOD("request_particles_process", "process_time"), &GPUParticles3D::_request_particles_process_bind_compat_109142);
}
#endif // DISABLE_DEPRECATED
+15 -3
View File
@@ -482,8 +482,20 @@ void GPUParticles3D::_validate_property(PropertyInfo &p_property) const {
}
}
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::request_particles_process(real_t p_requested_process_time, real_t p_request_process_time_residual) {
RS::get_singleton()->particles_request_process_time(particles, p_requested_process_time, p_request_process_time_residual);
// Setting emitting independently from set_emitting is important here
// we assume to be in a controlled process situation.
// setting RS emission to true is necessary to ensure particles will emit when
// regular process time is > than zero but the particles are already in trailing mode.
// this could also be done on the GScript/tool side.
if (p_requested_process_time > 0.0) {
emitting = true;
RS::get_singleton()->particles_set_emitting(particles, true);
}
if (p_request_process_time_residual > 0.0) {
emitting = false;
}
}
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) {
@@ -850,7 +862,7 @@ 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);
ClassDB::bind_method(D_METHOD("request_particles_process", "process_time", "process_time_residual"), &GPUParticles3D::request_particles_process, DEFVAL(0.0));
ADD_SIGNAL(MethodInfo("finished"));
+2 -1
View File
@@ -116,6 +116,7 @@ protected:
#ifndef DISABLE_DEPRECATED
void _restart_bind_compat_92089();
void _request_particles_process_bind_compat_109142(real_t p_time);
static void _bind_compatibility_methods();
#endif
@@ -200,7 +201,7 @@ public:
void set_seed(uint32_t p_seed);
uint32_t get_seed() const;
void request_particles_process(real_t p_requested_process_time);
void request_particles_process(real_t p_requested_process_time, real_t p_request_process_time_residual = 0.0f);
enum EmitFlags {
EMIT_FLAG_POSITION = RSE::PARTICLES_EMIT_FLAG_POSITION,
@@ -52,7 +52,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_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_particles_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 {}
@@ -375,10 +375,11 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
particles->pre_process_time = p_time;
}
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->request_process_time = p_request_process_time;
particles->request_process_time_residual = p_request_process_time_residual;
}
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
@@ -836,7 +837,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
}
double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime), 1.0);
double new_phase = Math::fmod((double)(p_particles->phase + (p_delta / p_particles->lifetime)), 1.0);
//move back history (if there is any)
for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
@@ -1461,13 +1462,13 @@ void ParticlesStorage::update_particles() {
particles->prev_phase = 0;
particles->clear = true;
particles->restart_request = false;
particles->frame_remainder = 0.0;
}
if (particles->inactive && !particles->emitting) {
//go next
continue;
}
if (particles->emitting) {
if (particles->inactive) {
//restart system from scratch
@@ -1558,13 +1559,12 @@ void ParticlesStorage::update_particles() {
}
}
double todo = particles->request_process_time;
if (particles->clear) {
todo += particles->pre_process_time;
}
float todo = particles->clear ? particles->pre_process_time : 0;
todo = todo > particles->request_process_time ? todo : particles->request_process_time;
todo = todo > particles->request_process_time_residual ? todo : particles->request_process_time_residual;
if (todo > 0.0) {
double frame_time;
real_t frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
@@ -1574,19 +1574,38 @@ void ParticlesStorage::update_particles() {
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;
if (particles->clear) {
todo = particles->pre_process_time;
while (todo > 0.0) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (particles->request_process_time > 0.0) {
todo = particles->request_process_time;
while (todo > 0.0) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
if (particles->request_process_time_residual > 0.0) {
particles->emitting = false;
todo = particles->request_process_time_residual;
while (todo > 0.0) {
_particles_process(particles, frame_time > todo ? todo : frame_time);
todo -= frame_time;
}
}
particles->request_process_time = 0.0;
particles->speed_scale = tmp_scale;
}
double time_scale = MAX(particles->speed_scale, 0.0);
particles->request_process_time = 0.0;
particles->request_process_time_residual = 0.0;
float time_scale = MAX(particles->speed_scale, 0.0);
if (fixed_fps > 0) {
double frame_time = 1.0 / fixed_fps;
double delta = RendererCompositorRD::get_singleton()->get_frame_delta_time();
float frame_time = 1.0 / fixed_fps;
float delta = (float)RendererCompositorRD::get_singleton()->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
@@ -1603,7 +1622,6 @@ void ParticlesStorage::update_particles() {
} else {
_particles_process(particles, RendererCompositorRD::get_singleton()->get_frame_delta_time() * time_scale);
}
// Ensure that memory is initialized (the code above should ensure that _particles_process is always called at least once upon clearing).
DEV_ASSERT(!particles->clear);
@@ -169,6 +169,7 @@ private:
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t request_process_time = 0.0;
real_t request_process_time_residual = 0.0;
real_t explosiveness = 0.0;
real_t randomness = 0.0;
bool restart_request = false;
@@ -455,7 +456,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_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual) 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;
@@ -66,6 +66,10 @@ void RenderingServer::_viewport_set_size_compat_115799(RID p_viewport, int p_wid
viewport_set_size(p_viewport, p_width, p_height, 1);
}
void RenderingServer::_particles_request_process_time_bind_compat_109142(RID p_particles, real_t p_request_process_time) {
particles_request_process_time(p_particles, p_request_process_time, 0.0);
}
void RenderingServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("multimesh_allocate_data", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::_multimesh_allocate_data_bind_compat_99455, DEFVAL(false), DEFVAL(false));
ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
@@ -75,6 +79,7 @@ void RenderingServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("instance_set_interpolated", "instance", "interpolated"), &RenderingServer::_instance_set_interpolated_bind_compat_104269);
ClassDB::bind_compatibility_method(D_METHOD("instance_reset_physics_interpolation", "instance"), &RenderingServer::_instance_reset_physics_interpolation_bind_compat_104269);
ClassDB::bind_compatibility_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::_viewport_set_size_compat_115799);
ClassDB::bind_compatibility_method(D_METHOD("particles_request_process_time", "particles", "process_time"), &RenderingServer::_particles_request_process_time_bind_compat_109142);
}
#endif // DISABLE_DEPRECATED
+1 -1
View File
@@ -2710,7 +2710,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_request_process_time", "particles", "process_time", "process_time_residual"), &RenderingServer::particles_request_process_time, DEFVAL(0.0f));
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);
+2 -1
View File
@@ -96,6 +96,7 @@ protected:
void _instance_set_interpolated_bind_compat_104269(RID p_instance, bool p_interpolated);
void _instance_reset_physics_interpolation_bind_compat_104269(RID p_instance);
void _viewport_set_size_compat_115799(RID p_viewport, int p_width, int p_height);
void _particles_request_process_time_bind_compat_109142(RID p_particles, real_t p_request_process_time);
static void _bind_compatibility_methods();
#endif
@@ -436,7 +437,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_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual = 0.0) = 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;
+1 -1
View File
@@ -617,7 +617,7 @@ 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)
FUNC3(particles_request_process_time, RID, real_t, real_t)
FUNC2(particles_set_explosiveness_ratio, RID, float)
FUNC2(particles_set_randomness_ratio, RID, float)
FUNC2(particles_set_seed, RID, uint32_t)
@@ -62,7 +62,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_request_process_time(RID p_particles, real_t p_request_process_time, real_t p_request_process_time_residual = 0.0) = 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;