From 3af20b9bdf43c1cc276680e342e59d0a2e5509a5 Mon Sep 17 00:00:00 2001 From: QbieShay Date: Sun, 11 Apr 2021 18:08:28 +0200 Subject: [PATCH] Added ring emitter for 3D particles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commits adds a new emitter type for particles material and 3D CPU particles. The new emitter is called "ring" and it can emit either in a ring or cylinder fashion. This adds the following properties for the emitter: 1. ring_emitter_axis: the axis along which the ring/cylinder will be constructed 2. ring_emitter_radius: outer radius of the ring/cylinder 3. ring_emitter_inner_radius: inner radius of the cylinder. when set to zero, particles will emit in the full volume. 4. ring_emitter_height: height of the ring/cylinder emitter. Co-authored-by: RĂ©mi Verschelde --- doc/classes/CPUParticles.xml | 21 +++++- doc/classes/ParticlesMaterial.xml | 17 ++++- scene/3d/cpu_particles.cpp | 80 ++++++++++++++++++++- scene/3d/cpu_particles.h | 13 ++++ scene/resources/particles_material.cpp | 98 +++++++++++++++++++++++++- scene/resources/particles_material.h | 17 +++++ 6 files changed, 238 insertions(+), 8 deletions(-) diff --git a/doc/classes/CPUParticles.xml b/doc/classes/CPUParticles.xml index dc7596298b5..eca76c107bd 100644 --- a/doc/classes/CPUParticles.xml +++ b/doc/classes/CPUParticles.xml @@ -173,15 +173,27 @@ The rectangle's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_BOX]. - + Sets the [Color]s to modulate particles by when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS]. Sets the direction the particles will be emitted in when using [constant EMISSION_SHAPE_DIRECTED_POINTS]. - + Sets the initial positions to spawn particles when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS]. + + The axis for the ring shaped emitter when using [constant EMISSION_SHAPE_RING]. + + + The height for the ring shaped emitter when using [constant EMISSION_SHAPE_RING]. + + + The inner radius for the ring shaped emitter when using [constant EMISSION_SHAPE_RING]. + + + The radius for the ring shaped emitter when using [constant EMISSION_SHAPE_RING]. + Particles will be emitted inside this region. See [enum EmissionShape] for possible values. @@ -380,7 +392,10 @@ 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 in a ring or cylinder. + + Represents the size of the [enum EmissionShape] enum. diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index f83f3754437..4252bf55027 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -164,6 +164,18 @@ Particles will be emitted at positions determined by sampling this texture at a random position. Used with [constant EMISSION_SHAPE_POINTS] and [constant EMISSION_SHAPE_DIRECTED_POINTS]. Can be created automatically from mesh or node by selecting "Create Emission Points from Mesh/Node" under the "Particles" tool in the toolbar. + + The axis of the ring when using the emitter [constant EMISSION_SHAPE_RING]. + + + The height of the ring when using the emitter [constant EMISSION_SHAPE_RING]. + + + The inner radius of the ring when using the emitter [constant EMISSION_SHAPE_RING]. + + + The radius of the ring when using the emitter [constant EMISSION_SHAPE_RING]. + Particles will be emitted inside this region. Use [enum EmissionShape] constants for values. @@ -329,7 +341,10 @@ Particles will be emitted at a position determined by sampling a random point on the [member emission_point_texture]. Particle velocity and rotation will be set based on [member emission_normal_texture]. Particle color will be modulated by [member emission_color_texture]. - + + Particles will be emitted in a ring or cylinder. + + Represents the size of the [enum EmissionShape] enum. diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 9f0d8d79768..fd8b6d0d977 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -389,6 +389,21 @@ void CPUParticles::set_emission_normals(const PoolVector &p_normals) { void CPUParticles::set_emission_colors(const PoolVector &p_colors) { emission_colors = p_colors; } +void CPUParticles::set_emission_ring_height(float p_height) { + emission_ring_height = p_height; +} + +void CPUParticles::set_emission_ring_radius(float p_radius) { + emission_ring_radius = p_radius; +} + +void CPUParticles::set_emission_ring_inner_radius(float p_offset) { + emission_ring_inner_radius = p_offset; +} + +void CPUParticles::set_emission_ring_axis(Vector3 p_axis) { + emission_ring_axis = p_axis; +} float CPUParticles::get_emission_sphere_radius() const { return emission_sphere_radius; @@ -407,6 +422,22 @@ PoolVector CPUParticles::get_emission_colors() const { return emission_colors; } +float CPUParticles::get_emission_ring_height() const { + return emission_ring_height; +} + +float CPUParticles::get_emission_ring_inner_radius() const { + return emission_ring_inner_radius; +} + +float CPUParticles::get_emission_ring_radius() const { + return emission_ring_radius; +} + +Vector3 CPUParticles::get_emission_ring_axis() const { + return emission_ring_axis; +} + CPUParticles::EmissionShape CPUParticles::get_emission_shape() const { return emission_shape; } @@ -431,7 +462,7 @@ void CPUParticles::_validate_property(PropertyInfo &property) const { property.usage = 0; } - if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { + if ((property.name == "emission_points" || property.name == "emission_colors") && (emission_shape != EMISSION_SHAPE_POINTS) && (emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { property.usage = 0; } @@ -439,6 +470,10 @@ void CPUParticles::_validate_property(PropertyInfo &property) const { property.usage = 0; } + if (property.name.begins_with("emission_ring") && emission_shape != EMISSION_SHAPE_RING) { + property.usage = 0; + } + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { property.usage = 0; } @@ -734,6 +769,21 @@ void CPUParticles::_particles_process(float p_delta) { p.base_color = emission_colors.get(random_idx); } } break; + case EMISSION_SHAPE_RING: { + float ring_random_angle = Math::randf() * 2.0 * Math_PI; + float ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius; + Vector3 axis = emission_ring_axis.normalized(); + Vector3 ortho_axis = Vector3(); + if (axis == Vector3(1.0, 0.0, 0.0)) { + ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis); + } else { + ortho_axis = Vector3(1.0, 0.0, 0.0).cross(axis); + } + ortho_axis = ortho_axis.normalized(); + ortho_axis.rotate(axis, ring_random_angle); + ortho_axis = ortho_axis.normalized(); + p.transform.origin = ortho_axis * ring_random_radius + (Math::randf() * emission_ring_height - emission_ring_height / 2.0) * axis; + } case EMISSION_SHAPE_MAX: { // Max value for validity check. break; } @@ -1194,6 +1244,10 @@ void CPUParticles::convert_from_particles(Node *p_particles) { set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); set_emission_box_extents(material->get_emission_box_extents()); + set_emission_ring_height(material->get_emission_ring_height()); + set_emission_ring_inner_radius(material->get_emission_ring_inner_radius()); + set_emission_ring_radius(material->get_emission_ring_radius()); + set_emission_ring_axis(material->get_emission_ring_axis()); set_gravity(material->get_gravity()); set_lifetime_randomness(material->get_lifetime_randomness()); @@ -1327,6 +1381,18 @@ void CPUParticles::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles::set_emission_colors); ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles::get_emission_colors); + ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &CPUParticles::set_emission_ring_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &CPUParticles::get_emission_ring_radius); + + ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "offset"), &CPUParticles::set_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &CPUParticles::get_emission_ring_inner_radius); + + ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &CPUParticles::set_emission_ring_height); + ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &CPUParticles::get_emission_ring_height); + + ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &CPUParticles::set_emission_ring_axis); + ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &CPUParticles::get_emission_ring_axis); + ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles::set_gravity); @@ -1335,12 +1401,17 @@ void CPUParticles::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_render_thread"), &CPUParticles::_update_render_thread); ADD_GROUP("Emission Shape", "emission_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,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,Box,Points,Directed Points, Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals"); ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_radius", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater"), "set_emission_ring_radius", "get_emission_ring_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_inner_radius", PROPERTY_HINT_RANGE, "0.0,1000,0.01,or_greater"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_height", PROPERTY_HINT_RANGE, "0.0,100,0.01,or_greater"), "set_emission_ring_height", "get_emission_ring_height"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_ring_axis"), "set_emission_ring_axis", "get_emission_ring_axis"); + ADD_GROUP("Flags", "flag_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_particle_flag", "get_particle_flag", FLAG_ROTATE_Y); @@ -1426,6 +1497,7 @@ void CPUParticles::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); } @@ -1476,6 +1548,10 @@ CPUParticles::CPUParticles() { set_emission_shape(EMISSION_SHAPE_POINT); set_emission_sphere_radius(1); set_emission_box_extents(Vector3(1, 1, 1)); + set_emission_ring_height(1.0); + set_emission_ring_radius(1.0); + set_emission_ring_inner_radius(0.0); + set_emission_ring_axis(Vector3(0.0, 0.0, 1.0)); set_gravity(Vector3(0, -9.8, 0)); diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 625e15fefd6..77153cdd57a 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -77,6 +77,7 @@ public: EMISSION_SHAPE_BOX, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_RING, EMISSION_SHAPE_MAX }; @@ -172,6 +173,10 @@ private: PoolVector emission_normals; PoolVector emission_colors; int emission_point_count; + float emission_ring_height; + float emission_ring_inner_radius; + float emission_ring_radius; + Vector3 emission_ring_axis; Vector3 gravity; @@ -269,6 +274,10 @@ public: void set_emission_normals(const PoolVector &p_normals); void set_emission_colors(const PoolVector &p_colors); void set_emission_point_count(int p_count); + void set_emission_ring_height(float p_height); + void set_emission_ring_inner_radius(float p_inner_radius); + void set_emission_ring_radius(float p_radius); + void set_emission_ring_axis(Vector3 p_axis); EmissionShape get_emission_shape() const; float get_emission_sphere_radius() const; @@ -277,6 +286,10 @@ public: PoolVector get_emission_normals() const; PoolVector get_emission_colors() const; int get_emission_point_count() const; + float get_emission_ring_height() const; + float get_emission_ring_inner_radius() const; + float get_emission_ring_radius() const; + Vector3 get_emission_ring_axis() const; void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index beb2a5fb2cd..d523f9b066e 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -90,6 +90,10 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_texture_points = "emission_texture_points"; shader_names->emission_texture_normal = "emission_texture_normal"; shader_names->emission_texture_color = "emission_texture_color"; + shader_names->emission_ring_height = "ring_height"; + shader_names->emission_ring_inner_radius = "ring_inner_radius"; + shader_names->emission_ring_radius = "ring_radius"; + shader_names->emission_ring_axis = "ring_axis"; shader_names->trail_divisor = "trail_divisor"; shader_names->trail_size_modifier = "trail_size_modifier"; @@ -187,6 +191,12 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D emission_texture_color : hint_white;\n"; } } break; + case EMISSION_SHAPE_RING: { + code += "uniform float ring_radius = 2.0;\n"; + code += "uniform float ring_height = 1.0;\n"; + code += "uniform float ring_inner_radius = 0.0;\n"; + code += "uniform vec3 ring_axis = vec3(0.0, 0.0, 1.0);\n"; + } break; case EMISSION_SHAPE_MAX: { // Max value for validity check. break; } @@ -379,6 +389,28 @@ void ParticlesMaterial::_update_shader() { } } } break; + case EMISSION_SHAPE_RING: { + code += " float ring_spawn_angle = rand_from_seed(alt_seed) * 2.0 * pi;\n"; + code += " float ring_random_radius = rand_from_seed(alt_seed) * (ring_radius - ring_inner_radius) + ring_inner_radius;\n"; + code += " vec3 axis = normalize(ring_axis);\n"; + code += " vec3 ortho_axis = vec3(0.0);\n"; + code += " if (axis == vec3(1.0, 0.0, 0.0)) {\n"; + code += " ortho_axis = cross(axis, vec3(0.0, 1.0, 0.0));\n"; + code += " } else {\n"; + code += " ortho_axis = cross(axis, vec3(1.0, 0.0, 0.0));\n"; + code += " }\n"; + code += " ortho_axis = normalize(ortho_axis);\n"; + code += " float s = sin(ring_spawn_angle);\n"; + code += " float c = cos(ring_spawn_angle);\n"; + code += " float oc = 1.0 - c;\n"; + code += " ortho_axis = mat3(\n"; + code += " vec3(c + axis.x * axis.x * oc, axis.x * axis.y * oc - axis.z * s, axis.x * axis.z *oc + axis.y * s),\n"; + code += " vec3(axis.x * axis.y * oc + s * axis.z, c + axis.y * axis.y * oc, axis.y * axis.z * oc - axis.x * s),\n"; + code += " vec3(axis.z * axis.x * oc - axis.y * s, axis.z * axis.y * oc + axis.x * s, c + axis.z * axis.z * oc)\n"; + code += " ) * ortho_axis;\n"; + code += " ortho_axis = normalize(ortho_axis);\n"; + code += " TRANSFORM[3].xyz = ortho_axis * ring_random_radius + (rand_from_seed(alt_seed) * ring_height - ring_height / 2.0) * axis;\n"; + } break; case EMISSION_SHAPE_MAX: { // Max value for validity check. break; } @@ -932,6 +964,26 @@ void ParticlesMaterial::set_emission_point_count(int p_count) { VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); } +void ParticlesMaterial::set_emission_ring_height(float p_height) { + emission_ring_height = p_height; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_height, p_height); +} + +void ParticlesMaterial::set_emission_ring_radius(float p_radius) { + emission_ring_radius = p_radius; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_radius, p_radius); +} + +void ParticlesMaterial::set_emission_ring_inner_radius(float p_offset) { + emission_ring_inner_radius = p_offset; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_inner_radius, p_offset); +} + +void ParticlesMaterial::set_emission_ring_axis(Vector3 p_axis) { + emission_ring_axis = p_axis; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_axis, p_axis); +} + ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { return emission_shape; } @@ -957,6 +1009,22 @@ int ParticlesMaterial::get_emission_point_count() const { return emission_point_count; } +float ParticlesMaterial::get_emission_ring_height() const { + return emission_ring_height; +} + +float ParticlesMaterial::get_emission_ring_inner_radius() const { + return emission_ring_inner_radius; +} + +float ParticlesMaterial::get_emission_ring_radius() const { + return emission_ring_radius; +} + +Vector3 ParticlesMaterial::get_emission_ring_axis() const { + return emission_ring_axis; +} + void ParticlesMaterial::set_trail_divisor(int p_divisor) { trail_divisor = p_divisor; VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); @@ -1032,7 +1100,7 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } - if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { + if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape != EMISSION_SHAPE_POINTS) && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { property.usage = 0; } @@ -1044,6 +1112,10 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } + if ((property.name == "emission_ring_radius" || property.name == "emission_ring_height" || property.name == "emission_ring_inner_radius") && emission_shape != EMISSION_SHAPE_RING) { + property.usage = 0; + } + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { property.usage = 0; } @@ -1102,6 +1174,18 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticlesMaterial::set_emission_ring_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticlesMaterial::get_emission_ring_radius); + + ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "offset"), &ParticlesMaterial::set_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius); + + ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticlesMaterial::set_emission_ring_height); + ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticlesMaterial::get_emission_ring_height); + + ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticlesMaterial::set_emission_ring_axis); + ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticlesMaterial::get_emission_ring_axis); + ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); @@ -1124,13 +1208,18 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); ADD_GROUP("Emission Shape", "emission_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points,Ring"), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_color_texture", "get_emission_color_texture"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_radius", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater"), "set_emission_ring_radius", "get_emission_ring_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_inner_radius", PROPERTY_HINT_RANGE, "0.0,1000,0.01,or_greater"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_ring_height", PROPERTY_HINT_RANGE, "0.0,100,0.01,or_greater"), "set_emission_ring_height", "get_emission_ring_height"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_ring_axis"), "set_emission_ring_axis", "get_emission_ring_axis"); + ADD_GROUP("Flags", "flag_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_flag", "get_flag", FLAG_ROTATE_Y); @@ -1216,6 +1305,7 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); } @@ -1243,6 +1333,10 @@ ParticlesMaterial::ParticlesMaterial() : set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); emission_point_count = 1; + set_emission_ring_height(1.0); + set_emission_ring_inner_radius(0.0); + set_emission_ring_radius(2.0); + set_emission_ring_axis(Vector3(0.0, 0.0, 1.0)); for (int i = 0; i < PARAM_MAX; i++) { set_param_randomness(Parameter(i), 0); diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index a25f0191b04..a964eb379a4 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -68,6 +68,7 @@ public: EMISSION_SHAPE_BOX, EMISSION_SHAPE_POINTS, EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_RING, EMISSION_SHAPE_MAX }; @@ -177,6 +178,10 @@ private: StringName emission_texture_points; StringName emission_texture_normal; StringName emission_texture_color; + StringName emission_ring_radius; + StringName emission_ring_inner_radius; + StringName emission_ring_height; + StringName emission_ring_axis; StringName trail_divisor; StringName trail_size_modifier; @@ -215,6 +220,10 @@ private: Ref emission_normal_texture; Ref emission_color_texture; int emission_point_count; + float emission_ring_height; + float emission_ring_radius; + float emission_ring_inner_radius; + Vector3 emission_ring_axis; bool anim_loop; @@ -268,6 +277,10 @@ public: void set_emission_normal_texture(const Ref &p_normals); void set_emission_color_texture(const Ref &p_colors); void set_emission_point_count(int p_count); + void set_emission_ring_radius(float p_radius); + void set_emission_ring_inner_radius(float p_offset); + void set_emission_ring_height(float p_height); + void set_emission_ring_axis(Vector3 p_axis); EmissionShape get_emission_shape() const; float get_emission_sphere_radius() const; @@ -276,6 +289,10 @@ public: Ref get_emission_normal_texture() const; Ref get_emission_color_texture() const; int get_emission_point_count() const; + float get_emission_ring_radius() const; + float get_emission_ring_inner_radius() const; + float get_emission_ring_height() const; + Vector3 get_emission_ring_axis() const; void set_trail_divisor(int p_divisor); int get_trail_divisor() const;