diff --git a/Cargo.toml b/Cargo.toml index 6f27a6fb7a..76a70f715c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,10 @@ opt-level = 3 name = "hello_world" path = "examples/hello_world.rs" +[[example]] +name = "sprite" +path = "examples/2d/sprite.rs" + [[example]] name = "load_model" path = "examples/3d/load_model.rs" diff --git a/crates/bevy_render/src/texture/texture.rs b/crates/bevy_render/src/texture/texture.rs index 2997d9f379..2f0b182770 100644 --- a/crates/bevy_render/src/texture/texture.rs +++ b/crates/bevy_render/src/texture/texture.rs @@ -15,6 +15,12 @@ pub struct Texture { pub height: usize, } +impl Texture { + pub fn aspect(&self) -> f32 { + self.height as f32 / self.width as f32 + } +} + impl Asset for Texture { fn load(descriptor: TextureType) -> Self { let (data, width, height) = match descriptor { diff --git a/crates/bevy_ui/src/entity.rs b/crates/bevy_ui/src/entity.rs index b872d2c5b1..3bdae7b92d 100644 --- a/crates/bevy_ui/src/entity.rs +++ b/crates/bevy_ui/src/entity.rs @@ -1,5 +1,5 @@ use super::Node; -use crate::{render::UI_PIPELINE_HANDLE, ColorMaterial, Rect, QUAD_HANDLE}; +use crate::{render::UI_PIPELINE_HANDLE, ColorMaterial, Rect, QUAD_HANDLE, sprite::Sprite}; use bevy_asset::Handle; use bevy_derive::EntityArchetype; use bevy_render::{mesh::Mesh, Renderable}; @@ -28,3 +28,28 @@ impl Default for UiEntity { } } } + +#[derive(EntityArchetype)] +#[module(meta = false)] +pub struct SpriteEntity { + pub sprite: Sprite, + pub rect: Rect, + pub mesh: Handle, // TODO: maybe abstract this out + pub material: Handle, + pub renderable: Renderable, +} + +impl Default for SpriteEntity { + fn default() -> Self { + SpriteEntity { + sprite: Default::default(), + rect: Default::default(), + mesh: QUAD_HANDLE, + material: Default::default(), + renderable: Renderable { + pipelines: vec![UI_PIPELINE_HANDLE], + ..Default::default() + }, + } + } +} \ No newline at end of file diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index e7b0d379ab..242e0b1d63 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -4,6 +4,7 @@ pub mod entity; mod margins; mod node; mod rect; +mod sprite; mod render; mod ui_update_system; @@ -14,6 +15,7 @@ pub use node::*; pub use rect::*; pub use render::*; pub use ui_update_system::*; +pub use sprite::*; use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_asset::{AssetStorage, Handle}; @@ -24,6 +26,7 @@ use bevy_render::{ }; use glam::Vec2; use legion::prelude::IntoSystem; +use sprite::sprite_system; #[derive(Default)] pub struct UiPlugin; @@ -42,7 +45,8 @@ impl AppPlugin for UiPlugin { stage::POST_UPDATE, asset_handle_shader_def_system::.system(), ) - .add_system(ui_update_system()); + .add_system_to_stage(stage::POST_UPDATE, sprite_system()) + .add_system_to_stage(stage::POST_UPDATE, ui_update_system()); let resources = app.resources(); let mut render_graph = resources.get_mut::().unwrap(); diff --git a/crates/bevy_ui/src/sprite.rs b/crates/bevy_ui/src/sprite.rs new file mode 100644 index 0000000000..789c82ab9d --- /dev/null +++ b/crates/bevy_ui/src/sprite.rs @@ -0,0 +1,37 @@ +use crate::{ColorMaterial, Rect}; +use bevy_asset::{AssetStorage, Handle}; +use bevy_render::texture::Texture; +pub use legion::prelude::*; +pub struct Sprite { + pub scale: f32, +} + +impl Default for Sprite { + fn default() -> Self { + Sprite { + scale: 1.0 + } + } +} + +pub fn sprite_system() -> Box { + SystemBuilder::new("sprite_system") + .read_resource::>() + .read_resource::>() + .with_query( + <(Read, Read>, Write)>::query().filter( + changed::() | changed::() | changed::>(), + ), + ) + .build(|_, world, (materials, textures), query| { + for (sprite, handle, mut rect) in query.iter_mut(world) { + let material = materials.get(&handle).unwrap(); + if let Some(texture_handle) = material.texture { + let texture = textures.get(&texture_handle).unwrap(); + let aspect = texture.aspect(); + *rect.size.x_mut() = texture.width as f32 * sprite.scale; + *rect.size.y_mut() = rect.size.x() * aspect; + } + } + }) +} diff --git a/examples/2d/sprite.rs b/examples/2d/sprite.rs new file mode 100644 index 0000000000..9630d3a8be --- /dev/null +++ b/examples/2d/sprite.rs @@ -0,0 +1,32 @@ +use bevy::prelude::*; + +fn main() { + App::build() + .add_default_plugins() + .add_startup_system(setup) + .run(); +} + +fn setup(world: &mut World, resources: &mut Resources) { + let mut texture_storage = resources.get_mut::>().unwrap(); + let texture_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/branding/icon.png" + ); + let texture = Texture::load(TextureType::Png(texture_path.to_string())); + let texture_handle = texture_storage.add(texture); + let mut color_materials = resources.get_mut::>().unwrap(); + + world + .build() + .add_entity(Camera2dEntity::default()) + .add_entity(SpriteEntity { + rect: Rect { + position: Vec2::new(300.0, 300.0), + z_index: 0.5, + ..Default::default() + }, + material: color_materials.add(texture_handle.into()), + ..Default::default() + }); +} diff --git a/examples/3d/texture.rs b/examples/3d/texture.rs index ac2ea189cc..13c9d8eacc 100644 --- a/examples/3d/texture.rs +++ b/examples/3d/texture.rs @@ -16,7 +16,7 @@ fn setup(world: &mut World, resources: &mut Resources) { "/assets/branding/bevy_logo_dark_big.png" ); let texture = Texture::load(TextureType::Png(texture_path.to_string())); - let aspect = texture.height as f32 / texture.width as f32; + let aspect = texture.aspect(); let texture_handle = texture_storage.add(texture); // create a new quad mesh. this is what we will apply the texture to diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index be3b6d2cb3..7e7371bab9 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -24,7 +24,7 @@ fn setup(world: &mut World, resources: &mut Resources) { "/assets/branding/bevy_logo_dark_big.png" ); let texture = Texture::load(TextureType::Png(texture_path.to_string())); - let aspect = texture.height as f32 / texture.width as f32; + let aspect = texture.aspect(); let texture_handle = texture_storage.add(texture); let mut color_materials = resources.get_mut::>().unwrap(); diff --git a/src/prelude.rs b/src/prelude.rs index 40a46039d9..e3a0c167e4 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -32,7 +32,7 @@ pub use crate::render::{ #[cfg(feature = "transform")] pub use crate::transform::prelude::*; #[cfg(feature = "ui")] -pub use crate::ui::{entity::*, Anchors, Margins, Node, ColorMaterial}; +pub use crate::ui::{entity::*, Anchors, Rect, Sprite, Margins, Node, ColorMaterial}; #[cfg(feature = "window")] pub use crate::window::{Window, WindowDescriptor, WindowPlugin, Windows}; pub use crate::{