Skip to content

Commit eb5839d

Browse files
committed
Add "At Start" mode for sub-emitter particles
1 parent 1f47e4c commit eb5839d

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

doc/classes/ParticleProcessMaterial.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@
346346
The amount of particles to spawn from the subemitter node when the particle expires.
347347
[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.
348348
</member>
349+
<member name="sub_emitter_amount_at_start" type="int" setter="set_sub_emitter_amount_at_start" getter="get_sub_emitter_amount_at_start">
350+
The amount of particles to spawn from the subemitter node when the particle spawns.
351+
[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.
352+
</member>
349353
<member name="sub_emitter_frequency" type="float" setter="set_sub_emitter_frequency" getter="get_sub_emitter_frequency">
350354
The frequency at which particles should be emitted from the subemitter node. One particle will be spawned every [member sub_emitter_frequency] seconds.
351355
[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.
@@ -514,7 +518,9 @@
514518
</constant>
515519
<constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode">
516520
</constant>
517-
<constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode">
521+
<constant name="SUB_EMITTER_AT_START" value="4" enum="SubEmitterMode">
522+
</constant>
523+
<constant name="SUB_EMITTER_MAX" value="5" enum="SubEmitterMode">
518524
Represents the size of the [enum SubEmitterMode] enum.
519525
</constant>
520526
<constant name="COLLISION_DISABLED" value="0" enum="CollisionMode">

scene/resources/particle_process_material.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ void ParticleProcessMaterial::init_shaders() {
132132
shader_names->sub_emitter_frequency = "sub_emitter_frequency";
133133
shader_names->sub_emitter_amount_at_end = "sub_emitter_amount_at_end";
134134
shader_names->sub_emitter_amount_at_collision = "sub_emitter_amount_at_collision";
135+
shader_names->sub_emitter_amount_at_start = "sub_emitter_amount_at_start";
135136
shader_names->sub_emitter_keep_velocity = "sub_emitter_keep_velocity";
136137

137138
shader_names->collision_friction = "collision_friction";
@@ -287,6 +288,9 @@ void ParticleProcessMaterial::_update_shader() {
287288
if (sub_emitter_mode == SUB_EMITTER_AT_COLLISION) {
288289
code += "uniform int sub_emitter_amount_at_collision;\n";
289290
}
291+
if (sub_emitter_mode == SUB_EMITTER_AT_START) {
292+
code += "uniform int sub_emitter_amount_at_start;\n";
293+
}
290294
code += "uniform bool sub_emitter_keep_velocity;\n";
291295
}
292296

@@ -918,6 +922,10 @@ void ParticleProcessMaterial::_update_shader() {
918922
code += " float pi = 3.14159;\n";
919923
code += " float degree_to_rad = pi / 180.0;\n\n";
920924

925+
if (sub_emitter_mode == SUB_EMITTER_AT_START && !RenderingServer::get_singleton()->is_low_end()) {
926+
code += " bool just_spawned = CUSTOM.y == 0.0;\n";
927+
}
928+
921929
code += " CUSTOM.y += DELTA / LIFETIME;\n";
922930
code += " CUSTOM.y = mix(CUSTOM.y, 1.0, INTERPOLATE_TO_END);\n";
923931
code += " float lifetime_percent = CUSTOM.y / params.lifetime;\n";
@@ -1134,6 +1142,11 @@ void ParticleProcessMaterial::_update_shader() {
11341142
code += " emit_count = sub_emitter_amount_at_end;\n";
11351143
code += " }\n";
11361144
} break;
1145+
case SUB_EMITTER_AT_START: {
1146+
code += " if (just_spawned) {\n";
1147+
code += " emit_count = sub_emitter_amount_at_start;\n";
1148+
code += " }\n";
1149+
} break;
11371150
default: {
11381151
}
11391152
}
@@ -1819,6 +1832,10 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
18191832
p_property.usage = PROPERTY_USAGE_NONE;
18201833
}
18211834

1835+
if (p_property.name == "sub_emitter_amount_at_start" && sub_emitter_mode != SUB_EMITTER_AT_START) {
1836+
p_property.usage = PROPERTY_USAGE_NONE;
1837+
}
1838+
18221839
if (!turbulence_enabled) {
18231840
if (p_property.name == "turbulence_noise_strength" ||
18241841
p_property.name == "turbulence_noise_scale" ||
@@ -1893,6 +1910,15 @@ int ParticleProcessMaterial::get_sub_emitter_amount_at_collision() const {
18931910
return sub_emitter_amount_at_collision;
18941911
}
18951912

1913+
void ParticleProcessMaterial::set_sub_emitter_amount_at_start(int p_amount) {
1914+
sub_emitter_amount_at_start = p_amount;
1915+
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_start, p_amount);
1916+
}
1917+
1918+
int ParticleProcessMaterial::get_sub_emitter_amount_at_start() const {
1919+
return sub_emitter_amount_at_start;
1920+
}
1921+
18961922
void ParticleProcessMaterial::set_sub_emitter_keep_velocity(bool p_enable) {
18971923
sub_emitter_keep_velocity = p_enable;
18981924
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable);
@@ -2074,6 +2100,9 @@ void ParticleProcessMaterial::_bind_methods() {
20742100
ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_collision"), &ParticleProcessMaterial::get_sub_emitter_amount_at_collision);
20752101
ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_collision", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_collision);
20762102

2103+
ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_start"), &ParticleProcessMaterial::get_sub_emitter_amount_at_start);
2104+
ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_start", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_start);
2105+
20772106
ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticleProcessMaterial::get_sub_emitter_keep_velocity);
20782107
ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticleProcessMaterial::set_sub_emitter_keep_velocity);
20792108

@@ -2203,10 +2232,11 @@ void ParticleProcessMaterial::_bind_methods() {
22032232
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
22042233
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_scale"), "set_collision_use_scale", "is_collision_using_scale");
22052234
ADD_GROUP("Sub Emitter", "sub_emitter_");
2206-
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");
2235+
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");
22072236
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");
22082237
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");
22092238
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");
2239+
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");
22102240
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity");
22112241

22122242
BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY);
@@ -2249,6 +2279,7 @@ void ParticleProcessMaterial::_bind_methods() {
22492279
BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT);
22502280
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END);
22512281
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION);
2282+
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_START);
22522283
BIND_ENUM_CONSTANT(SUB_EMITTER_MAX);
22532284

