Skip to content

Commit d0bddf5

Browse files
committed
Implement manual particle emission and particle sub emitters.
1 parent ceed524 commit d0bddf5

14 files changed

+864
-310
lines changed

scene/3d/gpu_particles_3d.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,36 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
301301
}
302302
}
303303

304+
void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
305+
RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags);
306+
}
307+
308+
void GPUParticles3D::_attach_sub_emitter() {
309+
Node *n = get_node_or_null(sub_emitter);
310+
if (n) {
311+
GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n);
312+
if (sen && sen != this) {
313+
RS::get_singleton()->particles_set_subemitter(particles, sen->particles);
314+
}
315+
}
316+
}
317+
318+
void GPUParticles3D::set_sub_emitter(const NodePath &p_path) {
319+
if (is_inside_tree()) {
320+
RS::get_singleton()->particles_set_subemitter(particles, RID());
321+
}
322+
323+
sub_emitter = p_path;
324+
325+
if (is_inside_tree() && sub_emitter != NodePath()) {
326+
_attach_sub_emitter();
327+
}
328+
}
329+
330+
NodePath GPUParticles3D::get_sub_emitter() const {
331+
return sub_emitter;
332+
}
333+
304334
void GPUParticles3D::_notification(int p_what) {
305335
if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
306336
if (can_process()) {
@@ -319,6 +349,16 @@ void GPUParticles3D::_notification(int p_what) {
319349
}
320350
}
321351

352+
if (p_what == NOTIFICATION_ENTER_TREE) {
353+
if (sub_emitter != NodePath()) {
354+
_attach_sub_emitter();
355+
}
356+
}
357+
358+
if (p_what == NOTIFICATION_EXIT_TREE) {
359+
RS::get_singleton()->particles_set_subemitter(particles, RID());
360+
}
361+
322362
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
323363
// make sure particles are updated before rendering occurs if they were active before
324364
if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) {
@@ -369,8 +409,14 @@ void GPUParticles3D::_bind_methods() {
369409
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart);
370410
ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb);
371411

412+
ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter);
413+
ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter);
414+
415+
ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle);
416+
372417
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
373418
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
419+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
374420
ADD_GROUP("Time", "");
375421
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
376422
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
@@ -396,6 +442,12 @@ void GPUParticles3D::_bind_methods() {
396442
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
397443
BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH);
398444

445+
BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION);
446+
BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE);
447+
BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY);
448+
BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR);
449+
BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM);
450+
399451
BIND_CONSTANT(MAX_DRAW_PASSES);
400452
}
401453

scene/3d/gpu_particles_3d.h

+17
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ class GPUParticles3D : public GeometryInstance3D {
6464
bool local_coords;
6565
int fixed_fps;
6666
bool fractional_delta;
67+
NodePath sub_emitter;
6768

6869
Ref<Material> process_material;
6970

7071
DrawOrder draw_order;
7172

7273
Vector<Ref<Mesh>> draw_passes;
7374

75+
void _attach_sub_emitter();
76+
7477
protected:
7578
static void _bind_methods();
7679
void _notification(int p_what);
@@ -121,13 +124,27 @@ class GPUParticles3D : public GeometryInstance3D {
121124

122125
virtual String get_configuration_warning() const override;
123126

127+
void set_sub_emitter(const NodePath &p_path);
128+
NodePath get_sub_emitter() const;
129+
124130
void restart();
125131

132+
enum EmitFlags {
133+
EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION,
134+
EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE,
135+
EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY,
136+
EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR,
137+
EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM
138+
};
139+
140+
void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
141+
126142
AABB capture_aabb() const;
127143
GPUParticles3D();
128144
~GPUParticles3D();
129145
};
130146

131147
VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder)
148+
VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags)
132149

133150
#endif // PARTICLES_H

0 commit comments

Comments
 (0)