Remove Need for Sprite Size Sync System (#2632)

# Objective

- Prevent the need to have a system that synchronizes sprite sizes with their images

## Solution

- Read the sprite size from the image asset when rendering the sprite
- Replace the `size` and `resize_mode` fields of `Sprite` with a `custom_size: Option<Vec2>` that will modify the sprite's rendered size to be different than the image size, but only if it is `Some(Vec2)`
This commit is contained in:
Zicklag 2021-08-26 00:53:51 +00:00
parent dd32cd029d
commit cea7db1050
4 changed files with 17 additions and 68 deletions

View file

@ -3,10 +3,10 @@ use bevy::{
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
ecs::prelude::*, ecs::prelude::*,
input::Input, input::Input,
math::{Vec2, Vec3}, math::Vec3,
prelude::{App, AssetServer, Handle, MouseButton, Transform}, prelude::{App, AssetServer, Handle, MouseButton, Transform},
render2::{camera::OrthographicCameraBundle, color::Color, texture::Image}, render2::{camera::OrthographicCameraBundle, color::Color, texture::Image},
sprite2::{PipelinedSpriteBundle, Sprite}, sprite2::PipelinedSpriteBundle,
window::WindowDescriptor, window::WindowDescriptor,
PipelinedDefaultPlugins, PipelinedDefaultPlugins,
}; };
@ -177,10 +177,6 @@ fn spawn_birds(
.spawn_bundle(PipelinedSpriteBundle { .spawn_bundle(PipelinedSpriteBundle {
// material: bird_material.0.clone(), // material: bird_material.0.clone(),
texture: texture.clone(), texture: texture.clone(),
sprite: Sprite {
size: Vec2::new(250.0, 250.0),
..Default::default()
},
transform: Transform { transform: Transform {
translation: Vec3::new(bird_x, bird_y, bird_z), translation: Vec3::new(bird_x, bird_y, bird_z),
scale: Vec3::splat(BIRD_SCALE), scale: Vec3::splat(BIRD_SCALE),

View file

@ -25,9 +25,7 @@ pub struct SpritePlugin;
impl Plugin for SpritePlugin { impl Plugin for SpritePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_asset::<TextureAtlas>() app.add_asset::<TextureAtlas>().register_type::<Sprite>();
.register_type::<Sprite>()
.add_system_to_stage(CoreStage::PostUpdate, sprite_auto_resize_system);
let render_app = app.sub_app(RenderApp); let render_app = app.sub_app(RenderApp);
render_app render_app
.init_resource::<ExtractedSprites>() .init_resource::<ExtractedSprites>()

View file

@ -190,16 +190,21 @@ pub fn extract_sprites(
) { ) {
let mut extracted_sprites = Vec::new(); let mut extracted_sprites = Vec::new();
for (sprite, transform, handle) in sprite_query.iter() { for (sprite, transform, handle) in sprite_query.iter() {
if !images.contains(handle) { let image = if let Some(image) = images.get(handle) {
image
} else {
continue; continue;
} };
let size = image.texture_descriptor.size;
extracted_sprites.push(ExtractedSprite { extracted_sprites.push(ExtractedSprite {
atlas_size: None, atlas_size: None,
transform: transform.compute_matrix(), transform: transform.compute_matrix(),
rect: Rect { rect: Rect {
min: Vec2::ZERO, min: Vec2::ZERO,
max: sprite.size, max: sprite
.custom_size
.unwrap_or_else(|| Vec2::new(size.width as f32, size.height as f32)),
}, },
handle: handle.clone_weak(), handle: handle.clone_weak(),
}); });

View file

@ -1,65 +1,15 @@
use bevy_asset::{Assets, Handle};
use bevy_ecs::prelude::{Query, Res};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_reflect::{Reflect, ReflectDeserialize, TypeUuid}; use bevy_reflect::{Reflect, TypeUuid};
use bevy_render2::texture::Image;
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, TypeUuid, Reflect)] #[derive(Debug, Default, Clone, TypeUuid, Reflect)]
#[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"] #[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"]
#[repr(C)] #[repr(C)]
pub struct Sprite { pub struct Sprite {
pub size: Vec2, /// Flip the sprite along the X axis
pub flip_x: bool, pub flip_x: bool,
/// Flip the sprite along the Y axis
pub flip_y: bool, pub flip_y: bool,
pub resize_mode: SpriteResizeMode, /// An optional custom size for the sprite that will be used when rendering, instead of the size
} /// of the sprite's image
pub custom_size: Option<Vec2>,
/// Determines how `Sprite` resize should be handled
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect_value(PartialEq, Serialize, Deserialize)]
pub enum SpriteResizeMode {
Manual,
Automatic,
}
impl Default for SpriteResizeMode {
fn default() -> Self {
SpriteResizeMode::Automatic
}
}
impl Sprite {
/// Creates new `Sprite` with `SpriteResizeMode::Manual` value for `resize_mode`
pub fn new(size: Vec2) -> Self {
Self {
size,
resize_mode: SpriteResizeMode::Manual,
flip_x: false,
flip_y: false,
}
}
}
/// System that resizes sprites that have their resize mode set to automatic
pub fn sprite_auto_resize_system(
textures: Res<Assets<Image>>,
mut query: Query<(&mut Sprite, &Handle<Image>)>,
) {
for (mut sprite, image_handle) in query.iter_mut() {
match sprite.resize_mode {
SpriteResizeMode::Manual => continue,
SpriteResizeMode::Automatic => {
if let Some(image) = textures.get(image_handle) {
let extent = image.texture_descriptor.size;
let texture_size = Vec2::new(extent.width as f32, extent.height as f32);
// only set sprite size if it has changed (this check prevents change
// detection from triggering)
if sprite.size != texture_size {
sprite.size = texture_size;
}
}
}
}
}
} }