Ui depth from parent (falls back to insertion order for orphans), do ui rect size offsets before rendering,
This commit is contained in:
parent
b5cdb7c5fc
commit
75614f5084
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user