Ui depth from parent (falls back to insertion order for orphans), do ui rect size offsets before rendering,

This commit is contained in:
Carter Anderson 2020-05-06 13:49:07 -07:00
parent b5cdb7c5fc
commit 75614f5084
6 changed files with 105 additions and 79 deletions

View File

@ -32,7 +32,7 @@ pub fn run_on_hierarchy_mut<T>(
) where
T: Copy,
{
// TODO: not a huge fan of this pattern. are there ways to do recursive updates in legion without allocactions?
// TODO: not a huge fan of this pattern. are there ways to do recursive updates in legion without allocations?
let children = match world.get_component::<Children>(entity) {
Some(children) => Some(
children
@ -78,11 +78,12 @@ pub fn run_on_hierarchy_subworld_mut<T>(
world: &mut SubWorld,
entity: Entity,
input: T,
func: &mut dyn FnMut(&mut SubWorld, Entity, T) -> Option<T>,
) where
run: &mut dyn FnMut(&mut SubWorld, Entity, T) -> Option<T>,
child_result_action: &mut dyn FnMut(T, T) -> T,
) -> Option<T> where
T: Copy,
{
// TODO: not a huge fan of this pattern. are there ways to do recursive updates in legion without allocactions?
// TODO: not a huge fan of this pattern. are there ways to do recursive updates in legion without allocations?
let children = match world.get_component::<Children>(entity) {
Some(children) => Some(
children
@ -93,13 +94,20 @@ pub fn run_on_hierarchy_subworld_mut<T>(
None => None,
};
let result = func(world, entity, input);
let result = run(world, entity, input);
if let Some(result) = result {
if let Some(mut result) = result {
if let Some(children) = children {
for child in children {
run_on_hierarchy_subworld_mut(world, child, result, func);
let child_result = run_on_hierarchy_subworld_mut(world, child, result, run, child_result_action);
if let Some(child_result) = child_result {
result = child_result_action(result, child_result)
}
}
}
Some(result)
} else {
None
}
}

View File

@ -3,7 +3,7 @@ use crate::Rect;
use glam::Vec2;
#[derive(Debug, Clone)]
enum GrowDirection {
enum MarginGrowDirection {
Negative,
Positive,
}
@ -37,7 +37,7 @@ impl Node {
pub fn update(
&mut self,
rect: &mut Rect,
parent_dimensions: Vec2,
parent_size: Vec2,
parent_position: Vec2,
z_index: f32,
) {
@ -47,7 +47,7 @@ impl Node {
self.margins.right,
self.anchors.left,
self.anchors.right,
parent_dimensions.x(),
parent_size.x(),
);
let (rect_y, rect_height) = Self::compute_dimension_properties(
self.position.y(),
@ -55,7 +55,7 @@ impl Node {
self.margins.top,
self.anchors.bottom,
self.anchors.top,
parent_dimensions.y(),
parent_size.y(),
);
rect.size = Vec2::new(rect_width, rect_height);
@ -75,37 +75,33 @@ impl Node {
let anchor_p1 = anchor1 * length;
let p0_grow_direction = if anchor_p0 <= 0.5 {
GrowDirection::Positive
MarginGrowDirection::Positive
} else {
GrowDirection::Negative
MarginGrowDirection::Negative
};
let p1_grow_direction = if anchor_p1 < 0.5 {
GrowDirection::Positive
let p1_grow_direction = if anchor_p1 <= 0.5 {
MarginGrowDirection::Positive
} else {
GrowDirection::Negative
MarginGrowDirection::Negative
};
let p0 = Self::compute_rect_position(offset, margin0, anchor_p0, p0_grow_direction);
let p1 = Self::compute_rect_position(offset, margin1, anchor_p1, p1_grow_direction);
let final_width = p1 - p0;
let mut p = (p0 + p1) / 2.0;
// move position to "origin" in bottom left hand corner
p = p - final_width / 2.0;
(p, final_width)
let p = (p0 + p1) / 2.0;
(p, final_width.abs())
}
fn compute_rect_position(
position: f32,
margin: f32,
anchor_position: f32,
grow_direction: GrowDirection,
grow_direction: MarginGrowDirection,
) -> f32 {
match grow_direction {
GrowDirection::Negative => position + anchor_position - margin,
GrowDirection::Positive => position + anchor_position + margin,
MarginGrowDirection::Negative => position + anchor_position - margin,
MarginGrowDirection::Positive => position + anchor_position + margin,
}
}
}

View File

@ -27,8 +27,8 @@ pub fn build_ui_pipeline(shaders: &mut AssetStorage<Shader>) -> PipelineDescript
}),
depth_stencil_state: Some(DepthStencilStateDescriptor {
format: TextureFormat::Depth32Float,
depth_write_enabled: false,
depth_compare: CompareFunction::Always,
depth_write_enabled: true,
depth_compare: CompareFunction::Less,
stencil_front: StencilStateFaceDescriptor::IGNORE,
stencil_back: StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,

View File

@ -19,6 +19,6 @@ layout(set = 1, binding = 0) uniform Rect {
void main() {
v_Uv = Vertex_Uv;
vec3 position = Vertex_Position * vec3(Rect_Size, 0.0);
position = position + vec3(Rect_Position + Rect_Size / 2.0, -Rect_ZIndex);
position = position + vec3(Rect_Position, -Rect_ZIndex);
gl_Position = ViewProj * vec4(position, 1.0);
}

View File

@ -6,6 +6,8 @@ use bevy_window::Windows;
use glam::Vec2;
use legion::{prelude::*, systems::SubWorld};
pub const UI_Z_STEP: f32 = 0.0001;
pub fn ui_update_system() -> Box<dyn Schedulable> {
SystemBuilder::new("ui_update")
.read_resource::<Windows>()
@ -15,39 +17,58 @@ pub fn ui_update_system() -> Box<dyn Schedulable> {
.read_component::<Children>()
.build(move |_, world, windows, node_query| {
if let Some(window) = windows.get_primary() {
let parent_size = glam::vec2(window.width as f32, window.height as f32);
let parent_position = glam::vec2(0.0, 0.0);
let mut window_rect = Rect {
size: Vec2::new(window.width as f32, window.height as f32),
position: Vec2::new(0.0, 0.0),
z_index: 0.9999,
};
for entity in node_query
.iter_entities(world)
.map(|(e, _)| e)
.collect::<Vec<Entity>>()
{
run_on_hierarchy_subworld_mut(
let result = run_on_hierarchy_subworld_mut(
world,
entity,
(parent_size, parent_position, 0.9999),
window_rect.clone(),
&mut update_node_entity,
&mut process_child_result,
);
if let Some(result) = result {
window_rect.z_index = result.z_index;
}
}
}
})
}
fn update_node_entity(
world: &mut SubWorld,
entity: Entity,
parent_properties: (Vec2, Vec2, f32),
) -> Option<(Vec2, Vec2, f32)> {
let (parent_size, parent_position, z_index) = parent_properties;
fn update_node_entity(world: &mut SubWorld, entity: Entity, parent_rect: Rect) -> Option<Rect> {
// 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, z_index);
return Some((rect.size, rect.position, z_index - 0.0001));
node.update(
&mut rect,
parent_rect.size,
parent_rect.position,
parent_rect.z_index,
);
return Some(Rect {
size: rect.size,
position: rect.position - rect.size / 2.0,
z_index: rect.z_index - UI_Z_STEP,
});
}
}
}
None
}
fn process_child_result(_parent_result: Rect, child_result: Rect) -> Rect {
// "earlier" children are sorted behind "later" children
let mut result = child_result.clone();
result.z_index -= UI_Z_STEP;
result
}

View File

@ -8,15 +8,16 @@ fn main() {
}
fn setup(world: &mut World, resources: &mut Resources) {
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut material_storage = resources
.get_mut::<AssetStorage<StandardMaterial>>()
.unwrap();
let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
});
// TODO: "background" 3D temporarily disabled until depth mismatch is fixed
// let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
// let mut material_storage = resources
// .get_mut::<AssetStorage<StandardMaterial>>()
// .unwrap();
// let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
// let cube_material_handle = material_storage.add(StandardMaterial {
// albedo: Color::rgb(0.5, 0.4, 0.3),
// ..Default::default()
// });
let mut texture_storage = resources.get_mut::<AssetStorage<Texture>>().unwrap();
let texture_path = concat!(
@ -32,27 +33,27 @@ fn setup(world: &mut World, resources: &mut Resources) {
world
.build()
// cube
.add_entity(MeshEntity {
mesh: cube_handle,
material: cube_material_handle,
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_entity(LightEntity {
translation: Translation::new(4.0, -4.0, 5.0),
..Default::default()
})
// 3d camera
.add_entity(CameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
..Default::default()
})
// // cube
// .add_entity(MeshEntity {
// mesh: cube_handle,
// material: cube_material_handle,
// translation: Translation::new(0.0, 0.0, 1.0),
// ..Default::default()
// })
// // light
// .add_entity(LightEntity {
// translation: Translation::new(4.0, -4.0, 5.0),
// ..Default::default()
// })
// // 3d camera
// .add_entity(CameraEntity {
// local_to_world: LocalToWorld(Mat4::look_at_rh(
// Vec3::new(3.0, 8.0, 5.0),
// Vec3::new(0.0, 0.0, 0.0),
// Vec3::new(0.0, 0.0, 1.0),
// )),
// ..Default::default()
// })
// 2d camera
.add_entity(Camera2dEntity::default())
// left vertical fill
@ -78,7 +79,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
// render order test: reddest in the back, whitest in the front
.add_entity(UiEntity {
node: Node::new(
math::vec2(75.0, 75.0),
math::vec2(75.0, 60.0),
Anchors::CENTER,
Margins::new(0.0, 100.0, 0.0, 100.0),
),
@ -87,7 +88,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
})
.add_entity(UiEntity {
node: Node::new(
math::vec2(50.0, 50.0),
math::vec2(50.0, 35.0),
Anchors::CENTER,
Margins::new(0.0, 100.0, 0.0, 100.0),
),
@ -96,7 +97,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
})
.add_entity(UiEntity {
node: Node::new(
math::vec2(100.0, 100.0),
math::vec2(100.0, 85.0),
Anchors::CENTER,
Margins::new(0.0, 100.0, 0.0, 100.0),
),
@ -105,7 +106,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
})
.add_entity(UiEntity {
node: Node::new(
math::vec2(150.0, 150.0),
math::vec2(150.0, 135.0),
Anchors::CENTER,
Margins::new(0.0, 100.0, 0.0, 100.0),
),
@ -115,9 +116,9 @@ fn setup(world: &mut World, resources: &mut Resources) {
// parenting
.add_entity(UiEntity {
node: Node::new(
math::vec2(210.0, 10.0),
math::vec2(210.0, 0.0),
Anchors::BOTTOM_LEFT,
Margins::new(0.0, 200.0, 0.0, 200.0),
Margins::new(0.0, 200.0, 10.0, 210.0),
),
material: color_materials.add(Color::rgb(0.1, 0.1, 1.0).into()),
..Default::default()
@ -136,7 +137,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
// alpha test
.add_entity(UiEntity {
node: Node::new(
math::vec2(200.0, 200.0),
math::vec2(200.0, 185.0),
Anchors::CENTER,
Margins::new(0.0, 100.0, 0.0, 100.0),
),
@ -147,8 +148,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(UiEntity {
node: Node::new(
math::vec2(0.0, 0.0),
Anchors::CENTER_BOTTOM,
Margins::new(0.0, 500.0, 10.0, 10.0 + 500.0 * aspect),
Anchors::CENTER_TOP,
Margins::new(-250.0, 250.0, 510.0 * aspect, 10.0),
),
material: color_materials.add(ColorMaterial::texture(texture_handle)),
..Default::default()