Skip to content

Commit

Permalink
Merge pull request #41810 from reduz/particle-improvements
Browse files Browse the repository at this point in the history
Implement manual particle emission and particle sub emitters.
  • Loading branch information
reduz authored Sep 6, 2020
2 parents 8593223 + d0bddf5 commit 39f58c7
Show file tree
Hide file tree
Showing 14 changed files with 864 additions and 310 deletions.
52 changes: 52 additions & 0 deletions scene/3d/gpu_particles_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,36 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
}
}

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) {
RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags);
}

void GPUParticles3D::_attach_sub_emitter() {
Node *n = get_node_or_null(sub_emitter);
if (n) {
GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n);
if (sen && sen != this) {
RS::get_singleton()->particles_set_subemitter(particles, sen->particles);
}
}
}

void GPUParticles3D::set_sub_emitter(const NodePath &p_path) {
if (is_inside_tree()) {
RS::get_singleton()->particles_set_subemitter(particles, RID());
}

sub_emitter = p_path;

if (is_inside_tree() && sub_emitter != NodePath()) {
_attach_sub_emitter();
}
}

NodePath GPUParticles3D::get_sub_emitter() const {
return sub_emitter;
}

void GPUParticles3D::_notification(int p_what) {
if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
if (can_process()) {
Expand All @@ -319,6 +349,16 @@ void GPUParticles3D::_notification(int p_what) {
}
}

if (p_what == NOTIFICATION_ENTER_TREE) {
if (sub_emitter != NodePath()) {
_attach_sub_emitter();
}
}

if (p_what == NOTIFICATION_EXIT_TREE) {
RS::get_singleton()->particles_set_subemitter(particles, RID());
}

if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
// make sure particles are updated before rendering occurs if they were active before
if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) {
Expand Down Expand Up @@ -369,8 +409,14 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart);
ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb);

ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter);
ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter);

ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle);

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_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
Expand All @@ -396,6 +442,12 @@ void GPUParticles3D::_bind_methods() {
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH);

BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION);
BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE);
BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY);
BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR);
BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM);

BIND_CONSTANT(MAX_DRAW_PASSES);
}

Expand Down
17 changes: 17 additions & 0 deletions scene/3d/gpu_particles_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ class GPUParticles3D : public GeometryInstance3D {
bool local_coords;
int fixed_fps;
bool fractional_delta;
NodePath sub_emitter;

Ref<Material> process_material;

DrawOrder draw_order;

Vector<Ref<Mesh>> draw_passes;

void _attach_sub_emitter();

protected:
static void _bind_methods();
void _notification(int p_what);
Expand Down Expand Up @@ -121,13 +124,27 @@ class GPUParticles3D : public GeometryInstance3D {

virtual String get_configuration_warning() const override;

void set_sub_emitter(const NodePath &p_path);
NodePath get_sub_emitter() const;

void restart();

enum EmitFlags {
EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION,
EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE,
EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY,
EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR,
EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM
};

void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);

AABB capture_aabb() const;
GPUParticles3D();
~GPUParticles3D();
};

VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder)
VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags)

#endif // PARTICLES_H
Loading

0 comments on commit 39f58c7

Please sign in to comment.