Skip to main content

bevy_mesh/
components.rs

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