From ec9ca078bc78b031ce6f695317a9c461c2b4a3ac Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 18 Dec 2022 02:58:39 +1100 Subject: [PATCH] Add circle emission shape with random and ordered emission mode --- doc/classes/CPUParticles2D.xml | 17 ++++++++++++++- scene/2d/cpu_particles_2d.cpp | 40 ++++++++++++++++++++++++++++++++-- scene/2d/cpu_particles_2d.h | 11 ++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index 314e46d9d018..cbabec07fc7a 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -150,6 +150,9 @@ Particle draw order. Uses [enum DrawOrder] values. + + The order [enum EmissionCircleMode] in which points are emitted for [constant EMISSION_SHAPE_CIRCLE] + Sets the [Color]s to modulate particles by when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS]. @@ -361,8 +364,20 @@ 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 from a circle of [member emission_sphere_radius] radius. + + Represents the size of the [enum EmissionShape] enum. + + Particles emitted in random order + + + Particles emitted in a clockwise order + + + Particles emitted in a counter clockwise order + diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index c6296f4732e4..3d6d5f193b85 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -426,6 +426,10 @@ void CPUParticles2D::set_emission_shape(EmissionShape p_shape) { notify_property_list_changed(); } +void CPUParticles2D::set_emission_circle_mode(EmissionCircleMode p_circle_mode) { + emission_circle_mode = p_circle_mode; +} + void CPUParticles2D::set_emission_sphere_radius(real_t p_radius) { emission_sphere_radius = p_radius; } @@ -470,6 +474,10 @@ CPUParticles2D::EmissionShape CPUParticles2D::get_emission_shape() const { return emission_shape; } +CPUParticles2D::EmissionCircleMode CPUParticles2D::get_emission_circle_mode() const { + return emission_circle_mode; +} + void CPUParticles2D::set_gravity(const Vector2 &p_gravity) { gravity = p_gravity; } @@ -504,7 +512,11 @@ bool CPUParticles2D::get_split_scale() { } void CPUParticles2D::_validate_property(PropertyInfo &p_property) const { - if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { + if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE && emission_shape != EMISSION_SHAPE_CIRCLE)) { + p_property.usage = PROPERTY_USAGE_NONE; + } + + if (p_property.name == "emission_circle_mode" && emission_shape != EMISSION_SHAPE_CIRCLE) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -770,6 +782,21 @@ void CPUParticles2D::_particles_process(double p_delta) { real_t radius = emission_sphere_radius * Math::randf(); p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius; } break; + case EMISSION_SHAPE_CIRCLE: { + real_t t = 0; + switch (emission_circle_mode) { + case EMISSION_CIRCLE_MODE_RANDOM: { + t = Math_TAU * Math::randf(); + } break; + case EMISSION_CIRCLE_MODE_CW: { + t = Math_TAU * (i / float(pcount)); + } break; + case EMISSION_CIRCLE_MODE_CCW: { + t = Math_TAU * (1 - i / float(pcount)); + } break; + } + p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * emission_sphere_radius; + } break; case EMISSION_SHAPE_SPHERE_SURFACE: { real_t s = Math::randf(), t = Math_TAU * Math::randf(); real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s); @@ -1335,6 +1362,9 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles2D::set_emission_shape); ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles2D::get_emission_shape); + ClassDB::bind_method(D_METHOD("set_emission_circle_mode", "mode"), &CPUParticles2D::set_emission_circle_mode); + ClassDB::bind_method(D_METHOD("get_emission_circle_mode"), &CPUParticles2D::get_emission_circle_mode); + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &CPUParticles2D::set_emission_sphere_radius); ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &CPUParticles2D::get_emission_sphere_radius); @@ -1365,8 +1395,9 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles); 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,Circle", 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::INT, "emission_circle_mode", PROPERTY_HINT_ENUM, "Random,Clockwise,Counter Clockwise", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_circle_mode", "get_emission_circle_mode"); 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_normals"), "set_emission_normals", "get_emission_normals"); @@ -1459,7 +1490,12 @@ void CPUParticles2D::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_CIRCLE); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + + BIND_ENUM_CONSTANT(EMISSION_CIRCLE_MODE_RANDOM); + BIND_ENUM_CONSTANT(EMISSION_CIRCLE_MODE_CW); + BIND_ENUM_CONSTANT(EMISSION_CIRCLE_MODE_CCW); } CPUParticles2D::CPUParticles2D() { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 141e5f913942..92916cafbb13 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -73,9 +73,16 @@ class CPUParticles2D : public Node2D { EMISSION_SHAPE_RECTANGLE, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_CIRCLE, EMISSION_SHAPE_MAX }; + enum EmissionCircleMode { + EMISSION_CIRCLE_MODE_RANDOM, + EMISSION_CIRCLE_MODE_CW, + EMISSION_CIRCLE_MODE_CCW, + }; + private: bool emitting = false; @@ -163,6 +170,7 @@ class CPUParticles2D : public Node2D { bool particle_flags[PARTICLE_FLAG_MAX]; EmissionShape emission_shape = EMISSION_SHAPE_POINT; + EmissionCircleMode emission_circle_mode = EMISSION_CIRCLE_MODE_RANDOM; real_t emission_sphere_radius = 1.0; Vector2 emission_rect_extents = Vector2(1, 1); Vector emission_points; @@ -260,6 +268,7 @@ class CPUParticles2D : public Node2D { bool get_particle_flag(ParticleFlags p_particle_flag) const; void set_emission_shape(EmissionShape p_shape); + void set_emission_circle_mode(EmissionCircleMode p_circle_mode); void set_emission_sphere_radius(real_t p_radius); void set_emission_rect_extents(Vector2 p_extents); void set_emission_points(const Vector &p_points); @@ -270,6 +279,7 @@ class CPUParticles2D : public Node2D { void set_split_scale(bool p_split_scale); EmissionShape get_emission_shape() const; + EmissionCircleMode get_emission_circle_mode() const; real_t get_emission_sphere_radius() const; Vector2 get_emission_rect_extents() const; Vector get_emission_points() const; @@ -296,5 +306,6 @@ VARIANT_ENUM_CAST(CPUParticles2D::DrawOrder) VARIANT_ENUM_CAST(CPUParticles2D::Parameter) VARIANT_ENUM_CAST(CPUParticles2D::ParticleFlags) VARIANT_ENUM_CAST(CPUParticles2D::EmissionShape) +VARIANT_ENUM_CAST(CPUParticles2D::EmissionCircleMode) #endif // CPU_PARTICLES_2D_H