Fixed delay when CPUParticles & CPUParticles2D start being emitted
Particles were processed only on the next frame after the emission started, causing a one frame delay in rendering. Now the first process cycle is started during the same frame, which makes them consistent with Particles & Particles2D. Fixes #32890
This commit is contained in:
parent
119bf23720
commit
5bf516a062
|
@ -37,6 +37,9 @@
|
|||
|
||||
void CPUParticles2D::set_emitting(bool p_emitting) {
|
||||
|
||||
if (emitting == p_emitting)
|
||||
return;
|
||||
|
||||
emitting = p_emitting;
|
||||
if (emitting)
|
||||
set_process_internal(true);
|
||||
|
@ -535,6 +538,74 @@ static float rand_from_seed(uint32_t &seed) {
|
|||
return float(seed % uint32_t(65536)) / 65535.0;
|
||||
}
|
||||
|
||||
void CPUParticles2D::_update_internal() {
|
||||
|
||||
if (particles.size() == 0 || !is_visible_in_tree()) {
|
||||
_set_redraw(false);
|
||||
return;
|
||||
}
|
||||
|
||||
float delta = get_process_delta_time();
|
||||
if (emitting) {
|
||||
inactive_time = 0;
|
||||
} else {
|
||||
inactive_time += delta;
|
||||
if (inactive_time > lifetime * 1.2) {
|
||||
set_process_internal(false);
|
||||
_set_redraw(false);
|
||||
|
||||
//reset variables
|
||||
time = 0;
|
||||
inactive_time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_set_redraw(true);
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
|
||||
float frame_time;
|
||||
if (fixed_fps > 0)
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
else
|
||||
frame_time = 1.0 / 30.0;
|
||||
|
||||
float todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
float frame_time = 1.0 / fixed_fps;
|
||||
float decr = frame_time;
|
||||
|
||||
float ldelta = delta;
|
||||
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
|
||||
ldelta = 0.1;
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
float todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
todo -= decr;
|
||||
}
|
||||
|
||||
frame_remainder = todo;
|
||||
|
||||
} else {
|
||||
_particles_process(delta);
|
||||
}
|
||||
|
||||
_update_particle_data_buffer();
|
||||
}
|
||||
|
||||
void CPUParticles2D::_particles_process(float p_delta) {
|
||||
|
||||
p_delta *= speed_scale;
|
||||
|
@ -1000,6 +1071,10 @@ void CPUParticles2D::_notification(int p_what) {
|
|||
}
|
||||
|
||||
if (p_what == NOTIFICATION_DRAW) {
|
||||
// first update before rendering to avoid one frame delay after emitting starts
|
||||
if (emitting && (time == 0))
|
||||
_update_internal();
|
||||
|
||||
if (!redraw)
|
||||
return; // don't add to render list
|
||||
|
||||
|
@ -1017,71 +1092,7 @@ void CPUParticles2D::_notification(int p_what) {
|
|||
}
|
||||
|
||||
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
|
||||
|
||||
if (particles.size() == 0 || !is_visible_in_tree()) {
|
||||
_set_redraw(false);
|
||||
return;
|
||||
}
|
||||
|
||||
float delta = get_process_delta_time();
|
||||
if (emitting) {
|
||||
inactive_time = 0;
|
||||
} else {
|
||||
inactive_time += delta;
|
||||
if (inactive_time > lifetime * 1.2) {
|
||||
set_process_internal(false);
|
||||
_set_redraw(false);
|
||||
|
||||
//reset variables
|
||||
time = 0;
|
||||
inactive_time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_set_redraw(true);
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
|
||||
float frame_time;
|
||||
if (fixed_fps > 0)
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
else
|
||||
frame_time = 1.0 / 30.0;
|
||||
|
||||
float todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
float frame_time = 1.0 / fixed_fps;
|
||||
float decr = frame_time;
|
||||
|
||||
float ldelta = delta;
|
||||
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
|
||||
ldelta = 0.1;
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
float todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
todo -= decr;
|
||||
}
|
||||
|
||||
frame_remainder = todo;
|
||||
|
||||
} else {
|
||||
_particles_process(delta);
|
||||
}
|
||||
|
||||
_update_particle_data_buffer();
|
||||
_update_internal();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
|
|
|
@ -174,6 +174,7 @@ private:
|
|||
|
||||
Vector2 gravity;
|
||||
|
||||
void _update_internal();
|
||||
void _particles_process(float p_delta);
|
||||
void _update_particle_data_buffer();
|
||||
|
||||
|
|
|
@ -46,9 +46,17 @@ PoolVector<Face3> CPUParticles::get_faces(uint32_t p_usage_flags) const {
|
|||
|
||||
void CPUParticles::set_emitting(bool p_emitting) {
|
||||
|
||||
if (emitting == p_emitting)
|
||||
return;
|
||||
|
||||
emitting = p_emitting;
|
||||
if (emitting)
|
||||
if (emitting) {
|
||||
set_process_internal(true);
|
||||
|
||||
// first update before rendering to avoid one frame delay after emitting starts
|
||||
if (time == 0)
|
||||
_update_internal();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUParticles::set_amount(int p_amount) {
|
||||
|
@ -508,6 +516,81 @@ static float rand_from_seed(uint32_t &seed) {
|
|||
return float(seed % uint32_t(65536)) / 65535.0;
|
||||
}
|
||||
|
||||
void CPUParticles::_update_internal() {
|
||||
|
||||
if (particles.size() == 0 || !is_visible_in_tree()) {
|
||||
_set_redraw(false);
|
||||
return;
|
||||
}
|
||||
|
||||
float delta = get_process_delta_time();
|
||||
if (emitting) {
|
||||
inactive_time = 0;
|
||||
} else {
|
||||
inactive_time += delta;
|
||||
if (inactive_time > lifetime * 1.2) {
|
||||
set_process_internal(false);
|
||||
_set_redraw(false);
|
||||
|
||||
//reset variables
|
||||
time = 0;
|
||||
inactive_time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_set_redraw(true);
|
||||
|
||||
bool processed = false;
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
|
||||
float frame_time;
|
||||
if (fixed_fps > 0)
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
else
|
||||
frame_time = 1.0 / 30.0;
|
||||
|
||||
float todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
processed = true;
|
||||
todo -= frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
float frame_time = 1.0 / fixed_fps;
|
||||
float decr = frame_time;
|
||||
|
||||
float ldelta = delta;
|
||||
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
|
||||
ldelta = 0.1;
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
float todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
processed = true;
|
||||
todo -= decr;
|
||||
}
|
||||
|
||||
frame_remainder = todo;
|
||||
|
||||
} else {
|
||||
_particles_process(delta);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (processed) {
|
||||
_update_particle_data_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUParticles::_particles_process(float p_delta) {
|
||||
|
||||
p_delta *= speed_scale;
|
||||
|
@ -1068,85 +1151,24 @@ void CPUParticles::_notification(int p_what) {
|
|||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
set_process_internal(emitting);
|
||||
|
||||
// first update before rendering to avoid one frame delay after emitting starts
|
||||
if (emitting && (time == 0))
|
||||
_update_internal();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
_set_redraw(false);
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
// first update before rendering to avoid one frame delay after emitting starts
|
||||
if (emitting && (time == 0))
|
||||
_update_internal();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
|
||||
|
||||
if (particles.size() == 0 || !is_visible_in_tree()) {
|
||||
_set_redraw(false);
|
||||
return;
|
||||
}
|
||||
|
||||
float delta = get_process_delta_time();
|
||||
if (emitting) {
|
||||
inactive_time = 0;
|
||||
} else {
|
||||
inactive_time += delta;
|
||||
if (inactive_time > lifetime * 1.2) {
|
||||
set_process_internal(false);
|
||||
_set_redraw(false);
|
||||
|
||||
//reset variables
|
||||
time = 0;
|
||||
inactive_time = 0;
|
||||
frame_remainder = 0;
|
||||
cycle = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_set_redraw(true);
|
||||
|
||||
bool processed = false;
|
||||
|
||||
if (time == 0 && pre_process_time > 0.0) {
|
||||
|
||||
float frame_time;
|
||||
if (fixed_fps > 0)
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
else
|
||||
frame_time = 1.0 / 30.0;
|
||||
|
||||
float todo = pre_process_time;
|
||||
|
||||
while (todo >= 0) {
|
||||
_particles_process(frame_time);
|
||||
processed = true;
|
||||
todo -= frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed_fps > 0) {
|
||||
float frame_time = 1.0 / fixed_fps;
|
||||
float decr = frame_time;
|
||||
|
||||
float ldelta = delta;
|
||||
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
|
||||
ldelta = 0.1;
|
||||
} else if (ldelta <= 0.0) { //unlikely but..
|
||||
ldelta = 0.001;
|
||||
}
|
||||
float todo = frame_remainder + ldelta;
|
||||
|
||||
while (todo >= frame_time) {
|
||||
_particles_process(frame_time);
|
||||
processed = true;
|
||||
todo -= decr;
|
||||
}
|
||||
|
||||
frame_remainder = todo;
|
||||
|
||||
} else {
|
||||
_particles_process(delta);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (processed) {
|
||||
_update_particle_data_buffer();
|
||||
}
|
||||
_update_internal();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
|
|
|
@ -173,6 +173,7 @@ private:
|
|||
|
||||
Vector3 gravity;
|
||||
|
||||
void _update_internal();
|
||||
void _particles_process(float p_delta);
|
||||
void _update_particle_data_buffer();
|
||||
|
||||
|
|
Loading…
Reference in New Issue