Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_sprite_render/src/sprite_mesh/mod.rs
9353 views
1
use bevy_app::{Plugin, Update};
2
use bevy_ecs::{
3
entity::Entity,
4
query::{Added, Changed, Or},
5
schedule::IntoScheduleConfigs,
6
system::{Commands, Local, Query, Res, ResMut},
7
};
8
9
use bevy_asset::{Assets, Handle};
10
11
use bevy_image::TextureAtlasLayout;
12
use bevy_math::{primitives::Rectangle, vec2};
13
use bevy_mesh::{Mesh, Mesh2d};
14
15
use bevy_platform::collections::HashMap;
16
use bevy_sprite::{prelude::SpriteMesh, Anchor};
17
18
mod sprite_material;
19
pub use sprite_material::*;
20
21
use crate::MeshMaterial2d;
22
23
pub struct SpriteMeshPlugin;
24
25
impl Plugin for SpriteMeshPlugin {
26
fn build(&self, app: &mut bevy_app::App) {
27
app.add_plugins(SpriteMaterialPlugin);
28
29
app.add_systems(Update, (add_mesh, add_material).chain());
30
}
31
}
32
33
// Insert a Mesh2d quad each time the SpriteMesh component is added.
34
// The meshhandle is kept locally so they can be cloned.
35
fn add_mesh(
36
sprites: Query<Entity, Added<SpriteMesh>>,
37
mut meshes: ResMut<Assets<Mesh>>,
38
mut quad: Local<Option<Handle<Mesh>>>,
39
mut commands: Commands,
40
) {
41
if quad.is_none() {
42
*quad = Some(meshes.add(Rectangle::from_size(vec2(1.0, 1.0))));
43
}
44
for entity in sprites {
45
if let Some(quad) = quad.clone() {
46
commands.entity(entity).insert(Mesh2d(quad));
47
}
48
}
49
}
50
51
// Change the material when SpriteMesh is added / changed.
52
//
53
// NOTE: This also adds the SpriteAtlasLayout into the SpriteMaterial,
54
// but this should instead be read later, similar to the images, allowing
55
// for hot reload.
56
fn add_material(
57
sprites: Query<
58
(Entity, &SpriteMesh, &Anchor),
59
Or<(Changed<SpriteMesh>, Changed<Anchor>, Added<Mesh2d>)>,
60
>,
61
texture_atlas_layouts: Res<Assets<TextureAtlasLayout>>,
62
mut cached_materials: Local<HashMap<(SpriteMesh, Anchor), Handle<SpriteMaterial>>>,
63
mut materials: ResMut<Assets<SpriteMaterial>>,
64
mut commands: Commands,
65
) {
66
for (entity, sprite, anchor) in sprites {
67
if let Some(handle) = cached_materials.get(&(sprite.clone(), *anchor)) {
68
commands
69
.entity(entity)
70
.insert(MeshMaterial2d(handle.clone()));
71
} else {
72
let mut material = SpriteMaterial::from_sprite_mesh(sprite.clone());
73
material.anchor = **anchor;
74
75
if let Some(texture_atlas) = &sprite.texture_atlas
76
&& let Some(texture_atlas_layout) =
77
texture_atlas_layouts.get(texture_atlas.layout.id())
78
{
79
material.texture_atlas_layout = Some(texture_atlas_layout.clone());
80
material.texture_atlas_index = texture_atlas.index;
81
}
82
83
let handle = materials.add(material);
84
cached_materials.insert((sprite.clone(), *anchor), handle.clone());
85
86
commands
87
.entity(entity)
88
.insert(MeshMaterial2d(handle.clone()));
89
}
90
}
91
}
92
93