mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
ui: fix z indices and depth calculations
This commit is contained in:
parent
2929197d9b
commit
db665b96c0
6 changed files with 66 additions and 24 deletions
|
@ -11,6 +11,20 @@ pub struct Camera {
|
|||
pub name: Option<String>,
|
||||
#[property(ignore)]
|
||||
pub window: WindowId,
|
||||
#[property(ignore)]
|
||||
pub depth_calculation: DepthCalculation,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DepthCalculation {
|
||||
Distance,
|
||||
ZDifference,
|
||||
}
|
||||
|
||||
impl Default for DepthCalculation {
|
||||
fn default() -> Self {
|
||||
DepthCalculation::Distance
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -55,8 +69,11 @@ pub fn camera_system<T: CameraProjection + Component>(
|
|||
|
||||
for (mut camera, mut camera_projection) in &mut query.iter() {
|
||||
if let Some(window) = windows.get(camera.window) {
|
||||
camera_projection.update(window.width as usize, window.height as usize);
|
||||
camera.projection_matrix = camera_projection.get_projection_matrix();
|
||||
if changed_window_ids.contains(&window.id) {
|
||||
camera_projection.update(window.width as usize, window.height as usize);
|
||||
camera.projection_matrix = camera_projection.get_projection_matrix();
|
||||
camera.depth_calculation = camera_projection.depth_calculation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use bevy_math::{Mat4, PerspectiveRh};
|
||||
use bevy_property::{Properties, Property};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use super::DepthCalculation;
|
||||
|
||||
pub trait CameraProjection {
|
||||
fn get_projection_matrix(&self) -> Mat4;
|
||||
fn update(&mut self, width: usize, height: usize);
|
||||
fn depth_calculation(&self) -> DepthCalculation;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Properties)]
|
||||
|
@ -23,6 +25,10 @@ impl CameraProjection for PerspectiveProjection {
|
|||
fn update(&mut self, width: usize, height: usize) {
|
||||
self.aspect_ratio = width as f32 / height as f32;
|
||||
}
|
||||
|
||||
fn depth_calculation(&self) -> DepthCalculation {
|
||||
DepthCalculation::Distance
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PerspectiveProjection {
|
||||
|
@ -84,6 +90,10 @@ impl CameraProjection for OrthographicProjection {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn depth_calculation(&self) -> DepthCalculation {
|
||||
DepthCalculation::ZDifference
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OrthographicProjection {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::Camera;
|
||||
use super::{Camera, DepthCalculation};
|
||||
use crate::Draw;
|
||||
use bevy_core::FloatOrd;
|
||||
use bevy_ecs::{Entity, Query};
|
||||
|
@ -26,7 +26,7 @@ pub fn visible_entities_system(
|
|||
mut draw_query: Query<(Entity, &Draw)>,
|
||||
draw_transform_query: Query<(&Draw, &Transform)>,
|
||||
) {
|
||||
for (_camera, camera_transform, mut visible_entities) in &mut camera_query.iter() {
|
||||
for (camera, camera_transform, mut visible_entities) in &mut camera_query.iter() {
|
||||
visible_entities.value.clear();
|
||||
let camera_position = camera_transform.value.w_axis().truncate();
|
||||
|
||||
|
@ -40,7 +40,10 @@ pub fn visible_entities_system(
|
|||
let order = if let Ok(transform) = draw_transform_query.get::<Transform>(entity) {
|
||||
let position = transform.value.w_axis().truncate();
|
||||
// smaller distances are sorted to lower indices by using the distance from the camera
|
||||
FloatOrd((camera_position - position).length())
|
||||
FloatOrd(match camera.depth_calculation {
|
||||
DepthCalculation::ZDifference => camera_position.z() - position.z(),
|
||||
DepthCalculation::Distance => (camera_position - position).length(),
|
||||
})
|
||||
} else {
|
||||
let order = FloatOrd(no_transform_order);
|
||||
no_transform_order += 0.1;
|
||||
|
|
|
@ -32,15 +32,20 @@ use update::ui_z_system;
|
|||
#[derive(Default)]
|
||||
pub struct UiPlugin;
|
||||
|
||||
pub mod stage {
|
||||
pub const UI: &'static str = "ui";
|
||||
}
|
||||
|
||||
impl AppPlugin for UiPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.init_resource::<FlexSurface>()
|
||||
.add_system_to_stage(stage::PRE_UPDATE, ui_focus_system.system())
|
||||
.add_stage_before(bevy_app::stage::POST_UPDATE, stage::UI)
|
||||
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, ui_focus_system.system())
|
||||
// add these stages to front because these must run before transform update systems
|
||||
.add_system_to_stage_front(stage::POST_UPDATE, flex_node_system.system())
|
||||
.add_system_to_stage_front(stage::POST_UPDATE, ui_z_system.system())
|
||||
.add_system_to_stage_front(stage::POST_UPDATE, widget::text_system.system())
|
||||
.add_system_to_stage_front(stage::POST_UPDATE, widget::image_node_system.system())
|
||||
.add_system_to_stage(stage::UI, widget::text_system.system())
|
||||
.add_system_to_stage(stage::UI, widget::image_node_system.system())
|
||||
.add_system_to_stage(stage::UI, ui_z_system.system())
|
||||
.add_system_to_stage(stage::UI, flex_node_system.system())
|
||||
.add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system.system());
|
||||
|
||||
let resources = app.resources();
|
||||
|
|
|
@ -3,10 +3,17 @@ use bevy_asset::{Assets, Handle};
|
|||
use bevy_ecs::Resources;
|
||||
use bevy_render::{
|
||||
camera::ActiveCameras,
|
||||
pass::{
|
||||
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||
},
|
||||
pipeline::*,
|
||||
render_graph::{base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode, WindowTextureNode},
|
||||
render_graph::{
|
||||
base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
texture::TextureFormat, prelude::{Color, MainPass}, pass::{RenderPassColorAttachmentDescriptor, PassDescriptor, TextureAttachment, LoadOp, Operations, RenderPassDepthStencilAttachmentDescriptor},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
|
||||
pub const UI_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||
|
@ -121,11 +128,9 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||
|
||||
// setup ui camera
|
||||
self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA));
|
||||
self.add_node_edge(node::UI_CAMERA, node::UI_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::UI_CAMERA, node::UI_PASS).unwrap();
|
||||
self.add_system_node(node::NODE, RenderResourcesNode::<Node>::new(true));
|
||||
self.add_node_edge(node::NODE, node::UI_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::NODE, node::UI_PASS).unwrap();
|
||||
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
||||
active_cameras.add(camera::UI_CAMERA);
|
||||
self
|
||||
|
|
|
@ -12,7 +12,7 @@ pub fn ui_z_system(
|
|||
mut node_query: Query<(Entity, &Node, &mut LocalTransform)>,
|
||||
children_query: Query<&Children>,
|
||||
) {
|
||||
let mut window_z = 0.0;
|
||||
let mut current_global_z = 0.0;
|
||||
|
||||
// PERF: we can probably avoid an allocation here by making root_node_query and node_query non-overlapping
|
||||
let root_nodes = (&mut root_node_query.iter())
|
||||
|
@ -24,11 +24,11 @@ pub fn ui_z_system(
|
|||
&children_query,
|
||||
&mut node_query,
|
||||
entity,
|
||||
Some(window_z),
|
||||
Some(window_z),
|
||||
Some(current_global_z),
|
||||
Some(current_global_z),
|
||||
&mut update_node_entity,
|
||||
) {
|
||||
window_z = result;
|
||||
current_global_z = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,18 +36,20 @@ pub fn ui_z_system(
|
|||
fn update_node_entity(
|
||||
node_query: &mut Query<(Entity, &Node, &mut LocalTransform)>,
|
||||
entity: Entity,
|
||||
_parent_result: Option<f32>,
|
||||
parent_result: Option<f32>,
|
||||
previous_result: Option<f32>,
|
||||
) -> Option<f32> {
|
||||
let mut transform = node_query.get_mut::<LocalTransform>(entity).unwrap();
|
||||
let mut z = UI_Z_STEP;
|
||||
if let Some(previous_z) = previous_result {
|
||||
z += previous_z;
|
||||
let parent_global_z = parent_result.unwrap();
|
||||
if let Some(previous_global_z) = previous_result {
|
||||
z += previous_global_z - parent_global_z;
|
||||
};
|
||||
let global_z = z + parent_global_z;
|
||||
|
||||
let mut position = transform.w_axis();
|
||||
position.set_z(z);
|
||||
transform.set_w_axis(position);
|
||||
|
||||
return Some(z);
|
||||
return Some(global_z);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue