Skip to content

Commit

Permalink
Merge pull request #100050 from YeldhamDev/sub_emitter_at_start
Browse files Browse the repository at this point in the history
Add "At Start" mode for sub-emitter particles
  • Loading branch information
akien-mga committed Jan 14, 2025
2 parents a69ccee + eb5839d commit 1e1f54e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
8 changes: 7 additions & 1 deletion doc/classes/ParticleProcessMaterial.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@
The amount of particles to spawn from the subemitter node when the particle expires.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
</member>
<member name="sub_emitter_amount_at_start" type="int" setter="set_sub_emitter_amount_at_start" getter="get_sub_emitter_amount_at_start">
The amount of particles to spawn from the subemitter node when the particle spawns.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
</member>
<member name="sub_emitter_frequency" type="float" setter="set_sub_emitter_frequency" getter="get_sub_emitter_frequency">
The frequency at which particles should be emitted from the subemitter node. One particle will be spawned every [member sub_emitter_frequency] seconds.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
Expand Down Expand Up @@ -521,7 +525,9 @@
</constant>
<constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode">
<constant name="SUB_EMITTER_AT_START" value="4" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_MAX" value="5" enum="SubEmitterMode">
Represents the size of the [enum SubEmitterMode] enum.
</constant>
<constant name="COLLISION_DISABLED" value="0" enum="CollisionMode">
Expand Down
34 changes: 33 additions & 1 deletion scene/resources/particle_process_material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ void ParticleProcessMaterial::init_shaders() {
shader_names->sub_emitter_frequency = "sub_emitter_frequency";
shader_names->sub_emitter_amount_at_end = "sub_emitter_amount_at_end";
shader_names->sub_emitter_amount_at_collision = "sub_emitter_amount_at_collision";
shader_names->sub_emitter_amount_at_start = "sub_emitter_amount_at_start";
shader_names->sub_emitter_keep_velocity = "sub_emitter_keep_velocity";

shader_names->collision_friction = "collision_friction";
Expand Down Expand Up @@ -287,6 +288,9 @@ void ParticleProcessMaterial::_update_shader() {
if (sub_emitter_mode == SUB_EMITTER_AT_COLLISION) {
code += "uniform int sub_emitter_amount_at_collision;\n";
}
if (sub_emitter_mode == SUB_EMITTER_AT_START) {
code += "uniform int sub_emitter_amount_at_start;\n";
}
code += "uniform bool sub_emitter_keep_velocity;\n";
}

Expand Down Expand Up @@ -923,6 +927,10 @@ void ParticleProcessMaterial::_update_shader() {
code += " float pi = 3.14159;\n";
code += " float degree_to_rad = pi / 180.0;\n\n";

if (sub_emitter_mode == SUB_EMITTER_AT_START && !RenderingServer::get_singleton()->is_low_end()) {
code += " bool just_spawned = CUSTOM.y == 0.0;\n";
}

code += " CUSTOM.y += DELTA / LIFETIME;\n";
code += " CUSTOM.y = mix(CUSTOM.y, 1.0, INTERPOLATE_TO_END);\n";
code += " float lifetime_percent = CUSTOM.y / params.lifetime;\n";
Expand Down Expand Up @@ -1139,6 +1147,11 @@ void ParticleProcessMaterial::_update_shader() {
code += " emit_count = sub_emitter_amount_at_end;\n";
code += " }\n";
} break;
case SUB_EMITTER_AT_START: {
code += " if (just_spawned) {\n";
code += " emit_count = sub_emitter_amount_at_start;\n";
code += " }\n";
} break;
default: {
}
}
Expand Down Expand Up @@ -1858,6 +1871,10 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
p_property.usage = PROPERTY_USAGE_NONE;
}

if (p_property.name == "sub_emitter_amount_at_start" && sub_emitter_mode != SUB_EMITTER_AT_START) {
p_property.usage = PROPERTY_USAGE_NONE;
}

