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