Skip to content

Commit

Permalink
Sprite textures is now an enum
Browse files Browse the repository at this point in the history
  • Loading branch information
ManevilleF committed Jun 22, 2022
1 parent 86dd6f0 commit e94650f
Show file tree
Hide file tree
Showing 22 changed files with 104 additions and 151 deletions.
42 changes: 5 additions & 37 deletions crates/bevy_sprite/src/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,15 @@
use crate::{
texture_atlas::{TextureAtlas, TextureAtlasSprite},
Sprite,
};
use bevy_asset::Handle;
use crate::{Sprite, SpriteImage};
use bevy_ecs::bundle::Bundle;
use bevy_render::{
texture::{Image, DEFAULT_IMAGE_HANDLE},
view::Visibility,
};
use bevy_render::view::Visibility;
use bevy_transform::components::{GlobalTransform, Transform};

#[derive(Bundle, Clone)]
#[derive(Bundle, Clone, Default)]
pub struct SpriteBundle {
pub sprite: Sprite,
pub transform: Transform,
pub global_transform: GlobalTransform,
pub texture: Handle<Image>,
/// User indication of whether an entity is visible
pub visibility: Visibility,
}

impl Default for SpriteBundle {
fn default() -> Self {
Self {
sprite: Default::default(),
transform: Default::default(),
global_transform: Default::default(),
texture: DEFAULT_IMAGE_HANDLE.typed(),
visibility: Default::default(),
}
}
}
/// A Bundle of components for drawing a single sprite from a sprite sheet (also referred
/// to as a `TextureAtlas`)
#[derive(Bundle, Clone, Default)]
pub struct SpriteSheetBundle {
/// The specific sprite from the texture atlas to be drawn
pub sprite: TextureAtlasSprite,
/// A handle to the texture atlas that holds the sprite images
pub texture_atlas: Handle<TextureAtlas>,
/// Data pertaining to how the sprite is drawn on the screen
pub transform: Transform,
pub global_transform: GlobalTransform,
/// The sprite texture
pub texture: SpriteImage,
/// User indication of whether an entity is visible
pub visibility: Visibility,
}
31 changes: 31 additions & 0 deletions crates/bevy_sprite/src/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::TextureAtlas;
use bevy_asset::Handle;
use bevy_ecs::component::Component;
use bevy_reflect::Reflect;
use bevy_render::texture::{Image, DEFAULT_IMAGE_HANDLE};

/// The sprite texture
#[derive(Component, Clone, Debug, Reflect)]
pub enum SpriteImage {
/// Single texture
Image(Handle<Image>),
/// Texture atlas.
TextureAtlas {
/// Texture atlas handle
handle: Handle<TextureAtlas>,
/// Texture atlas index
index: usize,
},
}

impl Default for SpriteImage {
fn default() -> Self {
Self::Image(DEFAULT_IMAGE_HANDLE.typed())
}
}

impl From<Handle<Image>> for SpriteImage {
fn from(handle: Handle<Image>) -> Self {
Self::Image(handle)
}
}
6 changes: 3 additions & 3 deletions crates/bevy_sprite/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod bundle;
mod dynamic_texture_atlas_builder;
mod image;
mod mesh2d;
mod rect;
mod render;
Expand All @@ -12,15 +13,14 @@ pub mod collide_aabb;
pub mod prelude {
#[doc(hidden)]
pub use crate::{
bundle::{SpriteBundle, SpriteSheetBundle},
sprite::Sprite,
texture_atlas::{TextureAtlas, TextureAtlasSprite},
bundle::SpriteBundle, image::SpriteImage, sprite::Sprite, texture_atlas::TextureAtlas,
ColorMaterial, ColorMesh2dBundle, TextureAtlasBuilder,
};
}

pub use bundle::*;
pub use dynamic_texture_atlas_builder::*;
pub use image::*;
pub use mesh2d::*;
pub use rect::*;
pub use render::*;
Expand Down
54 changes: 20 additions & 34 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::cmp::Ordering;

