mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
begin porting ui to new render graph
This commit is contained in:
parent
dd84f185f8
commit
355e219608
11 changed files with 79 additions and 143 deletions
|
@ -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();
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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(
|
||||
|
|
12
crates/bevy_ui/src/rect.rs
Normal file
12
crates/bevy_ui/src/rect.rs
Normal 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,
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue