Browse Source

Add `finished` signal to CPUParticles

HolonProduction 2 years ago
parent
commit
a1c0d206e8

+ 7 - 0
doc/classes/CPUParticles2D.xml

@@ -285,6 +285,13 @@
 			Particle texture. If [code]null[/code], particles will be squares.
 			Particle texture. If [code]null[/code], particles will be squares.
 		</member>
 		</member>
 	</members>
 	</members>
+	<signals>
+		<signal name="finished">
+			<description>
+				Emitted when all active particles have finished processing. When [member one_shot] is disabled, particles will process continuously, so this is never emitted.
+			</description>
+		</signal>
+	</signals>
 	<constants>
 	<constants>
 		<constant name="DRAW_ORDER_INDEX" value="0" enum="DrawOrder">
 		<constant name="DRAW_ORDER_INDEX" value="0" enum="DrawOrder">
 			Particles are drawn in the order emitted.
 			Particles are drawn in the order emitted.

+ 7 - 0
doc/classes/CPUParticles3D.xml

@@ -309,6 +309,13 @@
 			Minimum tangent acceleration.
 			Minimum tangent acceleration.
 		</member>
 		</member>
 	</members>
 	</members>
+	<signals>
+		<signal name="finished">
+			<description>
+				Emitted when all active particles have finished processing. When [member one_shot] is disabled, particles will process continuously, so this is never emitted.
+			</description>
+		</signal>
+	</signals>
 	<constants>
 	<constants>
 		<constant name="DRAW_ORDER_INDEX" value="0" enum="DrawOrder">
 		<constant name="DRAW_ORDER_INDEX" value="0" enum="DrawOrder">
 			Particles are drawn in the order emitted.
 			Particles are drawn in the order emitted.

+ 19 - 15
scene/2d/cpu_particles_2d.cpp

@@ -33,6 +33,7 @@
 #include "core/core_string_names.h"
 #include "core/core_string_names.h"
 #include "scene/2d/gpu_particles_2d.h"
 #include "scene/2d/gpu_particles_2d.h"
 #include "scene/resources/particle_process_material.h"
 #include "scene/resources/particle_process_material.h"
+#include "scene/scene_string_names.h"
 
 
 void CPUParticles2D::set_emitting(bool p_emitting) {
 void CPUParticles2D::set_emitting(bool p_emitting) {
 	if (emitting == p_emitting) {
 	if (emitting == p_emitting) {
@@ -41,6 +42,7 @@ void CPUParticles2D::set_emitting(bool p_emitting) {
 
 
 	emitting = p_emitting;
 	emitting = p_emitting;
 	if (emitting) {
 	if (emitting) {
+		active = true;
 		set_process_internal(true);
 		set_process_internal(true);
 	}
 	}
 }
 }
@@ -259,7 +261,6 @@ PackedStringArray CPUParticles2D::get_configuration_warnings() const {
 
 
 void CPUParticles2D::restart() {
 void CPUParticles2D::restart() {
 	time = 0;
 	time = 0;
-	inactive_time = 0;
 	frame_remainder = 0;
 	frame_remainder = 0;
 	cycle = 0;
 	cycle = 0;
 	emitting = false;
 	emitting = false;
@@ -561,21 +562,15 @@ void CPUParticles2D::_update_internal() {
 	}
 	}
 
 
 	double delta = get_process_delta_time();
 	double 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_do_redraw(false);
+	if (!active && !emitting) {
+		set_process_internal(false);
+		_set_do_redraw(false);
 
 
-			//reset variables
-			time = 0;
-			inactive_time = 0;
-			frame_remainder = 0;
-			cycle = 0;
-			return;
-		}
+		//reset variables
+		time = 0;
+		frame_remainder = 0;
+		cycle = 0;
+		return;
 	}
 	}
 	_set_do_redraw(true);
 	_set_do_redraw(true);
 
 
@@ -650,6 +645,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
 
 
 	double system_phase = time / lifetime;
 	double system_phase = time / lifetime;
 
 
+	bool should_be_active = false;
 	for (int i = 0; i < pcount; i++) {
 	for (int i = 0; i < pcount; i++) {
 		Particle &p = parray[i];
 		Particle &p = parray[i];
 
 
@@ -994,6 +990,12 @@ void CPUParticles2D::_particles_process(double p_delta) {
 		p.transform.columns[1] *= base_scale.y;
 		p.transform.columns[1] *= base_scale.y;
 
 
 		p.transform[2] += p.velocity * local_delta;
 		p.transform[2] += p.velocity * local_delta;
+
+		should_be_active = true;
+	}
+	if (!Math::is_equal_approx(time, 0.0) && active && !should_be_active) {
+		active = false;
+		emit_signal(SceneStringNames::get_singleton()->finished);
 	}
 	}
 }
 }
 
 
@@ -1364,6 +1366,8 @@ void CPUParticles2D::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles);
 	ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles);
 
 
+	ADD_SIGNAL(MethodInfo("finished"));
+
 	ADD_GROUP("Emission Shape", "emission_");
 	ADD_GROUP("Emission Shape", "emission_");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Rectangle,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Rectangle,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,suffix:px"), "set_emission_sphere_radius", "get_emission_sphere_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,suffix:px"), "set_emission_sphere_radius", "get_emission_sphere_radius");

+ 1 - 1
scene/2d/cpu_particles_2d.h

@@ -78,6 +78,7 @@ public:
 
 
 private:
 private:
 	bool emitting = false;
 	bool emitting = false;
