|
@@ -32,6 +32,7 @@
|
|
|
|
|
|
#include "core/os/os.h"
|
|
|
#include "scene/resources/particles_material.h"
|
|
|
+#include "scene/scene_string_names.h"
|
|
|
|
|
|
#include "servers/visual_server.h"
|
|
|
|
|
@@ -43,13 +44,31 @@ PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
|
|
|
}
|
|
|
|
|
|
void Particles::set_emitting(bool p_emitting) {
|
|
|
- VS::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_canceled = false;
|
|
|
+ emission_time = lifetime;
|
|
|
+ active_time = lifetime * (2 - explosiveness_ratio);
|
|
|
+ } else {
|
|
|
+ signal_canceled = 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;
|
|
|
+ VS::get_singleton()->particles_set_emitting(particles, p_emitting);
|
|
|
}
|
|
|
|
|
|
void Particles::set_amount(int p_amount) {
|
|
@@ -118,7 +137,7 @@ void Particles::set_speed_scale(float p_scale) {
|
|
|
}
|
|
|
|
|
|
bool Particles::is_emitting() const {
|
|
|
- return VS::get_singleton()->particles_get_emitting(particles);
|
|
|
+ return emitting;
|
|
|
}
|
|
|
int Particles::get_amount() const {
|
|
|
return amount;
|
|
@@ -281,6 +300,16 @@ String Particles::get_configuration_warning() const {
|
|
|
void Particles::restart() {
|
|
|
VisualServer::get_singleton()->particles_restart(particles);
|
|
|
VisualServer::get_singleton()->particles_set_emitting(particles, true);
|
|
|
+
|
|
|
+ emitting = true;
|
|
|
+ active = true;
|
|
|
+ signal_canceled = false;
|
|
|
+ time = 0;
|
|
|
+ emission_time = lifetime * (1 - explosiveness_ratio);
|
|
|
+ active_time = lifetime * (2 - explosiveness_ratio);
|
|
|
+ if (one_shot) {
|
|
|
+ set_process_internal(true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
AABB Particles::capture_aabb() const {
|
|
@@ -309,9 +338,23 @@ void Particles::_notification(int p_what) {
|
|
|
// Use internal process when emitting and one_shot are on so that when
|
|
|
// the shot ends the editor can properly update
|
|
|
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
|
|
|
- if (one_shot && !is_emitting()) {
|
|
|
- _change_notify();
|
|
|
- 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_canceled) {
|
|
|
+ emit_signal(SceneStringNames::get_singleton()->finished);
|
|
|
+ }
|
|
|
+ active = false;
|
|
|
+ if (!emitting) {
|
|
|
+ set_process_internal(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -365,6 +408,8 @@ void Particles::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("restart"), &Particles::restart);
|
|
|
ClassDB::bind_method(D_METHOD("capture_aabb"), &Particles::capture_aabb);
|
|
|
|
|
|
+ ADD_SIGNAL(MethodInfo("finished"));
|
|
|
+
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
|
|
|
ADD_GROUP("Time", "");
|