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
|
) where
|
||||||
T: Copy,
|
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) {
|
let children = match world.get_component::<Children>(entity) {
|
||||||
Some(children) => Some(
|
Some(children) => Some(
|
||||||
children
|
children
|
||||||
@ -78,11 +78,12 @@ pub fn run_on_hierarchy_subworld_mut<T>(
|
|||||||
world: &mut SubWorld,
|
world: &mut SubWorld,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
input: T,
|
input: T,
|
||||||
func: &mut dyn FnMut(&mut SubWorld, Entity, T) -> Option<T>,
|
run: &mut dyn FnMut(&mut SubWorld, Entity, T) -> Option<T>,
|
||||||
) where
|
child_result_action: &mut dyn FnMut(T, T) -> T,
|
||||||
|
) -> Option<T> where
|
||||||
T: Copy,
|
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) {
|
let children = match world.get_component::<Children>(entity) {
|
||||||
Some(children) => Some(
|
Some(children) => Some(
|
||||||
children
|
children
|
||||||
@ -93,13 +94,20 @@ pub fn run_on_hierarchy_subworld_mut<T>(
|
|||||||
None => None,
|
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 {
|
if let Some(children) = children {
|
||||||
for child in 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;
|
use glam::Vec2;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum GrowDirection {
|
enum MarginGrowDirection {
|
||||||
Negative,
|
Negative,
|
||||||
Positive,
|
Positive,
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ impl Node {
|
|||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
rect: &mut Rect,
|
rect: &mut Rect,
|
||||||
parent_dimensions: Vec2,
|
parent_size: Vec2,
|
||||||
parent_position: Vec2,
|
parent_position: Vec2,
|
||||||
z_index: f32,
|
z_index: f32,
|
||||||
) {
|
) {
|
||||||
@ -47,7 +47,7 @@ impl Node {
|
|||||||
self.margins.right,
|
self.margins.right,
|
||||||
self.anchors.left,
|
self.anchors.left,
|
||||||
self.anchors.right,
|
self.anchors.right,
|
||||||
parent_dimensions.x(),
|
parent_size.x(),
|
||||||
);
|
);
|
||||||
let (rect_y, rect_height) = Self::compute_dimension_properties(
|
let (rect_y, rect_height) = Self::compute_dimension_properties(
|
||||||
self.position.y(),
|
self.position.y(),
|
||||||
@ -55,7 +55,7 @@ impl Node {
|
|||||||
self.margins.top,
|
self.margins.top,
|
||||||
self.anchors.bottom,
|
self.anchors.bottom,
|
||||||
self.anchors.top,
|
self.anchors.top,
|
||||||
parent_dimensions.y(),
|
parent_size.y(),
|
||||||
);
|
);
|
||||||
|
|
||||||
rect.size = Vec2::new(rect_width, rect_height);
|
rect.size = Vec2::new(rect_width, rect_height);
|
||||||
@ -75,37 +75,33 @@ impl Node {
|
|||||||
let anchor_p1 = anchor1 * length;
|
let anchor_p1 = anchor1 * length;
|
||||||
|
|
||||||
let p0_grow_direction = if anchor_p0 <= 0.5 {
|
let p0_grow_direction = if anchor_p0 <= 0.5 {
|
||||||
GrowDirection::Positive
|
MarginGrowDirection::Positive
|
||||||
} else {
|
} else {
|
||||||
GrowDirection::Negative
|
MarginGrowDirection::Negative
|
||||||
};
|
};
|
||||||
let p1_grow_direction = if anchor_p1 < 0.5 {
|
let p1_grow_direction = if anchor_p1 <= 0.5 {
|
||||||
GrowDirection::Positive
|
MarginGrowDirection::Positive
|
||||||
} else {
|
} else {
|
||||||
GrowDirection::Negative
|
MarginGrowDirection::Negative
|
||||||
};
|
};
|
||||||
|
|
||||||
let p0 = Self::compute_rect_position(offset, margin0, anchor_p0, p0_grow_direction);
|
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 p1 = Self::compute_rect_position(offset, margin1, anchor_p1, p1_grow_direction);
|
||||||
|
|
||||||
let final_width = p1 - p0;
|
let final_width = p1 - p0;
|
||||||
let mut p = (p0 + p1) / 2.0;
|
let p = (p0 + p1) / 2.0;
|
||||||
|
(p, final_width.abs())
|
||||||
// move position to "origin" in bottom left hand corner
|
|
||||||
p = p - final_width / 2.0;
|
|
||||||
|
|
||||||
(p, final_width)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_rect_position(
|
fn compute_rect_position(
|
||||||
position: f32,
|
position: f32,
|
||||||
margin: f32,
|
margin: f32,
|
||||||
anchor_position: f32,
|
anchor_position: f32,
|
||||||
grow_direction: GrowDirection,
|
grow_direction: MarginGrowDirection,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
match grow_direction {
|
match grow_direction {
|
||||||
GrowDirection::Negative => position + anchor_position - margin,
|
MarginGrowDirection::Negative => position + anchor_position - margin,
|
||||||
GrowDirection::Positive => 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 {
|
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||||
format: TextureFormat::Depth32Float,
|
format: TextureFormat::Depth32Float,
|
||||||
depth_write_enabled: false,
|
depth_write_enabled: true,
|
||||||
depth_compare: CompareFunction::Always,
|
depth_compare: CompareFunction::Less,
|
||||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||||
stencil_read_mask: 0,
|
stencil_read_mask: 0,
|
||||||
|
|||||||
@ -19,6 +19,6 @@ layout(set = 1, binding = 0) uniform Rect {
|
|||||||
void main() {
|
void main() {
|
||||||
v_Uv = Vertex_Uv;
|
v_Uv = Vertex_Uv;
|
||||||
vec3 position = Vertex_Position * vec3(Rect_Size, 0.0);
|
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);
|
gl_Position = ViewProj * vec4(position, 1.0);
|
||||||
}
|
}
|
||||||
@ -6,6 +6,8 @@ use bevy_window::Windows;
|
|||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use legion::{prelude::*, systems::SubWorld};
|
use legion::{prelude::*, systems::SubWorld};
|
||||||
|
|
||||||
|
pub const UI_Z_STEP: f32 = 0.0001;
|
||||||
|
|
||||||
pub fn ui_update_system() -> Box<dyn Schedulable> {
|
pub fn ui_update_system() -> Box<dyn Schedulable> {
|
||||||
SystemBuilder::new("ui_update")
|
SystemBuilder::new("ui_update")
|
||||||
.read_resource::<Windows>()
|
.read_resource::<Windows>()
|
||||||
@ -15,39 +17,58 @@ pub fn ui_update_system() -> Box<dyn Schedulable> {
|
|||||||
.read_component::<Children>()
|
.read_component::<Children>()
|
||||||
.build(move |_, world, windows, node_query| {
|
.build(move |_, world, windows, node_query| {
|
||||||
if let Some(window) = windows.get_primary() {
|
if let Some(window) = windows.get_primary() {
|
||||||
let parent_size = glam::vec2(window.width as f32, window.height as f32);
|
let mut window_rect = Rect {
|
||||||
let parent_position = glam::vec2(0.0, 0.0);
|
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
|
for entity in node_query
|
||||||
.iter_entities(world)
|
.iter_entities(world)
|
||||||
.map(|(e, _)| e)
|
.map(|(e, _)| e)
|
||||||
.collect::<Vec<Entity>>()
|
.collect::<Vec<Entity>>()
|
||||||
{
|
{
|
||||||
run_on_hierarchy_subworld_mut(
|
let result = run_on_hierarchy_subworld_mut(
|
||||||
world,
|
world,
|
||||||
entity,
|
entity,
|
||||||
(parent_size, parent_position, 0.9999),
|
window_rect.clone(),
|
||||||
&mut update_node_entity,
|
&mut update_node_entity,
|
||||||
|
&mut process_child_result,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(result) = result {
|
||||||
|
window_rect.z_index = result.z_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_node_entity(
|
fn update_node_entity(world: &mut SubWorld, entity: Entity, parent_rect: Rect) -> Option<Rect> {
|
||||||
world: &mut SubWorld,
|
|
||||||
entity: Entity,
|
|
||||||
parent_properties: (Vec2, Vec2, f32),
|
|
||||||
) -> Option<(Vec2, Vec2, f32)> {
|
|
||||||
let (parent_size, parent_position, z_index) = parent_properties;
|
|
||||||
// TODO: Somehow remove this unsafe
|
// TODO: Somehow remove this unsafe
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(mut node) = world.get_component_mut_unchecked::<Node>(entity) {
|
if let Some(mut node) = world.get_component_mut_unchecked::<Node>(entity) {
|
||||||
if let Some(mut rect) = world.get_component_mut_unchecked::<Rect>(entity) {
|
if let Some(mut rect) = world.get_component_mut_unchecked::<Rect>(entity) {
|
||||||
node.update(&mut rect, parent_size, parent_position, z_index);
|
node.update(
|
||||||
return Some((rect.size, rect.position, z_index - 0.0001));
|
&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
|
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) {
|
fn setup(world: &mut World, resources: &mut Resources) {
|
||||||
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
// TODO: "background" 3D temporarily disabled until depth mismatch is fixed
|
||||||
let mut material_storage = resources
|
// let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
.get_mut::<AssetStorage<StandardMaterial>>()
|
// let mut material_storage = resources
|
||||||
.unwrap();
|
// .get_mut::<AssetStorage<StandardMaterial>>()
|
||||||
let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
|
// .unwrap();
|
||||||
let cube_material_handle = material_storage.add(StandardMaterial {
|
// let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
|
||||||
albedo: Color::rgb(0.5, 0.3, 0.3),
|
// let cube_material_handle = material_storage.add(StandardMaterial {
|
||||||
..Default::default()
|
// albedo: Color::rgb(0.5, 0.4, 0.3),
|
||||||
});
|
// ..Default::default()
|
||||||
|
// });
|
||||||
|
|
||||||
let mut texture_storage = resources.get_mut::<AssetStorage<Texture>>().unwrap();
|
let mut texture_storage = resources.get_mut::<AssetStorage<Texture>>().unwrap();
|
||||||
let texture_path = concat!(
|
let texture_path = concat!(
|
||||||
@ -32,27 +33,27 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||||||
|
|
||||||
world
|
world
|
||||||
.build()
|
.build()
|
||||||
// cube
|
// // cube
|
||||||
.add_entity(MeshEntity {
|
// .add_entity(MeshEntity {
|
||||||
mesh: cube_handle,
|
// mesh: cube_handle,
|
||||||
material: cube_material_handle,
|
// material: cube_material_handle,
|
||||||
translation: Translation::new(0.0, 0.0, 1.0),
|
// translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
})
|
// })
|
||||||
// light
|
// // light
|
||||||
.add_entity(LightEntity {
|
// .add_entity(LightEntity {
|
||||||
translation: Translation::new(4.0, -4.0, 5.0),
|
// translation: Translation::new(4.0, -4.0, 5.0),
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
})
|
// })
|
||||||
// 3d camera
|
// // 3d camera
|
||||||
.add_entity(CameraEntity {
|
// .add_entity(CameraEntity {
|
||||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
// local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||||
Vec3::new(3.0, 8.0, 5.0),
|
// Vec3::new(3.0, 8.0, 5.0),
|
||||||
Vec3::new(0.0, 0.0, 0.0),
|
// Vec3::new(0.0, 0.0, 0.0),
|
||||||
Vec3::new(0.0, 0.0, 1.0),
|
// Vec3::new(0.0, 0.0, 1.0),
|
||||||
)),
|
// )),
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
})
|
// })
|
||||||
// 2d camera
|
// 2d camera
|
||||||
.add_entity(Camera2dEntity::default())
|
.add_entity(Camera2dEntity::default())
|
||||||
// left vertical fill
|
// 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
|
// render order test: reddest in the back, whitest in the front
|
||||||
.add_entity(UiEntity {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(75.0, 75.0),
|
math::vec2(75.0, 60.0),
|
||||||
Anchors::CENTER,
|
Anchors::CENTER,
|
||||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
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 {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(50.0, 50.0),
|
math::vec2(50.0, 35.0),
|
||||||
Anchors::CENTER,
|
Anchors::CENTER,
|
||||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
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 {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(100.0, 100.0),
|
math::vec2(100.0, 85.0),
|
||||||
Anchors::CENTER,
|
Anchors::CENTER,
|
||||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
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 {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(150.0, 150.0),
|
math::vec2(150.0, 135.0),
|
||||||
Anchors::CENTER,
|
Anchors::CENTER,
|
||||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
),
|
),
|
||||||
@ -115,9 +116,9 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||||||
// parenting
|
// parenting
|
||||||
.add_entity(UiEntity {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(210.0, 10.0),
|
math::vec2(210.0, 0.0),
|
||||||
Anchors::BOTTOM_LEFT,
|
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()),
|
material: color_materials.add(Color::rgb(0.1, 0.1, 1.0).into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -136,7 +137,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||||||
// alpha test
|
// alpha test
|
||||||
.add_entity(UiEntity {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(200.0, 200.0),
|
math::vec2(200.0, 185.0),
|
||||||
Anchors::CENTER,
|
Anchors::CENTER,
|
||||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
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 {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
math::vec2(0.0, 0.0),
|
math::vec2(0.0, 0.0),
|
||||||
Anchors::CENTER_BOTTOM,
|
Anchors::CENTER_TOP,
|
||||||
Margins::new(0.0, 500.0, 10.0, 10.0 + 500.0 * aspect),
|
Margins::new(-250.0, 250.0, 510.0 * aspect, 10.0),
|
||||||
),
|
),
|
||||||
material: color_materials.add(ColorMaterial::texture(texture_handle)),
|
material: color_materials.add(ColorMaterial::texture(texture_handle)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user