+	bool active = false;
 
 
 	struct Particle {
 	struct Particle {
 		Transform2D transform;
 		Transform2D transform;
@@ -99,7 +100,6 @@ private:
 	};
 	};
 
 
 	double time = 0.0;
 	double time = 0.0;
-	double inactive_time = 0.0;
 	double frame_remainder = 0.0;
 	double frame_remainder = 0.0;
 	int cycle = 0;
 	int cycle = 0;
 	bool do_redraw = false;
 	bool do_redraw = false;

+ 19 - 15
scene/3d/cpu_particles_3d.cpp

@@ -34,6 +34,7 @@
 #include "scene/3d/gpu_particles_3d.h"
 #include "scene/3d/gpu_particles_3d.h"
 #include "scene/main/viewport.h"
 #include "scene/main/viewport.h"
 #include "scene/resources/particle_process_material.h"
 #include "scene/resources/particle_process_material.h"
+#include "scene/scene_string_names.h"
 
 
 AABB CPUParticles3D::get_aabb() const {
 AABB CPUParticles3D::get_aabb() const {
 	return AABB();
 	return AABB();
@@ -46,6 +47,7 @@ void CPUParticles3D::set_emitting(bool p_emitting) {
 
 
 	emitting = p_emitting;
 	emitting = p_emitting;
 	if (emitting) {
 	if (emitting) {
+		active = true;
 		set_process_internal(true);
 		set_process_internal(true);
 
 
 		// first update before rendering to avoid one frame delay after emitting starts
 		// first update before rendering to avoid one frame delay after emitting starts
@@ -220,7 +222,6 @@ PackedStringArray CPUParticles3D::get_configuration_warnings() const {
 
 
 void CPUParticles3D::restart() {
 void CPUParticles3D::restart() {
 	time = 0;
 	time = 0;
-	inactive_time = 0;
 	frame_remainder = 0;
 	frame_remainder = 0;
 	cycle = 0;
 	cycle = 0;
 	emitting = false;
 	emitting = false;
@@ -575,21 +576,15 @@ void CPUParticles3D::_update_internal() {
 	}
 	}
 
 
 	double delta = get_process_delta_time();
 	double 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);
+	if (!active && !emitting) {
+		set_process_internal(false);
+		_set_redraw(false);
 
 
-			//reset variables
-			time = 0;
-			inactive_time = 0;
-			frame_remainder = 0;
-			cycle = 0;
-			return;
-		}
+		//reset variables
+		time = 0;
+		frame_remainder = 0;
+		cycle = 0;
+		return;
 	}
 	}
 	_set_redraw(true);
 	_set_redraw(true);
 
 
@@ -670,6 +665,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
 
 
 	double system_phase = time / lifetime;
 	double system_phase = time / lifetime;
 
 
+	bool should_be_active = false;
 	for (int i = 0; i < pcount; i++) {
 	for (int i = 0; i < pcount; i++) {
 		Particle &p = parray[i];
 		Particle &p = parray[i];
 
 
@@ -1136,6 +1132,12 @@ void CPUParticles3D::_particles_process(double p_delta) {
 		}
 		}
 
 
 		p.transform.origin += p.velocity * local_delta;
 		p.transform.origin += p.velocity * local_delta;
+
+		should_be_active = true;
+	}
+	if (!Math::is_equal_approx(time, 0.0) && active && !should_be_active) {
+		active = false;
+		emit_signal(SceneStringNames::get_singleton()->finished);
 	}
 	}
 }
 }
 
 
@@ -1543,6 +1545,8 @@ void CPUParticles3D::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles);
 	ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles);
 
 
+	ADD_SIGNAL(MethodInfo("finished"));
+
 	ADD_GROUP("Emission Shape", "emission_");
 	ADD_GROUP("Emission Shape", "emission_");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Box,Points,Directed Points,Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Box,Points,Directed Points,Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");

+ 1 - 1
scene/3d/cpu_particles_3d.h

@@ -81,6 +81,7 @@ public:
 
 
 private:
 private:
 	bool emitting = false;
 	bool emitting = false;
+	bool active = false;
 
 
 	struct Particle {
 	struct Particle {
 		Transform3D transform;
 		Transform3D transform;
@@ -101,7 +102,6 @@ private:
 	};
 	};
 
 
 	double time = 0.0;
 	double time = 0.0;
-	double inactive_time = 0.0;
 	double frame_remainder = 0.0;
 	double frame_remainder = 0.0;
 	int cycle = 0;
 	int cycle = 0;
 	bool redraw = false;
 	bool redraw = false;

+ 0 - 1
scene/scene_string_names.cpp

@@ -57,7 +57,6 @@ SceneStringNames::SceneStringNames() {
 	sleeping_state_changed = StaticCString::create("sleeping_state_changed");
 	sleeping_state_changed = StaticCString::create("sleeping_state_changed");
 
 
 	finished = StaticCString::create("finished");
 	finished = StaticCString::create("finished");
-	emission_finished = StaticCString::create("emission_finished");
 	animation_finished = StaticCString::create("animation_finished");
 	animation_finished = StaticCString::create("animation_finished");
 	animation_changed = StaticCString::create("animation_changed");
 	animation_changed = StaticCString::create("animation_changed");
 	animation_started = StaticCString::create("animation_started");
 	animation_started = StaticCString::create("animation_started");

+ 0 - 1
scene/scene_string_names.h

@@ -93,7 +93,6 @@ public:
 	StringName sort_children;
 	StringName sort_children;
 
 
 	StringName finished;
 	StringName finished;
-	StringName emission_finished;
 	StringName animation_finished;
 	StringName animation_finished;
 	StringName animation_changed;
 	StringName animation_changed;
 	StringName animation_started;
 	StringName animation_started;