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);