use crate::{
texture_atlas::{TextureAtlas, TextureAtlasSprite},
Rect, Sprite, SPRITE_SHADER_HANDLE,
};
use crate::{texture_atlas::TextureAtlas, Rect, Sprite, SpriteImage, SPRITE_SHADER_HANDLE};
use bevy_asset::{AssetEvent, Assets, Handle, HandleId};
use bevy_core_pipeline::core_2d::Transparent2d;
use bevy_ecs::{
Expand Down Expand Up @@ -224,54 +221,43 @@ pub fn extract_sprite_events(
pub fn extract_sprites(
mut render_world: ResMut<RenderWorld>,
texture_atlases: Res<Assets<TextureAtlas>>,
sprite_query: Query<(&Visibility, &Sprite, &GlobalTransform, &Handle<Image>)>,
atlas_query: Query<(
&Visibility,
&TextureAtlasSprite,
&GlobalTransform,
&Handle<TextureAtlas>,
)>,
sprite_query: Query<(&Visibility, &Sprite, &GlobalTransform, &SpriteImage)>,
) {
let mut extracted_sprites = render_world.resource_mut::<ExtractedSprites>();
extracted_sprites.sprites.clear();
for (visibility, sprite, transform, handle) in sprite_query.iter() {
for (visibility, sprite, transform, image) in sprite_query.iter() {
if !visibility.is_visible {
continue;
}

let (rect, image_handle_id) = match image {
SpriteImage::Image(handle) => (None, handle.id),
SpriteImage::TextureAtlas { handle, index } => {
if let Some(atlas) = texture_atlases.get(handle) {
let rect = atlas.textures.get(*index).copied().unwrap_or_else(|| {
panic!("TextureAtlas {:?} as no texture at index {}", atlas, index)
});
(Some(rect), atlas.texture.id)
} else {
// Skip loading images
continue;
}
}
};
// PERF: we don't check in this function that the `Image` asset is ready, since it should be in most cases and hashing the handle is expensive
extracted_sprites.sprites.alloc().init(ExtractedSprite {
color: sprite.color,
transform: *transform,
// Use the full texture
rect: None,
rect,
// Pass the custom size
custom_size: sprite.custom_size,
flip_x: sprite.flip_x,
flip_y: sprite.flip_y,
image_handle_id: handle.id,
image_handle_id,
anchor: sprite.anchor.as_vec(),
});
}
for (visibility, atlas_sprite, transform, texture_atlas_handle) in atlas_query.iter() {
if !visibility.is_visible {
continue;
}
if let Some(texture_atlas) = texture_atlases.get(texture_atlas_handle) {
let rect = Some(texture_atlas.textures[atlas_sprite.index as usize]);
extracted_sprites.sprites.alloc().init(ExtractedSprite {
color: atlas_sprite.color,
transform: *transform,
// Select the area in the texture atlas
rect,
// Pass the custom size
custom_size: atlas_sprite.custom_size,
flip_x: atlas_sprite.flip_x,
flip_y: atlas_sprite.flip_y,
image_handle_id: texture_atlas.texture.id,
anchor: atlas_sprite.anchor.as_vec(),
});
}
}
}

#[repr(C)]
Expand Down
41 changes: 3 additions & 38 deletions crates/bevy_sprite/src/texture_atlas.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use crate::{Anchor, Rect};
use crate::Rect;
use bevy_asset::Handle;
use bevy_ecs::component::Component;
use bevy_math::Vec2;
use bevy_reflect::{Reflect, TypeUuid};
use bevy_render::{color::Color, texture::Image};
use bevy_reflect::TypeUuid;
use bevy_render::texture::Image;
use bevy_utils::HashMap;

/// An atlas containing multiple textures (like a spritesheet or a tilemap).
Expand All @@ -21,40 +20,6 @@ pub struct TextureAtlas {
pub texture_handles: Option<HashMap<Handle<Image>, usize>>,
}

#[derive(Component, Debug, Clone, Reflect)]
pub struct TextureAtlasSprite {
pub color: Color,
pub index: usize,
pub flip_x: bool,
pub flip_y: bool,
/// An optional custom size for the sprite that will be used when rendering, instead of the size
/// of the sprite's image in the atlas
pub custom_size: Option<Vec2>,
pub anchor: Anchor,
}

impl Default for TextureAtlasSprite {
fn default() -> Self {
Self {
index: 0,
color: Color::WHITE,
flip_x: false,
flip_y: false,
custom_size: None,
anchor: Anchor::default(),
}
}
}

impl TextureAtlasSprite {
pub fn new(index: usize) -> TextureAtlasSprite {
Self {
index,
..Default::default()
}
}
}

impl TextureAtlas {
/// Create a new `TextureAtlas` that has a texture, but does not have
/// any individual sprites specified
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/move_sprite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn_bundle(Camera2dBundle::default());
commands
.spawn_bundle(SpriteBundle {
texture: asset_server.load("branding/icon.png"),
texture: asset_server.load("branding/icon.png").into(),
transform: Transform::from_xyz(100., 0., 0.),
..default()
})
Expand Down
10 changes: 5 additions & 5 deletions examples/2d/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// player controlled ship
commands
.spawn_bundle(SpriteBundle {
texture: ship_handle,
texture: ship_handle.into(),
..default()
})
.insert(Player {
Expand All @@ -78,14 +78,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// enemy that snaps to face the player spawns on the bottom and left
commands
.spawn_bundle(SpriteBundle {
texture: enemy_a_handle.clone(),
texture: enemy_a_handle.clone().into(),
transform: Transform::from_xyz(0.0 - horizontal_margin, 0.0, 0.0),
..default()
})
.insert(SnapToPlayer);
commands
.spawn_bundle(SpriteBundle {
texture: enemy_a_handle,
texture: enemy_a_handle.into(),
transform: Transform::from_xyz(0.0, 0.0 - vertical_margin, 0.0),
..default()
})
Expand All @@ -94,7 +94,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// enemy that rotates to face the player enemy spawns on the top and right
commands
.spawn_bundle(SpriteBundle {
texture: enemy_b_handle.clone(),
texture: enemy_b_handle.clone().into(),
transform: Transform::from_xyz(0.0 + horizontal_margin, 0.0, 0.0),
..default()
})
Expand All @@ -103,7 +103,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
commands
.spawn_bundle(SpriteBundle {
texture: enemy_b_handle,
texture: enemy_b_handle.into(),
transform: Transform::from_xyz(0.0, 0.0 + vertical_margin, 0.0),
..default()
})
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/sprite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn_bundle(Camera2dBundle::default());
commands.spawn_bundle(SpriteBundle {
texture: asset_server.load("branding/icon.png"),
texture: asset_server.load("branding/icon.png").into(),
..default()
});
}
2 changes: 1 addition & 1 deletion examples/2d/sprite_flipping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn_bundle(Camera2dBundle::default());
commands.spawn_bundle(SpriteBundle {
texture: asset_server.load("branding/icon.png"),
texture: asset_server.load("branding/icon.png").into(),
sprite: Sprite {
// Flip the logo to the left
flip_x: true,
Expand Down
22 changes: 12 additions & 10 deletions examples/2d/sprite_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! into a texture atlas, and changing the displayed image periodically.

use bevy::{prelude::*, render::texture::ImageSettings};
use std::ops::DerefMut;

fn main() {
App::new()
Expand All @@ -18,17 +19,15 @@ struct AnimationTimer(Timer);
fn animate_sprite(
time: Res<Time>,
texture_atlases: Res<Assets<TextureAtlas>>,
mut query: Query<(
&mut AnimationTimer,
&mut TextureAtlasSprite,
&Handle<TextureAtlas>,
)>,
mut query: Query<(&mut AnimationTimer, &mut SpriteImage)>,
) {
for (mut timer, mut sprite, texture_atlas_handle) in query.iter_mut() {
for (mut timer, mut image) in query.iter_mut() {
timer.tick(time.delta());
if timer.just_finished() {
let texture_atlas = texture_atlases.get(texture_atlas_handle).unwrap();
sprite.index = (sprite.index + 1) % texture_atlas.textures.len();
if let SpriteImage::TextureAtlas { index, handle } = image.deref_mut() {
let texture_atlas = texture_atlases.get(handle).unwrap();
*index = (*index + 1) % texture_atlas.textures.len();
}
}
}
}
Expand All @@ -43,8 +42,11 @@ fn setup(
let texture_atlas_handle = texture_atlases.add(texture_atlas);
commands.spawn_bundle(Camera2dBundle::default());
commands
.spawn_bundle(SpriteSheetBundle {
texture_atlas: texture_atlas_handle,
.spawn_bundle(SpriteBundle {
texture: SpriteImage::TextureAtlas {
handle: texture_atlas_handle,
index: 0,
},
transform: Transform::from_scale(Vec3::splat(6.0)),
..default()
})
Expand Down
10 changes: 6 additions & 4 deletions examples/2d/texture_atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,21 @@ fn setup(
// set up a scene to display our texture atlas
commands.spawn_bundle(Camera2dBundle::default());
// draw a sprite from the atlas
commands.spawn_bundle(SpriteSheetBundle {
commands.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(150.0, 0.0, 0.0),
scale: Vec3::splat(4.0),
..default()
},
sprite: TextureAtlasSprite::new(vendor_index),
texture_atlas: atlas_handle,
texture: SpriteImage::TextureAtlas {
handle: atlas_handle,
index: vendor_index,
},
..default()
});
// draw the atlas itself
commands.spawn_bundle(SpriteBundle {
texture: texture_atlas_texture,
texture: texture_atlas_texture.into(),
transform: Transform::from_xyz(-300.0, 0.0, 0.0),
..default()
});
Expand Down
Loading

0 comments on commit e94650f

Please sign in to comment.