|
@@ -31,19 +31,37 @@
|
|
|
#include "gpu_particles_3d.h"
|
|
|
|
|
|
#include "scene/resources/particle_process_material.h"
|
|
|
+#include "scene/scene_string_names.h"
|
|
|
|
|
|
AABB GPUParticles3D::get_aabb() const {
|
|
|
return AABB();
|
|
|
}
|
|
|
|
|
|
void GPUParticles3D::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 GPUParticles3D::set_amount(int p_amount) {
|
|
@@ -122,7 +140,7 @@ void GPUParticles3D::set_collision_base_size(real_t p_size) {
|
|
|
}
|
|
|
|
|
|
bool GPUParticles3D::is_emitting() const {
|
|
|
- return RS::get_singleton()->particles_get_emitting(particles);
|
|
|
+ return emitting;
|
|
|
}
|
|
|
|
|
|
int GPUParticles3D::get_amount() const {
|
|
@@ -373,6 +391,16 @@ PackedStringArray GPUParticles3D::get_configuration_warnings() const {
|
|
|
void GPUParticles3D::restart() {
|
|
|
RenderingServer::get_singleton()->particles_restart(particles);
|
|
|
RenderingServer::get_singleton()->particles_set_emitting(particles, true);
|
|
|
+
|
|
|
+ emitting = true;
|
|
|
+ active = true;
|
|
|
+ signal_cancled = false;
|
|
|
+ time = 0;
|
|
|
+ emission_time = lifetime * (1 - explosiveness_ratio);
|
|
|
+ active_time = lifetime * (2 - explosiveness_ratio);
|
|
|
+ if (one_shot) {
|
|
|
+ set_process_internal(true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
AABB GPUParticles3D::capture_aabb() const {
|
|
@@ -425,9 +453,23 @@ void GPUParticles3D::_notification(int p_what) {
|
|
|
// Use internal process when emitting and one_shot is on so that when
|
|
|
// the shot ends the editor can properly update.
|
|
|
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;
|
|
|
|
|
@@ -571,6 +613,8 @@ void GPUParticles3D::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("set_transform_align", "align"), &GPUParticles3D::set_transform_align);
|
|
|
ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align);
|
|
|
|
|
|
+ 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");
|