Add emission shape ring for CPUParticles2D

Particles will be emitted in the area of a ring parameterized by its
outer and inner radius. The distribution is uniform across the area.
This commit is contained in:
Benny Smit 2024-07-30 09:27:32 +02:00 committed by Benedict Smit
parent 514c564a8c
commit 2109b80b67
3 changed files with 56 additions and 3 deletions

View File

@ -162,6 +162,12 @@
<member name="emission_rect_extents" type="Vector2" setter="set_emission_rect_extents" getter="get_emission_rect_extents"> <member name="emission_rect_extents" type="Vector2" setter="set_emission_rect_extents" getter="get_emission_rect_extents">
The rectangle's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_RECTANGLE]. The rectangle's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_RECTANGLE].
</member> </member>
<member name="emission_ring_inner_radius" type="float" setter="set_emission_ring_inner_radius" getter="get_emission_ring_inner_radius">
The ring's inner radius if [member emission_shape] is set to [constant EMISSION_SHAPE_RING].
</member>
<member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius">
The ring's outer radius if [member emission_shape] is set to [constant EMISSION_SHAPE_RING].
</member>
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="CPUParticles2D.EmissionShape" default="0"> <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="CPUParticles2D.EmissionShape" default="0">
Particles will be emitted inside this region. See [enum EmissionShape] for possible values. Particles will be emitted inside this region. See [enum EmissionShape] for possible values.
</member> </member>
@ -368,7 +374,10 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="5" enum="EmissionShape"> <constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="5" enum="EmissionShape">
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors]. Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors].
</constant> </constant>
<constant name="EMISSION_SHAPE_MAX" value="6" enum="EmissionShape"> <constant name="EMISSION_SHAPE_RING" value="6" enum="EmissionShape">
Particles will be emitted in the area of a ring parameterized by its outer and inner radius.
</constant>
<constant name="EMISSION_SHAPE_MAX" value="7" enum="EmissionShape">
Represents the size of the [enum EmissionShape] enum. Represents the size of the [enum EmissionShape] enum.
</constant> </constant>
</constants> </constants>

View File

@ -448,6 +448,13 @@ void CPUParticles2D::set_emission_colors(const Vector<Color> &p_colors) {
emission_colors = p_colors; emission_colors = p_colors;
} }
void CPUParticles2D::set_emission_ring_inner_radius(real_t p_inner_radius) {
emission_ring_inner_radius = p_inner_radius;
}
void CPUParticles2D::set_emission_ring_radius(real_t p_ring_radius) {
emission_ring_radius = p_ring_radius;
}
real_t CPUParticles2D::get_emission_sphere_radius() const { real_t CPUParticles2D::get_emission_sphere_radius() const {
return emission_sphere_radius; return emission_sphere_radius;
} }
@ -468,6 +475,13 @@ Vector<Color> CPUParticles2D::get_emission_colors() const {
return emission_colors; return emission_colors;
} }
real_t CPUParticles2D::get_emission_ring_inner_radius() const {
return emission_ring_inner_radius;
}
real_t CPUParticles2D::get_emission_ring_radius() const {
return emission_ring_radius;
}
CPUParticles2D::EmissionShape CPUParticles2D::get_emission_shape() const { CPUParticles2D::EmissionShape CPUParticles2D::get_emission_shape() const {
return emission_shape; return emission_shape;
} }
@ -532,6 +546,13 @@ void CPUParticles2D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name.begins_with("scale_curve_") && !split_scale) { if (p_property.name.begins_with("scale_curve_") && !split_scale) {
p_property.usage = PROPERTY_USAGE_NONE; p_property.usage = PROPERTY_USAGE_NONE;
} }
if (p_property.name == "emission_ring_inner_radius" && emission_shape != EMISSION_SHAPE_RING) {
p_property.usage = PROPERTY_USAGE_NONE;
}
if (p_property.name == "emission_ring_radius" && emission_shape != EMISSION_SHAPE_RING) {
p_property.usage = PROPERTY_USAGE_NONE;
}
} }
static uint32_t idhash(uint32_t x) { static uint32_t idhash(uint32_t x) {
@ -798,6 +819,13 @@ void CPUParticles2D::_particles_process(double p_delta) {
p.base_color = emission_colors.get(random_idx); p.base_color = emission_colors.get(random_idx);
} }
} break; } break;
case EMISSION_SHAPE_RING: {
real_t t = Math_TAU * Math::randf();
real_t outer_sq = emission_ring_radius * emission_ring_radius;
real_t inner_sq = emission_ring_inner_radius * emission_ring_inner_radius;
real_t radius = Math::sqrt(Math::randf() * (outer_sq - inner_sq) + inner_sq);
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
} break;
case EMISSION_SHAPE_MAX: { // Max value for validity check. case EMISSION_SHAPE_MAX: { // Max value for validity check.
break; break;
} }
@ -1353,6 +1381,12 @@ void CPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles2D::set_emission_colors); ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles2D::set_emission_colors);
ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles2D::get_emission_colors); ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles2D::get_emission_colors);
ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &CPUParticles2D::set_emission_ring_inner_radius);
ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &CPUParticles2D::get_emission_ring_inner_radius);
ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &CPUParticles2D::set_emission_ring_radius);
ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &CPUParticles2D::get_emission_ring_radius);
ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles2D::get_gravity); ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles2D::get_gravity);
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles2D::set_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles2D::set_gravity);
@ -1370,12 +1404,14 @@ void CPUParticles2D::_bind_methods() {
ADD_SIGNAL(MethodInfo("finished")); ADD_SIGNAL(MethodInfo("finished"));
ADD_GROUP("Emission Shape", "emission_"); ADD_GROUP("Emission Shape", "emission_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Rectangle,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Sphere Surface,Rectangle,Points,Directed Points,Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,suffix:px"), "set_emission_sphere_radius", "get_emission_sphere_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,suffix:px"), "set_emission_sphere_radius", "get_emission_sphere_radius");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents", PROPERTY_HINT_NONE, "suffix:px"), "set_emission_rect_extents", "get_emission_rect_extents"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents", PROPERTY_HINT_NONE, "suffix:px"), "set_emission_rect_extents", "get_emission_rect_extents");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_points"), "set_emission_points", "get_emission_points"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius");
ADD_GROUP("Particle Flags", "particle_flag_"); ADD_GROUP("Particle Flags", "particle_flag_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
ADD_GROUP("Direction", ""); ADD_GROUP("Direction", "");
@ -1464,6 +1500,7 @@ void CPUParticles2D::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE); BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
} }

