diff options
Diffstat (limited to 'scene/2d/gpu_particles_2d.cpp')
-rw-r--r-- | scene/2d/gpu_particles_2d.cpp | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index 078a73c583..8c5782dc41 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -30,21 +30,39 @@ #include "gpu_particles_2d.h" -#include "core/core_string_names.h" +#include "scene/resources/atlas_texture.h" #include "scene/resources/particle_process_material.h" +#include "scene/scene_string_names.h" #ifdef TOOLS_ENABLED #include "core/config/engine.h" #endif void GPUParticles2D::set_emitting(bool p_emitting) { - RS::get_singleton()->particles_set_emitting(particles, p_emitting); + // Do not return even if `p_emitting == emitting` because `emitting` is just an approximation. if (p_emitting && one_shot) { + if (!active && !emitting) { + // Last cycle ended. + active = true; + time = 0; + signal_cancled = false; + emission_time = lifetime; + active_time = lifetime * (2 - explosiveness_ratio); + } else { + signal_cancled = true; + } set_process_internal(true); } else if (!p_emitting) { - set_process_internal(false); + if (one_shot) { + set_process_internal(true); + } else { + set_process_internal(false); + } } + + emitting = p_emitting; + RS::get_singleton()->particles_set_emitting(particles, p_emitting); } void GPUParticles2D::set_amount(int p_amount) { @@ -149,7 +167,7 @@ void GPUParticles2D::set_trail_enabled(bool p_enabled) { } void GPUParticles2D::set_trail_lifetime(double p_seconds) { - ERR_FAIL_COND(p_seconds < 0.001); + ERR_FAIL_COND(p_seconds < 0.01); trail_lifetime = p_seconds; RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime); queue_redraw(); @@ -211,7 +229,7 @@ void GPUParticles2D::set_speed_scale(double p_scale) { } bool GPUParticles2D::is_emitting() const { - return RS::get_singleton()->particles_get_emitting(particles); + return emitting; } int GPUParticles2D::get_amount() const { @@ -338,13 +356,13 @@ Rect2 GPUParticles2D::capture_rect() const { void GPUParticles2D::set_texture(const Ref<Texture2D> &p_texture) { if (texture.is_valid()) { - texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GPUParticles2D::_texture_changed)); + texture->disconnect_changed(callable_mp(this, &GPUParticles2D::_texture_changed)); } texture = p_texture; if (texture.is_valid()) { - texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GPUParticles2D::_texture_changed)); + texture->connect_changed(callable_mp(this, &GPUParticles2D::_texture_changed)); } _update_collision_size(); queue_redraw(); @@ -405,6 +423,16 @@ NodePath GPUParticles2D::get_sub_emitter() const { void GPUParticles2D::restart() { RS::get_singleton()->particles_restart(particles); RS::get_singleton()->particles_set_emitting(particles, true); + + emitting = true; + active = true; + signal_cancled = false; + time = 0; + emission_time = lifetime; + active_time = lifetime * (2 - explosiveness_ratio); + if (one_shot) { + set_process_internal(true); + } } void GPUParticles2D::_notification(int p_what) { @@ -570,9 +598,23 @@ void GPUParticles2D::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (one_shot && !is_emitting()) { - notify_property_list_changed(); - set_process_internal(false); + if (one_shot) { + time += get_process_delta_time(); + if (time > emission_time) { + emitting = false; + if (!active) { + set_process_internal(false); + } + } + if (time > active_time) { + if (active && !signal_cancled) { + emit_signal(SceneStringNames::get_singleton()->finished); + } + active = false; + if (!emitting) { + set_process_internal(false); + } + } } } break; } @@ -638,6 +680,8 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_trail_section_subdivisions", "subdivisions"), &GPUParticles2D::set_trail_section_subdivisions); ClassDB::bind_method(D_METHOD("get_trail_section_subdivisions"), &GPUParticles2D::get_trail_section_subdivisions); + ADD_SIGNAL(MethodInfo("finished")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); |