Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ratio to cpu particles to dynamically change amount emitted #70145

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/classes/CPUParticles2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
Number of particles emitted in one emission cycle.
</member>
<member name="amount_ratio" type="float" setter="set_amount_ratio" getter="get_amount_ratio" default="1.0">
Amount Ratio multiplied by [member amount] is how many particles will be emmitted each cycle. This value is to be adjusted while emitting particles as it will not clear the existing particles.
When not used leave this ratio at 1 and adjust amount accordingly.
Comment on lines +93 to +94
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve documentation to match my GPUParticles branch:

Suggested change
Amount Ratio multiplied by [member amount] is how many particles will be emmitted each cycle. This value is to be adjusted while emitting particles as it will not clear the existing particles.
When not used leave this ratio at 1 and adjust amount accordingly.
The ratio of particles that should actually be emitted. If set to a value lower than [code]1.0[/code], this will set the amount of emitted particles throughout the lifetime to [code]amount * amount_ratio[/code]. Unlike changing [member amount], changing [member amount_ratio] while emitting does not affect already-emitted particles and doesn't cause the particle system to restart. [member amount_ratio] can be used to create effects that make the number of emitted particles vary over time.
[b]Note:[/b] If you don't need to change the number of particles emitted while particles are emitting, keep [member amount_ratio] at [code]1.0[/code] and change [member amount] instead. This will result in better performance, as inactive particles still need to be partially evaluated in the shader otherwise.

Setting this value to zero will clear [member emitting] flag, increasing it from zero will set emitting.
</member>
<member name="angle_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
Each particle's rotation will be animated along this [Curve].
</member>
Expand Down
5 changes: 5 additions & 0 deletions doc/classes/CPUParticles3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
Number of particles emitted in one emission cycle.
</member>
<member name="amount_ratio" type="float" setter="set_amount_ratio" getter="get_amount_ratio" default="1.0">
Amount Ratio multiplied by [member amount] is how many particles will be emmitted each cycle. This value is to be adjusted while emitting particles as it will not clear the existing particles.
When not used leave this ratio at 1 and adjust amount accordingly.
Comment on lines +92 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Amount Ratio multiplied by [member amount] is how many particles will be emmitted each cycle. This value is to be adjusted while emitting particles as it will not clear the existing particles.
When not used leave this ratio at 1 and adjust amount accordingly.
The ratio of particles that should actually be emitted. If set to a value lower than [code]1.0[/code], this will set the amount of emitted particles throughout the lifetime to [code]amount * amount_ratio[/code]. Unlike changing [member amount], changing [member amount_ratio] while emitting does not affect already-emitted particles and doesn't cause the particle system to restart. [member amount_ratio] can be used to create effects that make the number of emitted particles vary over time.
[b]Note:[/b] If you don't need to change the number of particles emitted while particles are emitting, keep [member amount_ratio] at [code]1.0[/code] and change [member amount] instead. This will result in better performance, as inactive particles still need to be partially evaluated in the shader otherwise.

Setting this value to zero will clear [member emitting] flag, increasing it from zero will set emitting.
</member>
<member name="angle_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
Each particle's rotation will be animated along this [Curve].
</member>
Expand Down
44 changes: 44 additions & 0 deletions scene/2d/cpu_particles_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,32 @@ void CPUParticles2D::set_amount(int p_amount) {
RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true);

particle_order.resize(p_amount);
set_amount_ratio(amount_ratio);
}

void CPUParticles2D::set_amount_ratio(float p_amount_ratio) {
if (p_amount_ratio == 0) {
set_emitting(false);
} else if (!emitting && amount_ratio == 0) {
set_emitting(true);
}

amount_ratio = p_amount_ratio;

float tot = 1;
KoBeWi marked this conversation as resolved.
Show resolved Hide resolved
int pcount = particles.size();
Particle *w = particles.ptrw();

for (int i = 0; i < pcount; i++) {
tot += amount_ratio;
w[i].stopped = false;
if (tot >= 1) {
w[i].stopping = false;
tot -= 1;
} else {
w[i].stopping = true;
}
}
}