if (!turbulence_enabled) {
if (p_property.name == "turbulence_noise_strength" ||
p_property.name == "turbulence_noise_scale" ||
Expand Down Expand Up @@ -1932,6 +1949,15 @@ int ParticleProcessMaterial::get_sub_emitter_amount_at_collision() const {
return sub_emitter_amount_at_collision;
}

void ParticleProcessMaterial::set_sub_emitter_amount_at_start(int p_amount) {
sub_emitter_amount_at_start = p_amount;
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_start, p_amount);
}

int ParticleProcessMaterial::get_sub_emitter_amount_at_start() const {
return sub_emitter_amount_at_start;
}

void ParticleProcessMaterial::set_sub_emitter_keep_velocity(bool p_enable) {
sub_emitter_keep_velocity = p_enable;
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable);
Expand Down Expand Up @@ -2113,6 +2139,9 @@ void ParticleProcessMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_collision"), &ParticleProcessMaterial::get_sub_emitter_amount_at_collision);
ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_collision", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_collision);

ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_start"), &ParticleProcessMaterial::get_sub_emitter_amount_at_start);
ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_start", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_start);

ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticleProcessMaterial::get_sub_emitter_keep_velocity);
ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticleProcessMaterial::set_sub_emitter_keep_velocity);

Expand Down Expand Up @@ -2242,10 +2271,11 @@ void ParticleProcessMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_scale"), "set_collision_use_scale", "is_collision_using_scale");
ADD_GROUP("Sub Emitter", "sub_emitter_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,At End,At Collision"), "set_sub_emitter_mode", "get_sub_emitter_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled:0,Constant:1,At Start:4,At End:2,At Collision:3"), "set_sub_emitter_mode", "get_sub_emitter_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:Hz"), "set_sub_emitter_frequency", "get_sub_emitter_frequency");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_collision", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_collision", "get_sub_emitter_amount_at_collision");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_start", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_start", "get_sub_emitter_amount_at_start");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity");

ADD_SIGNAL(MethodInfo("emission_shape_changed"));
Expand Down Expand Up @@ -2290,6 +2320,7 @@ void ParticleProcessMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT);
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END);
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION);
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_START);
BIND_ENUM_CONSTANT(SUB_EMITTER_MAX);

BIND_ENUM_CONSTANT(COLLISION_DISABLED);
Expand Down Expand Up @@ -2361,6 +2392,7 @@ ParticleProcessMaterial::ParticleProcessMaterial() :
set_sub_emitter_frequency(4);
set_sub_emitter_amount_at_end(1);
set_sub_emitter_amount_at_collision(1);
set_sub_emitter_amount_at_start(1);
set_sub_emitter_keep_velocity(false);

set_attractor_interaction_enabled(true);
Expand Down
8 changes: 7 additions & 1 deletion scene/resources/particle_process_material.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class ParticleProcessMaterial : public Material {
SUB_EMITTER_CONSTANT,
SUB_EMITTER_AT_END,
SUB_EMITTER_AT_COLLISION,
SUB_EMITTER_AT_START,
SUB_EMITTER_MAX
};

Expand All @@ -117,7 +118,7 @@ class ParticleProcessMaterial : public Material {
uint64_t emission_shape : 3;
uint64_t invalid_key : 1;
uint64_t has_emission_color : 1;
uint64_t sub_emitter : 2;
uint64_t sub_emitter : 3;
uint64_t attractor_enabled : 1;
uint64_t collision_mode : 2;
uint64_t collision_scale : 1;
Expand Down Expand Up @@ -282,6 +283,7 @@ class ParticleProcessMaterial : public Material {
StringName sub_emitter_frequency;
StringName sub_emitter_amount_at_end;
StringName sub_emitter_amount_at_collision;
StringName sub_emitter_amount_at_start;
StringName sub_emitter_keep_velocity;

StringName collision_friction;
Expand Down Expand Up @@ -349,6 +351,7 @@ class ParticleProcessMaterial : public Material {
double sub_emitter_frequency = 0.0;
int sub_emitter_amount_at_end = 0;
int sub_emitter_amount_at_collision = 0;
int sub_emitter_amount_at_start = 0;
bool sub_emitter_keep_velocity = false;
//do not save emission points here

Expand Down Expand Up @@ -487,6 +490,9 @@ class ParticleProcessMaterial : public Material {
void set_sub_emitter_amount_at_collision(int p_amount);
int get_sub_emitter_amount_at_collision() const;

void set_sub_emitter_amount_at_start(int p_amount);
int get_sub_emitter_amount_at_start() const;

void set_sub_emitter_keep_velocity(bool p_enable);
bool get_sub_emitter_keep_velocity() const;

Expand Down

0 comments on commit 1e1f54e

Please sign in to comment.