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