Skip to content

Commit

Permalink
Implementing Reflect on *MeshBuilder types (#17600)
Browse files Browse the repository at this point in the history
# Objective

- Most of the `*MeshBuilder` classes are not implementing `Reflect`

## Solution

- Implementing `Reflect` for all `*MeshBuilder` were is possible.
- Make sure all `*MeshBuilder` implements `Default`.
- Adding new `MeshBuildersPlugin` that registers all `*MeshBuilder`
types.

## Testing

- `cargo run -p ci`
- Tested some examples like `3d_scene` just in case something was
broken.
  • Loading branch information
eckz authored Feb 3, 2025
1 parent f22ea72 commit b978b13
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 17 deletions.
60 changes: 54 additions & 6 deletions crates/bevy_mesh/src/primitives/dim2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ use bevy_math::{
},
FloatExt, Vec2,
};
use bevy_reflect::prelude::*;
use wgpu_types::PrimitiveTopology;

/// A builder used for creating a [`Mesh`] with a [`Circle`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct CircleMeshBuilder {
/// The [`Circle`] shape.
pub circle: Circle,
Expand Down Expand Up @@ -98,7 +100,8 @@ impl From<Circle> for Mesh {
/// It's expected that more will be added in the future, such as a variant that causes the texture to be
/// scaled to fit the bounding box of the shape, which would be good for packed textures only including the
/// portion of the circle that is needed to display.
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Reflect)]
#[reflect(Default, Debug)]
#[non_exhaustive]
pub enum CircularMeshUvMode {
/// Treats the shape as a mask over a circle of equal size and radius,
Expand All @@ -119,7 +122,8 @@ impl Default for CircularMeshUvMode {
///
/// The resulting mesh will have a UV-map such that the center of the circle is
/// at the center of the texture.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct CircularSectorMeshBuilder {
/// The sector shape.
pub sector: CircularSector,
Expand Down Expand Up @@ -256,7 +260,8 @@ impl From<CircularSector> for Mesh {
///
/// The resulting mesh will have a UV-map such that the center of the circle is
/// at the center of the texture.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct CircularSegmentMeshBuilder {
/// The segment shape.
pub segment: CircularSegment,
Expand Down Expand Up @@ -402,6 +407,8 @@ impl From<CircularSegment> for Mesh {
///
/// You must verify that the `vertices` are not concave when constructing this type. You can
/// guarantee this by creating a [`ConvexPolygon`] first, then calling [`ConvexPolygon::mesh()`].
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Debug)]
pub struct ConvexPolygonMeshBuilder<const N: usize> {
pub vertices: [Vec2; N],
}
Expand Down Expand Up @@ -451,11 +458,23 @@ impl<const N: usize> From<ConvexPolygon<N>> for Mesh {
}

/// A builder used for creating a [`Mesh`] with a [`RegularPolygon`] shape.
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct RegularPolygonMeshBuilder {
circumradius: f32,
sides: u32,
}

impl Default for RegularPolygonMeshBuilder {
/// Returns the default [`RegularPolygonMeshBuilder`] with six sides (a hexagon) and a circumradius of `0.5`.
fn default() -> Self {
Self {
circumradius: 0.5,
sides: 6,
}
}
}

impl RegularPolygonMeshBuilder {
/// Creates a new [`RegularPolygonMeshBuilder`] from the radius of a circumcircle and a number
/// of sides.
Expand Down Expand Up @@ -513,7 +532,8 @@ impl From<RegularPolygon> for Mesh {
}

/// A builder used for creating a [`Mesh`] with an [`Ellipse`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct EllipseMeshBuilder {
/// The [`Ellipse`] shape.
pub ellipse: Ellipse,
Expand Down Expand Up @@ -617,6 +637,8 @@ impl From<Ellipse> for Mesh {
}

/// A builder for creating a [`Mesh`] with an [`Annulus`] shape.
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct AnnulusMeshBuilder {
/// The [`Annulus`] shape.
pub annulus: Annulus,
Expand Down Expand Up @@ -747,10 +769,22 @@ impl From<Annulus> for Mesh {
}
}

/// A builder for creating a [`Mesh`] with an [`Rhombus`] shape.
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct RhombusMeshBuilder {
half_diagonals: Vec2,
}

impl Default for RhombusMeshBuilder {
/// Returns the default [`RhombusMeshBuilder`] with a half-horizontal and half-vertical diagonal of `0.5`.
fn default() -> Self {
Self {
half_diagonals: Vec2::splat(0.5),
}
}
}

impl RhombusMeshBuilder {
/// Creates a new [`RhombusMeshBuilder`] from a horizontal and vertical diagonal size.
///
Expand Down Expand Up @@ -822,6 +856,8 @@ impl From<Rhombus> for Mesh {
}

/// A builder used for creating a [`Mesh`] with a [`Triangle2d`] shape.
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub struct Triangle2dMeshBuilder {
triangle: Triangle2d,
}
Expand Down Expand Up @@ -897,10 +933,21 @@ impl From<Triangle2d> for Mesh {
}

/// A builder used for creating a [`Mesh`] with a [`Rectangle`] shape.
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct RectangleMeshBuilder {
half_size: Vec2,
}

impl Default for RectangleMeshBuilder {
/// Returns the default [`RectangleMeshBuilder`] with a half-width and half-height of `0.5`.
fn default() -> Self {
Self {
half_size: Vec2::splat(0.5),
}
}
}

impl RectangleMeshBuilder {
/// Creates a new [`RectangleMeshBuilder`] from a full width and height.
///
Expand Down Expand Up @@ -966,7 +1013,8 @@ impl From<Rectangle> for Mesh {
}

/// A builder used for creating a [`Mesh`] with a [`Capsule2d`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct Capsule2dMeshBuilder {
/// The [`Capsule2d`] shape.
pub capsule: Capsule2d,
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_mesh/src/primitives/dim3/capsule.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::Capsule3d, Vec2, Vec3};
use bevy_reflect::prelude::*;

/// Manner in which UV coordinates are distributed vertically.
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub enum CapsuleUvProfile {
/// UV space is distributed by how much of the capsule consists of the hemispheres.
#[default]
Expand All @@ -16,7 +18,8 @@ pub enum CapsuleUvProfile {
}

/// A builder used for creating a [`Mesh`] with a [`Capsule3d`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct Capsule3dMeshBuilder {
/// The [`Capsule3d`] shape.
pub capsule: Capsule3d,
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_mesh/src/primitives/dim3/cone.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::Cone, Vec3};
use bevy_reflect::prelude::*;

/// Anchoring options for [`ConeMeshBuilder`]
#[derive(Debug, Copy, Clone, Default)]
#[derive(Debug, Copy, Clone, Default, Reflect)]
#[reflect(Default, Debug)]
pub enum ConeAnchor {
#[default]
/// Midpoint between the tip of the cone and the center of its base.
Expand All @@ -15,7 +17,8 @@ pub enum ConeAnchor {
}

/// A builder used for creating a [`Mesh`] with a [`Cone`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct ConeMeshBuilder {
/// The [`Cone`] shape.
pub cone: Cone,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_mesh/src/primitives/dim3/conical_frustum.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::ConicalFrustum, Vec3};
use bevy_reflect::prelude::*;

/// A builder used for creating a [`Mesh`] with a [`ConicalFrustum`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct ConicalFrustumMeshBuilder {
/// The [`ConicalFrustum`] shape.
pub frustum: ConicalFrustum,
Expand Down
12 changes: 12 additions & 0 deletions crates/bevy_mesh/src/primitives/dim3/cuboid.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{primitives::Cuboid, Vec3};
use bevy_reflect::prelude::*;

/// A builder used for creating a [`Mesh`] with a [`Cuboid`] shape.
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct CuboidMeshBuilder {
half_size: Vec3,
}

impl Default for CuboidMeshBuilder {
/// Returns the default [`CuboidMeshBuilder`] with a width, height, and depth of `1.0`.
fn default() -> Self {
Self {
half_size: Vec3::splat(0.5),
}
}
}

impl MeshBuilder for CuboidMeshBuilder {
fn build(&self) -> Mesh {
let min = -self.half_size;
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_mesh/src/primitives/dim3/cylinder.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::Cylinder};
use bevy_reflect::prelude::*;

/// Anchoring options for [`CylinderMeshBuilder`]
#[derive(Debug, Copy, Clone, Default)]
#[derive(Debug, Copy, Clone, Default, Reflect)]
#[reflect(Default, Debug)]
pub enum CylinderAnchor {
#[default]
/// Midpoint between the top and bottom caps of the cylinder
Expand All @@ -15,7 +17,8 @@ pub enum CylinderAnchor {
}

/// A builder used for creating a [`Mesh`] with a [`Cylinder`] shape.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct CylinderMeshBuilder {
/// The [`Cylinder`] shape.
pub cylinder: Cylinder,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_mesh/src/primitives/dim3/plane.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};
use bevy_reflect::prelude::*;

/// A builder used for creating a [`Mesh`] with a [`Plane3d`] shape.
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub struct PlaneMeshBuilder {
/// The [`Plane3d`] shape.
pub plane: Plane3d,
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_mesh/src/primitives/dim3/sphere.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::Sphere};
use bevy_reflect::prelude::*;
use core::f32::consts::PI;
use hexasphere::shapes::IcoSphere;
use thiserror::Error;
Expand All @@ -19,7 +20,8 @@ pub enum IcosphereError {
}

/// A type of sphere mesh.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Reflect)]
#[reflect(Default, Debug)]
pub enum SphereKind {
/// An icosphere, a spherical mesh that consists of similar sized triangles.
Ico {
Expand All @@ -46,7 +48,8 @@ impl Default for SphereKind {
}

/// A builder used for creating a [`Mesh`] with an [`Sphere`] shape.
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub struct SphereMeshBuilder {
/// The [`Sphere`] shape.
pub sphere: Sphere,
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_mesh/src/primitives/dim3/tetrahedron.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use super::triangle3d;
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::primitives::{Tetrahedron, Triangle3d};
use bevy_reflect::prelude::*;

/// A builder used for creating a [`Mesh`] with a [`Tetrahedron`] shape.
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub struct TetrahedronMeshBuilder {
tetrahedron: Tetrahedron,
}
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_mesh/src/primitives/dim3/torus.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{ops, primitives::Torus, Vec3};
use bevy_reflect::prelude::*;
use core::ops::RangeInclusive;

/// A builder used for creating a [`Mesh`] with a [`Torus`] shape.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Reflect)]
#[reflect(Default, Debug)]
pub struct TorusMeshBuilder {
/// The [`Torus`] shape.
pub torus: Torus,
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_mesh/src/primitives/dim3/triangle3d.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
use bevy_asset::RenderAssetUsages;
use bevy_math::{primitives::Triangle3d, Vec3};
use bevy_reflect::prelude::*;

/// A builder used for creating a [`Mesh`] with a [`Triangle3d`] shape.
#[derive(Clone, Copy, Debug, Default, Reflect)]
#[reflect(Default, Debug)]
pub struct Triangle3dMeshBuilder {
triangle: Triangle3d,
}
Expand Down
31 changes: 31 additions & 0 deletions crates/bevy_render/src/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ use bevy_ecs::{
pub use components::{mark_3d_meshes_as_changed_if_their_assets_changed, Mesh2d, Mesh3d};
use wgpu::IndexFormat;

/// Registers all [`MeshBuilder`] types.
pub struct MeshBuildersPlugin;

impl Plugin for MeshBuildersPlugin {
fn build(&self, app: &mut App) {
// 2D Mesh builders
app.register_type::<CircleMeshBuilder>()
.register_type::<CircularSectorMeshBuilder>()
.register_type::<CircularSegmentMeshBuilder>()
.register_type::<RegularPolygonMeshBuilder>()
.register_type::<EllipseMeshBuilder>()
.register_type::<AnnulusMeshBuilder>()
.register_type::<RhombusMeshBuilder>()
.register_type::<Triangle2dMeshBuilder>()
.register_type::<RectangleMeshBuilder>()
.register_type::<Capsule2dMeshBuilder>()
// 3D Mesh builders
.register_type::<Capsule3dMeshBuilder>()
.register_type::<ConeMeshBuilder>()
.register_type::<ConicalFrustumMeshBuilder>()
.register_type::<CuboidMeshBuilder>()
.register_type::<CylinderMeshBuilder>()
.register_type::<PlaneMeshBuilder>()
.register_type::<SphereMeshBuilder>()
.register_type::<TetrahedronMeshBuilder>()
.register_type::<TorusMeshBuilder>()
.register_type::<Triangle3dMeshBuilder>();
}
}

/// Adds the [`Mesh`] as an asset and makes sure that they are extracted and prepared for the GPU.
pub struct MeshPlugin;

Expand All @@ -35,6 +65,7 @@ impl Plugin for MeshPlugin {
.register_type::<Mesh3d>()
.register_type::<skinning::SkinnedMesh>()
.register_type::<Vec<Entity>>()
.add_plugins(MeshBuildersPlugin)
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
.add_plugins(RenderAssetPlugin::<RenderMesh, GpuImage>::default())
.add_plugins(MeshAllocatorPlugin)
Expand Down

0 comments on commit b978b13

Please sign in to comment.