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:
PouleyKetchoupp 2019-10-19 17:30:13 +02:00
parent 119bf23720
commit 5bf516a062
4 changed files with 173 additions and 138 deletions

View File

@ -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) {

View File

@ -174,6 +174,7 @@ private:
Vector2 gravity;
void _update_internal();
void _particles_process(float p_delta);
void _update_particle_data_buffer();

View File

@ -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) {

View File

@ -173,6 +173,7 @@ private:
Vector3 gravity;
void _update_internal();
void _particles_process(float p_delta);
void _update_particle_data_buffer();