22542285
BIND_ENUM_CONSTANT(COLLISION_DISABLED);
@@ -2320,6 +2351,7 @@ ParticleProcessMaterial::ParticleProcessMaterial() :
23202351
set_sub_emitter_frequency(4);
23212352
set_sub_emitter_amount_at_end(1);
23222353
set_sub_emitter_amount_at_collision(1);
2354+
set_sub_emitter_amount_at_start(1);
23232355
set_sub_emitter_keep_velocity(false);
23242356

23252357
set_attractor_interaction_enabled(true);

scene/resources/particle_process_material.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class ParticleProcessMaterial : public Material {
9696
SUB_EMITTER_CONSTANT,
9797
SUB_EMITTER_AT_END,
9898
SUB_EMITTER_AT_COLLISION,
99+
SUB_EMITTER_AT_START,
99100
SUB_EMITTER_MAX
100101
};
101102

@@ -117,7 +118,7 @@ class ParticleProcessMaterial : public Material {
117118
uint64_t emission_shape : 3;
118119
uint64_t invalid_key : 1;
119120
uint64_t has_emission_color : 1;
120-
uint64_t sub_emitter : 2;
121+
uint64_t sub_emitter : 3;
121122
uint64_t attractor_enabled : 1;
122123
uint64_t collision_mode : 2;
123124
uint64_t collision_scale : 1;
@@ -282,6 +283,7 @@ class ParticleProcessMaterial : public Material {
282283
StringName sub_emitter_frequency;
283284
StringName sub_emitter_amount_at_end;
284285
StringName sub_emitter_amount_at_collision;
286+
StringName sub_emitter_amount_at_start;
285287
StringName sub_emitter_keep_velocity;
286288

287289
StringName collision_friction;
@@ -349,6 +351,7 @@ class ParticleProcessMaterial : public Material {
349351
double sub_emitter_frequency = 0.0;
350352
int sub_emitter_amount_at_end = 0;
351353
int sub_emitter_amount_at_collision = 0;
354+
int sub_emitter_amount_at_start = 0;
352355
bool sub_emitter_keep_velocity = false;
353356
//do not save emission points here
354357

@@ -487,6 +490,9 @@ class ParticleProcessMaterial : public Material {
487490
void set_sub_emitter_amount_at_collision(int p_amount);
488491
int get_sub_emitter_amount_at_collision() const;
489492

493+
void set_sub_emitter_amount_at_start(int p_amount);
494+
int get_sub_emitter_amount_at_start() const;
495+
490496
void set_sub_emitter_keep_velocity(bool p_enable);
491497
bool get_sub_emitter_keep_velocity() const;
492498

0 commit comments

Comments
 (0)