2022-11-17 00:25:54 +00:00
|
|
|
use bevy::prelude::*;
|
|
|
|
|
2023-02-21 21:12:44 +00:00
|
|
|
use crate::uniforms::DepthMode;
|
|
|
|
|
2022-11-17 22:15:13 +00:00
|
|
|
/// A component for storing the computed depth at which the outline lies.
|
2022-11-17 00:25:54 +00:00
|
|
|
#[derive(Clone, Component, Default)]
|
2022-11-17 22:15:13 +00:00
|
|
|
pub struct ComputedOutlineDepth {
|
2023-02-21 21:12:44 +00:00
|
|
|
pub(crate) world_origin: Vec3,
|
|
|
|
pub(crate) depth_mode: DepthMode,
|
2023-05-17 17:43:12 +00:00
|
|
|
pub(crate) inherited: Option<Entity>,
|
2022-11-17 00:25:54 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 23:46:36 +00:00
|
|
|
/// A component which specifies how the outline depth should be computed.
|
|
|
|
#[derive(Clone, Component)]
|
|
|
|
#[non_exhaustive]
|
|
|
|
pub enum SetOutlineDepth {
|
|
|
|
/// A flat plane facing the camera and intersecting the specified point in model-space.
|
|
|
|
Flat { model_origin: Vec3 },
|
2023-01-03 02:06:45 +00:00
|
|
|
/// Real model-space.
|
|
|
|
Real,
|
2022-11-21 23:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A component which specifies that this outline lies at the same depth as its parent.
|
2022-11-17 00:25:54 +00:00
|
|
|
#[derive(Clone, Component, Default)]
|
2022-11-17 22:15:13 +00:00
|
|
|
pub struct InheritOutlineDepth;
|
2022-11-17 00:25:54 +00:00
|
|
|
|
|
|
|
#[allow(clippy::type_complexity)]
|
2022-11-17 22:15:13 +00:00
|
|
|
pub(crate) fn compute_outline_depth(
|
2022-11-17 00:25:54 +00:00
|
|
|
mut root_query: Query<
|
|
|
|
(
|
2023-05-17 17:43:12 +00:00
|
|
|
Entity,
|
2022-11-17 22:15:13 +00:00
|
|
|
&mut ComputedOutlineDepth,
|
2022-11-17 00:25:54 +00:00
|
|
|
&GlobalTransform,
|
|
|
|
Changed<GlobalTransform>,
|
2022-11-21 23:46:36 +00:00
|
|
|
Option<(&SetOutlineDepth, Changed<SetOutlineDepth>)>,
|
2023-05-17 17:43:12 +00:00
|
|
|
Option<&Children>,
|
2022-11-17 00:25:54 +00:00
|
|
|
),
|
2022-11-17 22:15:13 +00:00
|
|
|
Without<InheritOutlineDepth>,
|
2022-11-17 00:25:54 +00:00
|
|
|
>,
|
2023-05-17 17:43:12 +00:00
|
|
|
mut computed_query: Query<&mut ComputedOutlineDepth, With<InheritOutlineDepth>>,
|
|
|
|
child_query: Query<&Children>,
|
2022-11-17 00:25:54 +00:00
|
|
|
) {
|
2023-05-17 17:43:12 +00:00
|
|
|
for (entity, mut computed, transform, changed_transform, set_depth, children) in
|
|
|
|
root_query.iter_mut()
|
|
|
|
{
|
|
|
|
let changed = !computed.depth_mode.is_valid()
|
|
|
|
|| computed.inherited.is_some()
|
|
|
|
|| changed_transform
|
|
|
|
|| set_depth.filter(|(_, c)| *c).is_some();
|
2022-11-21 23:46:36 +00:00
|
|
|
if changed {
|
2023-02-21 21:12:44 +00:00
|
|
|
let (origin, depth_mode) = if let Some((sd, _)) = set_depth {
|
2022-11-21 23:46:36 +00:00
|
|
|
match sd {
|
|
|
|
SetOutlineDepth::Flat {
|
|
|
|
model_origin: origin,
|
2023-02-21 21:12:44 +00:00
|
|
|
} => (*origin, DepthMode::Flat),
|
|
|
|
SetOutlineDepth::Real => (Vec3::NAN, DepthMode::Real),
|
2022-11-21 23:46:36 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-02-21 21:12:44 +00:00
|
|
|
(Vec3::ZERO, DepthMode::Flat)
|
2022-11-21 23:46:36 +00:00
|
|
|
};
|
2022-11-17 00:25:54 +00:00
|
|
|
let matrix = transform.compute_matrix();
|
2023-02-21 21:12:44 +00:00
|
|
|
computed.world_origin = matrix.project_point3(origin);
|
|
|
|
computed.depth_mode = depth_mode;
|
2023-05-17 17:43:12 +00:00
|
|
|
computed.inherited = None;
|
2022-11-17 00:25:54 +00:00
|
|
|
}
|
2023-05-17 17:43:12 +00:00
|
|
|
if let Some(cs) = children {
|
2022-11-17 00:25:54 +00:00
|
|
|
for child in cs.iter() {
|
2022-11-17 22:15:13 +00:00
|
|
|
propagate_outline_depth(
|
2022-11-17 00:25:54 +00:00
|
|
|
&computed,
|
2022-11-21 23:46:36 +00:00
|
|
|
changed,
|
2023-05-17 17:43:12 +00:00
|
|
|
entity,
|
2022-11-17 00:25:54 +00:00
|
|
|
*child,
|
|
|
|
&mut computed_query,
|
|
|
|
&child_query,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-17 22:15:13 +00:00
|
|
|
fn propagate_outline_depth(
|
|
|
|
root_computed: &ComputedOutlineDepth,
|
2022-11-21 23:46:36 +00:00
|
|
|
mut changed: bool,
|
2023-05-17 17:43:12 +00:00
|
|
|
parent: Entity,
|
2022-11-17 00:25:54 +00:00
|
|
|
entity: Entity,
|
2023-05-17 17:43:12 +00:00
|
|
|
computed_query: &mut Query<&mut ComputedOutlineDepth, With<InheritOutlineDepth>>,
|
|
|
|
child_query: &Query<&Children>,
|
2022-11-17 00:25:54 +00:00
|
|
|
) {
|
2023-05-17 17:43:12 +00:00
|
|
|
if let Ok(mut computed) = computed_query.get_mut(entity) {
|
|
|
|
changed |= !computed.depth_mode.is_valid() | (computed.inherited != Some(parent));
|
2022-11-21 23:46:36 +00:00
|
|
|
if changed {
|
2022-11-17 00:25:54 +00:00
|
|
|
*computed = root_computed.clone();
|
2023-05-17 17:43:12 +00:00
|
|
|
computed.inherited = Some(parent);
|
2022-11-17 00:25:54 +00:00
|
|
|
}
|
2023-05-17 17:43:12 +00:00
|
|
|
if let Ok(cs) = child_query.get(entity) {
|
2022-11-17 00:25:54 +00:00
|
|
|
for child in cs.iter() {
|
2022-11-17 22:15:13 +00:00
|
|
|
propagate_outline_depth(
|
2022-11-17 00:25:54 +00:00
|
|
|
root_computed,
|
2022-11-21 23:46:36 +00:00
|
|
|
changed,
|
2023-05-17 17:43:12 +00:00
|
|
|
entity,
|
2022-11-17 00:25:54 +00:00
|
|
|
*child,
|
|
|
|
computed_query,
|
|
|
|
child_query,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|