View File

@ -73,7 +73,8 @@ public:
EMISSION_SHAPE_RECTANGLE, EMISSION_SHAPE_RECTANGLE,
EMISSION_SHAPE_POINTS, EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS, EMISSION_SHAPE_DIRECTED_POINTS,
EMISSION_SHAPE_MAX EMISSION_SHAPE_RING,
EMISSION_SHAPE_MAX,
}; };
private: private:
@ -169,6 +170,8 @@ private:
Vector<Vector2> emission_normals; Vector<Vector2> emission_normals;
Vector<Color> emission_colors; Vector<Color> emission_colors;
int emission_point_count = 0; int emission_point_count = 0;
real_t emission_ring_inner_radius = 0.8;
real_t emission_ring_radius = 1.0;
Ref<Curve> scale_curve_x; Ref<Curve> scale_curve_x;
Ref<Curve> scale_curve_y; Ref<Curve> scale_curve_y;
@ -265,6 +268,8 @@ public:
void set_emission_points(const Vector<Vector2> &p_points); void set_emission_points(const Vector<Vector2> &p_points);
void set_emission_normals(const Vector<Vector2> &p_normals); void set_emission_normals(const Vector<Vector2> &p_normals);
void set_emission_colors(const Vector<Color> &p_colors); void set_emission_colors(const Vector<Color> &p_colors);
void set_emission_ring_inner_radius(real_t p_inner_radius);
void set_emission_ring_radius(real_t p_ring_radius);
void set_scale_curve_x(Ref<Curve> p_scale_curve); void set_scale_curve_x(Ref<Curve> p_scale_curve);
void set_scale_curve_y(Ref<Curve> p_scale_curve); void set_scale_curve_y(Ref<Curve> p_scale_curve);
void set_split_scale(bool p_split_scale); void set_split_scale(bool p_split_scale);
@ -275,6 +280,8 @@ public:
Vector<Vector2> get_emission_points() const; Vector<Vector2> get_emission_points() const;
Vector<Vector2> get_emission_normals() const; Vector<Vector2> get_emission_normals() const;
Vector<Color> get_emission_colors() const; Vector<Color> get_emission_colors() const;
real_t get_emission_ring_inner_radius() const;
real_t get_emission_ring_radius() const;
Ref<Curve> get_scale_curve_x() const; Ref<Curve> get_scale_curve_x() const;
Ref<Curve> get_scale_curve_y() const; Ref<Curve> get_scale_curve_y() const;
bool get_split_scale(); bool get_split_scale();