bevy_render/mesh/
components.rs

1use crate::{
2    mesh::Mesh,
3    view::{self, Visibility, VisibilityClass},
4};
5use bevy_asset::{AsAssetId, AssetEvent, AssetId, Handle};
6use bevy_derive::{Deref, DerefMut};
7use bevy_ecs::{
8    change_detection::DetectChangesMut, component::Component, event::EventReader,
9    reflect::ReflectComponent, system::Query,
10};
11use bevy_platform::{collections::HashSet, hash::FixedHasher};
12use bevy_reflect::{std_traits::ReflectDefault, Reflect};
13use bevy_transform::components::Transform;
14use derive_more::derive::From;
15
16/// A component for 2D meshes. Requires a [`MeshMaterial2d`] to be rendered, commonly using a [`ColorMaterial`].
17///
18/// [`MeshMaterial2d`]: <https://docs.rs/bevy/latest/bevy/sprite/struct.MeshMaterial2d.html>
19/// [`ColorMaterial`]: <https://docs.rs/bevy/latest/bevy/sprite/struct.ColorMaterial.html>
20///
21/// # Example
22///
23/// ```ignore
24/// # use bevy_sprite::{ColorMaterial, Mesh2d, MeshMaterial2d};
25/// # use bevy_ecs::prelude::*;
26/// # use bevy_render::mesh::Mesh;
27/// # use bevy_color::palettes::basic::RED;
28/// # use bevy_asset::Assets;
29/// # use bevy_math::primitives::Circle;
30/// #
31/// // Spawn an entity with a mesh using `ColorMaterial`.
32/// fn setup(
33///     mut commands: Commands,
34///     mut meshes: ResMut<Assets<Mesh>>,
35///     mut materials: ResMut<Assets<ColorMaterial>>,
36/// ) {
37///     commands.spawn((
38///         Mesh2d(meshes.add(Circle::new(50.0))),
39///         MeshMaterial2d(materials.add(ColorMaterial::from_color(RED))),
40///     ));
41/// }
42/// ```
43#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq, From)]
44#[reflect(Component, Default, Clone, PartialEq)]
45#[require(Transform, Visibility, VisibilityClass)]
46#[component(on_add = view::add_visibility_class::<Mesh2d>)]
47pub struct Mesh2d(pub Handle<Mesh>);
48
49impl From<Mesh2d> for AssetId<Mesh> {
50    fn from(mesh: Mesh2d) -> Self {
51        mesh.id()
52    }
53}
54
55impl From<&Mesh2d> for AssetId<Mesh> {
56    fn from(mesh: &Mesh2d) -> Self {
57        mesh.id()
58    }
59}
60
61impl AsAssetId for Mesh2d {
62    type Asset = Mesh;
63
64    fn as_asset_id(&self) -> AssetId<Self::Asset> {
65        self.id()
66    }
67}
68
69/// A component for 3D meshes. Requires a [`MeshMaterial3d`] to be rendered, commonly using a [`StandardMaterial`].
70///
71/// [`MeshMaterial3d`]: <https://docs.rs/bevy/latest/bevy/pbr/struct.MeshMaterial3d.html>
72/// [`StandardMaterial`]: <https://docs.rs/bevy/latest/bevy/pbr/struct.StandardMaterial.html>
73///
74/// # Example
75///
76/// ```ignore
77/// # use bevy_pbr::{Material, MeshMaterial3d, StandardMaterial};
78/// # use bevy_ecs::prelude::*;
79/// # use bevy_render::mesh::{Mesh, Mesh3d};
80/// # use bevy_color::palettes::basic::RED;
81/// # use bevy_asset::Assets;
82/// # use bevy_math::primitives::Capsule3d;
83/// #
84/// // Spawn an entity with a mesh using `StandardMaterial`.
85/// fn setup(
86///     mut commands: Commands,
87///     mut meshes: ResMut<Assets<Mesh>>,
88///     mut materials: ResMut<Assets<StandardMaterial>>,
89/// ) {
90///     commands.spawn((
91///         Mesh3d(meshes.add(Capsule3d::default())),
92///         MeshMaterial3d(materials.add(StandardMaterial {
93///             base_color: RED.into(),
94///             ..Default::default()
95///         })),
96///     ));
97/// }
98/// ```
99#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq, From)]
100#[reflect(Component, Default, Clone, PartialEq)]
101#[require(Transform, Visibility, VisibilityClass)]
102#[component(on_add = view::add_visibility_class::<Mesh3d>)]
103pub struct Mesh3d(pub Handle<Mesh>);
104
105impl From<Mesh3d> for AssetId<Mesh> {
106    fn from(mesh: Mesh3d) -> Self {
107        mesh.id()
108    }
109}
110
111impl From<&Mesh3d> for AssetId<Mesh> {
112    fn from(mesh: &Mesh3d) -> Self {
113        mesh.id()
114    }
115}
116
117impl AsAssetId for Mesh3d {
118    type Asset = Mesh;
119
120    fn as_asset_id(&self) -> AssetId<Self::Asset> {
121        self.id()
122    }
123}
124
125/// A system that marks a [`Mesh3d`] as changed if the associated [`Mesh`] asset
126/// has changed.
127///
128/// This is needed because the systems that extract meshes, such as
129/// `extract_meshes_for_gpu_building`, write some metadata about the mesh (like
130/// the location within each slab) into the GPU structures that they build that
131/// needs to be kept up to date if the contents of the mesh change.
132pub fn mark_3d_meshes_as_changed_if_their_assets_changed(
133    mut meshes_3d: Query<&mut Mesh3d>,
134    mut mesh_asset_events: EventReader<AssetEvent<Mesh>>,
135) {
136    let mut changed_meshes: HashSet<AssetId<Mesh>, FixedHasher> = HashSet::default();
137    for mesh_asset_event in mesh_asset_events.read() {
138        if let AssetEvent::Modified { id } = mesh_asset_event {
139            changed_meshes.insert(*id);
140        }
141    }
142
143    if changed_meshes.is_empty() {
144        return;
145    }
146
147    for mut mesh_3d in &mut meshes_3d {
148        if changed_meshes.contains(&mesh_3d.0.id()) {
149            mesh_3d.set_changed();
150        }
151    }
152}
153
154/// A component that stores an arbitrary index used to identify the mesh instance when rendering.
155#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)]
156#[reflect(Component, Default, Clone, PartialEq)]
157pub struct MeshTag(pub u32);