begin porting ui to new render graph

This commit is contained in:
Carter Anderson 2020-05-02 17:56:30 -07:00
parent dd84f185f8
commit 355e219608
11 changed files with 79 additions and 143 deletions

View file

@ -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<u8> {
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<u8> {
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<u8> {
let vec4_array: [f32; 4] = (*self).into();

View file

@ -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" }

View file

@ -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,
}

View file

@ -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};

View file

@ -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(

View file

@ -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,
}

View file

@ -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)
}

View file

@ -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<RenderResource>,
}
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 = <Read<Node>>::query().filter(!component::<Parent>());
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<dyn FnMut(&World, Entity, ()) -> Option<()>> =
Box::new(|world, entity, _| {
let node = world.get_component::<Node>(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::<Vec<Entity>>()
{
ecs::run_on_hierarchy(world, entity, (), &mut add_data);
}
}
}
if data.len() == 0 {
return;
}
let size = std::mem::size_of::<Rect>();
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::<RenderResourceAssignments>().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::<VertexBufferDescriptors>().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);
}
}

View file

@ -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<dyn Schedulable> {
.read_resource::<Windows>()
.with_query(<(Write<Node>,)>::query().filter(!component::<Parent>()))
.write_component::<Node>()
.write_component::<Rect>()
.read_component::<Children>()
.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::<Node>(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::<Node>(entity) {
if let Some(mut rect) = world.get_component_mut_unchecked::<Rect>(entity) {
node.update(&mut rect, parent_size, parent_position);
return Some((node.size, rect.position));
}
}
}
None

View file

@ -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()
});
}

View file

@ -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;