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