Path: blob/main/crates/bevy_sprite_render/src/sprite_mesh/mod.rs
9353 views
use bevy_app::{Plugin, Update};1use bevy_ecs::{2entity::Entity,3query::{Added, Changed, Or},4schedule::IntoScheduleConfigs,5system::{Commands, Local, Query, Res, ResMut},6};78use bevy_asset::{Assets, Handle};910use bevy_image::TextureAtlasLayout;11use bevy_math::{primitives::Rectangle, vec2};12use bevy_mesh::{Mesh, Mesh2d};1314use bevy_platform::collections::HashMap;15use bevy_sprite::{prelude::SpriteMesh, Anchor};1617mod sprite_material;18pub use sprite_material::*;1920use crate::MeshMaterial2d;2122pub struct SpriteMeshPlugin;2324impl Plugin for SpriteMeshPlugin {25fn build(&self, app: &mut bevy_app::App) {26app.add_plugins(SpriteMaterialPlugin);2728app.add_systems(Update, (add_mesh, add_material).chain());29}30}3132// Insert a Mesh2d quad each time the SpriteMesh component is added.33// The meshhandle is kept locally so they can be cloned.34fn add_mesh(35sprites: Query<Entity, Added<SpriteMesh>>,36mut meshes: ResMut<Assets<Mesh>>,37mut quad: Local<Option<Handle<Mesh>>>,38mut commands: Commands,39) {40if quad.is_none() {41*quad = Some(meshes.add(Rectangle::from_size(vec2(1.0, 1.0))));42}43for entity in sprites {44if let Some(quad) = quad.clone() {45commands.entity(entity).insert(Mesh2d(quad));46}47}48}4950// Change the material when SpriteMesh is added / changed.51//52// NOTE: This also adds the SpriteAtlasLayout into the SpriteMaterial,53// but this should instead be read later, similar to the images, allowing54// for hot reload.55fn add_material(56sprites: Query<57(Entity, &SpriteMesh, &Anchor),58Or<(Changed<SpriteMesh>, Changed<Anchor>, Added<Mesh2d>)>,59>,60texture_atlas_layouts: Res<Assets<TextureAtlasLayout>>,61mut cached_materials: Local<HashMap<(SpriteMesh, Anchor), Handle<SpriteMaterial>>>,62mut materials: ResMut<Assets<SpriteMaterial>>,63mut commands: Commands,64) {65for (entity, sprite, anchor) in sprites {66if let Some(handle) = cached_materials.get(&(sprite.clone(), *anchor)) {67commands68.entity(entity)69.insert(MeshMaterial2d(handle.clone()));70} else {71let mut material = SpriteMaterial::from_sprite_mesh(sprite.clone());72material.anchor = **anchor;7374if let Some(texture_atlas) = &sprite.texture_atlas75&& let Some(texture_atlas_layout) =76texture_atlas_layouts.get(texture_atlas.layout.id())77{78material.texture_atlas_layout = Some(texture_atlas_layout.clone());79material.texture_atlas_index = texture_atlas.index;80}8182let handle = materials.add(material);83cached_materials.insert((sprite.clone(), *anchor), handle.clone());8485commands86.entity(entity)87.insert(MeshMaterial2d(handle.clone()));88}89}90}919293