From 355e2196084fb70482e264ce1e295b36b789b2b7 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 2 May 2020 17:56:30 -0700 Subject: [PATCH] begin porting ui to new render graph --- crates/bevy_core/src/bytes.rs | 25 ++++- crates/bevy_ui/Cargo.toml | 1 + crates/bevy_ui/src/entity.rs | 6 +- crates/bevy_ui/src/lib.rs | 2 + crates/bevy_ui/src/node.rs | 11 +- crates/bevy_ui/src/rect.rs | 12 +++ crates/bevy_ui/src/render/ui.vert | 22 ++-- crates/bevy_ui/src/ui_resource_provider.rs | 120 --------------------- crates/bevy_ui/src/ui_update_system.rs | 13 ++- examples/ui/ui.rs | 9 ++ examples/ui/ui_bench.rs | 1 + 11 files changed, 79 insertions(+), 143 deletions(-) create mode 100644 crates/bevy_ui/src/rect.rs delete mode 100644 crates/bevy_ui/src/ui_resource_provider.rs diff --git a/crates/bevy_core/src/bytes.rs b/crates/bevy_core/src/bytes.rs index 8d41680479..c5a7843bf5 100644 --- a/crates/bevy_core/src/bytes.rs +++ b/crates/bevy_core/src/bytes.rs @@ -1,4 +1,4 @@ -use glam::{Mat4, Vec4}; +use glam::{Mat4, Vec4, Vec3, Vec2}; use zerocopy::AsBytes; pub trait GetBytes { @@ -42,6 +42,29 @@ impl GetBytes for [f32; 4] { } } +impl GetBytes for Vec3 { + fn get_bytes(&self) -> Vec { + let vec3_array: [f32; 3] = (*self).into(); + vec3_array.as_bytes().into() + } + + fn get_bytes_ref(&self) -> Option<&[u8]> { + Some(self.as_ref().as_bytes()) + } +} + +impl GetBytes for Vec2 { + fn get_bytes(&self) -> Vec { + let vec2_array: [f32; 2] = (*self).into(); + vec2_array.as_bytes().into() + } + + fn get_bytes_ref(&self) -> Option<&[u8]> { + Some(self.as_ref().as_bytes()) + } +} + + impl GetBytes for Vec4 { fn get_bytes(&self) -> Vec { let vec4_array: [f32; 4] = (*self).into(); diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index 276b996365..e750086a24 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } +bevy_asset = { path = "../bevy_asset" } bevy_core = { path = "../bevy_core" } bevy_derive = { path = "../bevy_derive" } bevy_transform = { path = "../bevy_transform" } diff --git a/crates/bevy_ui/src/entity.rs b/crates/bevy_ui/src/entity.rs index 944e2bc3ef..093a42cd69 100644 --- a/crates/bevy_ui/src/entity.rs +++ b/crates/bevy_ui/src/entity.rs @@ -1,8 +1,12 @@ use super::Node; use bevy_derive::EntityArchetype; +use bevy_render::Renderable; +use crate::Rect; -#[derive(EntityArchetype)] +#[derive(EntityArchetype, Default)] #[module(meta = false)] pub struct UiEntity { pub node: Node, + pub rect: Rect, + pub renderable: Renderable, } diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 8d9f9421f8..41b58b50c1 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -2,11 +2,13 @@ mod anchors; pub mod entity; mod margins; mod node; +mod rect; mod ui_update_system; pub use anchors::*; pub use margins::*; pub use node::*; +pub use rect::*; pub use ui_update_system::*; use bevy_app::{AppBuilder, AppPlugin}; diff --git a/crates/bevy_ui/src/node.rs b/crates/bevy_ui/src/node.rs index d66005cf69..b8ac8c3820 100644 --- a/crates/bevy_ui/src/node.rs +++ b/crates/bevy_ui/src/node.rs @@ -1,6 +1,7 @@ use super::{Anchors, Margins}; use bevy_render::Color; use glam::{self, Vec2}; +use crate::Rect; #[derive(Debug, Clone)] enum GrowDirection { @@ -11,9 +12,7 @@ enum GrowDirection { #[derive(Debug, Clone)] pub struct Node { pub position: Vec2, - pub global_position: Vec2, pub size: Vec2, - pub parent_dimensions: Vec2, pub anchors: Anchors, pub margins: Margins, pub color: Color, @@ -23,9 +22,7 @@ impl Default for Node { fn default() -> Self { Node { position: Vec2::default(), - global_position: Vec2::default(), size: Vec2::default(), - parent_dimensions: Vec2::default(), anchors: Anchors::default(), margins: Margins::default(), color: Color::rgb(0.0, 0.0, 0.0), @@ -37,16 +34,14 @@ impl Node { pub fn new(position: Vec2, anchors: Anchors, margins: Margins, color: Color) -> Self { Node { position, - global_position: Vec2::default(), size: Vec2::default(), - parent_dimensions: Vec2::default(), anchors, margins, color, } } - pub fn update(&mut self, parent_dimensions: Vec2, parent_position: Vec2) { + pub fn update(&mut self, rect: &mut Rect, parent_dimensions: Vec2, parent_position: Vec2) { let (rect_x, rect_width) = Self::compute_dimension_properties( self.position.x(), self.margins.left, @@ -65,7 +60,7 @@ impl Node { ); self.size = glam::vec2(rect_width, rect_height); - self.global_position = glam::vec2(rect_x, rect_y) + parent_position; + rect.position = glam::vec2(rect_x, rect_y) + parent_position; } fn compute_dimension_properties( diff --git a/crates/bevy_ui/src/rect.rs b/crates/bevy_ui/src/rect.rs new file mode 100644 index 0000000000..44e132061f --- /dev/null +++ b/crates/bevy_ui/src/rect.rs @@ -0,0 +1,12 @@ +use glam::Vec2; +use bevy_render::Color; +use bevy_derive::Uniforms; +#[repr(C)] +#[derive(Default, Clone, Copy, Debug, Uniforms)] +#[module(meta = "false")] +pub struct Rect { + pub position: Vec2, + pub size: Vec2, + pub color: Color, + pub z_index: f32, +} \ No newline at end of file diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index 90d2f59ac3..e3b435ec13 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -4,20 +4,22 @@ layout(location = 0) in vec3 Vertex_Position; layout(location = 1) in vec3 Vertex_Normal; layout(location = 2) in vec2 Vertex_Uv; -layout (location = 3) in vec2 I_Rect_Position; -layout (location = 4) in vec2 I_Rect_Size; -layout (location = 5) in vec4 I_Rect_Color; -layout (location = 6) in float I_Rect_ZIndex; - layout(location = 0) out vec4 v_Color; layout(set = 0, binding = 0) uniform Camera2d { mat4 ViewProj; }; +layout(set = 1, binding = 0) uniform Rect { + vec2 Rect_Position; + vec2 Rect_Size; + vec4 Rect_Color; + float Rect_ZIndex; +}; + void main() { - v_Color = I_Rect_Color; - vec3 position = Vertex_Position * vec3(I_Rect_Size, 0.0); - position = position + vec4(I_Rect_Position + I_Rect_Size / 2.0, -I_Rect_ZIndex, 0.0); - gl_Position = ViewProj * vec4(position, 1.0); -} + v_Color = Rect_Color; + vec3 position = Vertex_Position * vec3(Rect_Size, 0.0); + position = position + vec4(Rect_Position + Rect_Size / 2.0, -Rect_ZIndex, 0.0); + gl_Position = ViewProj * vec4(position, 1.0) +} \ No newline at end of file diff --git a/crates/bevy_ui/src/ui_resource_provider.rs b/crates/bevy_ui/src/ui_resource_provider.rs deleted file mode 100644 index 83332a8e66..0000000000 --- a/crates/bevy_ui/src/ui_resource_provider.rs +++ /dev/null @@ -1,120 +0,0 @@ -use bevy_core::ecs; -use bevy_derive::Uniforms; -use bevy_render::{ - pipeline::VertexBufferDescriptors, - render_resource::{ - resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, - RenderResourceAssignments, ResourceProvider, - }, - renderer::Renderer, - shader::AsUniforms, -}; -use bevy_transform::prelude::Parent; -use legion::prelude::*; -use zerocopy::{AsBytes, FromBytes}; - -#[repr(C)] -#[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)] -#[uniform(bevy_path = "crate")] -pub struct Rect { - #[uniform(instance)] - pub position: [f32; 2], - #[uniform(instance)] - pub size: [f32; 2], - #[uniform(instance)] - pub color: [f32; 4], - #[uniform(instance)] - pub z_index: f32, -} - -pub struct UiResourceProvider { - pub instance_buffer: Option, -} - -impl UiResourceProvider { - pub fn new() -> Self { - UiResourceProvider { - instance_buffer: None, - } - } - - pub fn update(&mut self, renderer: &mut dyn Renderer, world: &World, resources: &Resources) { - let node_query = >::query().filter(!component::()); - - let mut data = Vec::new(); - if node_query.iter(world).count() > 0 { - // TODO: this probably isn't the best way to handle z-ordering - let mut z = 0.9999; - { - let mut add_data: Box Option<()>> = - Box::new(|world, entity, _| { - let node = world.get_component::(entity).unwrap(); - data.push(Rect { - position: node.global_position.into(), - size: node.size.into(), - color: node.color.into(), - z_index: z, - }); - - z -= 0.0001; - Some(()) - }); - - for entity in node_query - .iter_entities(world) - .map(|(entity, _)| entity) - .collect::>() - { - ecs::run_on_hierarchy(world, entity, (), &mut add_data); - } - } - } - - if data.len() == 0 { - return; - } - - let size = std::mem::size_of::(); - let data_len = data.len(); - - if let Some(old_instance_buffer) = self.instance_buffer { - renderer.remove_buffer(old_instance_buffer); - } - - let buffer = renderer.create_buffer_with_data( - BufferInfo { - size, - buffer_usage: BufferUsage::COPY_SRC | BufferUsage::VERTEX, - array_info: Some(BufferArrayInfo { - item_capacity: data_len, - item_count: data_len, - item_size: size, - ..Default::default() - }), - ..Default::default() - }, - data.as_bytes(), - ); - - let mut render_resource_assignments = - resources.get_mut::().unwrap(); - render_resource_assignments.set(resource_name::buffer::UI_INSTANCES, buffer); - self.instance_buffer = Some(buffer); - } -} - -impl ResourceProvider for UiResourceProvider { - fn initialize( - &mut self, - _renderer: &mut dyn Renderer, - _world: &mut World, - resources: &Resources, - ) { - let mut vertex_buffer_descriptors = resources.get_mut::().unwrap(); - vertex_buffer_descriptors.set(Rect::get_vertex_buffer_descriptor().cloned().unwrap()); - } - - fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { - self.update(renderer, world, resources); - } -} diff --git a/crates/bevy_ui/src/ui_update_system.rs b/crates/bevy_ui/src/ui_update_system.rs index 1bd98a7f07..2a1cdaa37e 100644 --- a/crates/bevy_ui/src/ui_update_system.rs +++ b/crates/bevy_ui/src/ui_update_system.rs @@ -1,4 +1,5 @@ use super::Node; +use crate::Rect; use bevy_core::transform::run_on_hierarchy_subworld_mut; use bevy_transform::prelude::{Children, Parent}; use bevy_window::Windows; @@ -10,6 +11,7 @@ pub fn ui_update_system() -> Box { .read_resource::() .with_query(<(Write,)>::query().filter(!component::())) .write_component::() + .write_component::() .read_component::() .build(move |_, world, windows, node_query| { if let Some(window) = windows.get_primary() { @@ -33,9 +35,14 @@ fn update_node_entity( parent_properties: (Vec2, Vec2), ) -> Option<(Vec2, Vec2)> { let (parent_size, parent_position) = parent_properties; - if let Some(mut node) = world.get_component_mut::(entity) { - node.update(parent_size, parent_position); - return Some((node.size, node.global_position)); + // TODO: Somehow remove this unsafe + unsafe { + if let Some(mut node) = world.get_component_mut_unchecked::(entity) { + if let Some(mut rect) = world.get_component_mut_unchecked::(entity) { + node.update(&mut rect, parent_size, parent_position); + return Some((node.size, rect.position)); + } + } } None diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index a6ff9bc340..a935484e21 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -53,6 +53,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(10.0, 200.0, 10.0, 10.0), Color::rgb(0.1, 0.1, 0.1), ), + ..Default::default() }) // top right anchor with vertical fill .add_entity(UiEntity { @@ -62,6 +63,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(10.0, 100.0, 50.0, 100.0), Color::rgb(0.1, 0.1, 0.1), ), + ..Default::default() }) // render order test: reddest in the back, whitest in the front .add_entity(UiEntity { @@ -71,6 +73,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgb(1.0, 0.1, 0.1), ), + ..Default::default() }) .add_entity(UiEntity { node: Node::new( @@ -79,6 +82,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgb(1.0, 0.3, 0.3), ), + ..Default::default() }) .add_entity(UiEntity { node: Node::new( @@ -87,6 +91,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgb(1.0, 0.5, 0.5), ), + ..Default::default() }) .add_entity(UiEntity { node: Node::new( @@ -95,6 +100,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgb(1.0, 0.7, 0.7), ), + ..Default::default() }) // parenting .add_entity(UiEntity { @@ -104,6 +110,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 200.0, 0.0, 200.0), Color::rgb(0.1, 0.1, 1.0), ), + ..Default::default() }) .add_children(|builder| { builder.add_entity(UiEntity { @@ -113,6 +120,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(20.0, 20.0, 20.0, 20.0), Color::rgb(0.6, 0.6, 1.0), ), + ..Default::default() }); }) // alpha test @@ -123,5 +131,6 @@ fn setup(world: &mut World, resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgba(1.0, 0.9, 0.9, 0.4), ), + ..Default::default() }); } diff --git a/examples/ui/ui_bench.rs b/examples/ui/ui_bench.rs index 0dc4a791de..2e13f32d25 100644 --- a/examples/ui/ui_bench.rs +++ b/examples/ui/ui_bench.rs @@ -37,6 +37,7 @@ fn setup(world: &mut World, _resources: &mut Resources) { Margins::new(0.0, 100.0, 0.0, 100.0), Color::rgb(0.0 + i as f32 / count as f32, 0.1, 0.1), ), + ..Default::default() }); prev = cur;