void CPUParticles2D::set_lifetime(double p_lifetime) {
Expand Down Expand Up @@ -105,6 +131,10 @@ int CPUParticles2D::get_amount() const {
return particles.size();
}

float CPUParticles2D::get_amount_ratio() const {
return amount_ratio;
}

double CPUParticles2D::get_lifetime() const {
return lifetime;
}
Expand Down Expand Up @@ -653,6 +683,10 @@ void CPUParticles2D::_particles_process(double p_delta) {
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];

if (p.stopped) {
continue;
}

if (!emitting && !p.active) {
continue;
}
Expand Down Expand Up @@ -711,6 +745,12 @@ void CPUParticles2D::_particles_process(double p_delta) {
float tv = 0.0;

if (restart) {
if (p.stopping) {
p.stopped = true;
p.active = false;
continue;
}

if (!emitting) {
p.active = false;
continue;
Expand Down Expand Up @@ -1249,6 +1289,7 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) {
void CPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles2D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles2D::set_amount);
ClassDB::bind_method(D_METHOD("set_amount_ratio", "amount_ratio"), &CPUParticles2D::set_amount_ratio);
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles2D::set_lifetime);
ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles2D::set_one_shot);
ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles2D::set_pre_process_time);
Expand All @@ -1262,6 +1303,7 @@ void CPUParticles2D::_bind_methods() {

ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles2D::get_amount);
ClassDB::bind_method(D_METHOD("get_amount_ratio"), &CPUParticles2D::get_amount_ratio);
ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles2D::get_lifetime);
ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles2D::get_one_shot);
ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles2D::get_pre_process_time);
Expand All @@ -1284,6 +1326,7 @@ void CPUParticles2D::_bind_methods() {

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_amount_ratio", "get_amount_ratio");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,suffix:s"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
Expand Down Expand Up @@ -1469,6 +1512,7 @@ CPUParticles2D::CPUParticles2D() {

set_emitting(true);
set_amount(8);
set_amount_ratio(1);
set_use_local_coordinates(false);

set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
Expand Down
5 changes: 5 additions & 0 deletions scene/2d/cpu_particles_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class CPUParticles2D : public Node2D {
real_t rotation = 0.0;
Vector2 velocity;
bool active = false;
bool stopping = false;
bool stopped = false;
real_t angle_rand = 0.0;
real_t scale_rand = 0.0;
real_t hue_rot_rand = 0.0;
Expand Down Expand Up @@ -131,6 +133,7 @@ class CPUParticles2D : public Node2D {

bool one_shot = false;

float amount_ratio = 1;
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t explosiveness_ratio = 0.0;
Expand Down Expand Up @@ -198,6 +201,7 @@ class CPUParticles2D : public Node2D {
public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
void set_amount_ratio(float p_amount_ratio);
void set_lifetime(double p_lifetime);
void set_one_shot(bool p_one_shot);
void set_pre_process_time(double p_time);
Expand All @@ -209,6 +213,7 @@ class CPUParticles2D : public Node2D {

bool is_emitting() const;
int get_amount() const;
float get_amount_ratio() const;
double get_lifetime() const;
bool get_one_shot() const;
double get_pre_process_time() const;
Expand Down
44 changes: 44 additions & 0 deletions scene/3d/cpu_particles_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,32 @@ void CPUParticles3D::set_amount(int p_amount) {
RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);

particle_order.resize(p_amount);
set_amount_ratio(amount_ratio);
}

void CPUParticles3D::set_amount_ratio(float p_amount_ratio) {
if (p_amount_ratio == 0) {
set_emitting(false);
} else if (!emitting && amount_ratio == 0) {
set_emitting(true);
}

amount_ratio = p_amount_ratio;

float tot = 1;
int pcount = particles.size();
Particle *w = particles.ptrw();

for (int i = 0; i < pcount; i++) {
tot += amount_ratio;
w[i].stopped = false;
if (tot >= 1) {
w[i].stopping = false;
tot -= 1;
} else {
w[i].stopping = true;
}
}
}

void CPUParticles3D::set_lifetime(double p_lifetime) {
Expand Down Expand Up @@ -116,6 +142,10 @@ int CPUParticles3D::get_amount() const {
return particles.size();
}

float CPUParticles3D::get_amount_ratio() const {
return amount_ratio;
}

double CPUParticles3D::get_lifetime() const {
return lifetime;
}
Expand Down Expand Up @@ -673,6 +703,10 @@ void CPUParticles3D::_particles_process(double p_delta) {
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];

if (p.stopped) {
continue;
}

if (!emitting && !p.active) {
continue;
}
Expand Down Expand Up @@ -731,6 +765,12 @@ void CPUParticles3D::_particles_process(double p_delta) {
float tv = 0.0;

if (restart) {
if (p.stopping) {
p.stopped = true;
p.active = false;
continue;
}

if (!emitting) {
p.active = false;
continue;
Expand Down Expand Up @@ -1410,6 +1450,7 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) {
void CPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles3D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles3D::set_amount);
ClassDB::bind_method(D_METHOD("set_amount_ratio", "amount_ratio"), &CPUParticles3D::set_amount_ratio);
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles3D::set_lifetime);
ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles3D::set_one_shot);
ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles3D::set_pre_process_time);
Expand All @@ -1423,6 +1464,7 @@ void CPUParticles3D::_bind_methods() {

ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles3D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles3D::get_amount);
ClassDB::bind_method(D_METHOD("get_amount_ratio"), &CPUParticles3D::get_amount_ratio);
ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles3D::get_lifetime);
ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles3D::get_one_shot);
ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles3D::get_pre_process_time);
Expand All @@ -1445,6 +1487,7 @@ void CPUParticles3D::_bind_methods() {

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_amount_ratio", "get_amount_ratio");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
Expand Down Expand Up @@ -1658,6 +1701,7 @@ CPUParticles3D::CPUParticles3D() {

set_emitting(true);
set_amount(8);
set_amount_ratio(1);

set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param_min(PARAM_ANGULAR_VELOCITY, 0);
Expand Down
5 changes: 5 additions & 0 deletions scene/3d/cpu_particles_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class CPUParticles3D : public GeometryInstance3D {
real_t custom[4] = {};
Vector3 velocity;
bool active = false;
bool stopping = false;
bool stopped = false;
real_t angle_rand = 0.0;
real_t scale_rand = 0.0;
real_t hue_rot_rand = 0.0;
Expand Down Expand Up @@ -132,6 +134,7 @@ class CPUParticles3D : public GeometryInstance3D {

bool one_shot = false;

float amount_ratio = 1;
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t explosiveness_ratio = 0.0;
Expand Down Expand Up @@ -205,6 +208,7 @@ class CPUParticles3D : public GeometryInstance3D {

void set_emitting(bool p_emitting);
void set_amount(int p_amount);
void set_amount_ratio(float p_amount_ratio);
void set_lifetime(double p_lifetime);
void set_one_shot(bool p_one_shot);
void set_pre_process_time(double p_time);
Expand All @@ -216,6 +220,7 @@ class CPUParticles3D : public GeometryInstance3D {

bool is_emitting() const;
int get_amount() const;
float get_amount_ratio() const;
double get_lifetime() const;
bool get_one_shot() const;
double get_pre_process_time() const;
Expand Down