bevy_mod_outline/src/computed.rs

109 lines
3.4 KiB
Rust
Raw Normal View History

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.
#[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,
pub(crate) inherited: Option<Entity>,
}
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.
#[derive(Clone, Component, Default)]
2022-11-17 22:15:13 +00:00
pub struct InheritOutlineDepth;
#[allow(clippy::type_complexity)]
2022-11-17 22:15:13 +00:00
pub(crate) fn compute_outline_depth(
mut root_query: Query<
(
Entity,
2022-11-17 22:15:13 +00:00
&mut ComputedOutlineDepth,
&GlobalTransform,
Changed<GlobalTransform>,
2022-11-21 23:46:36 +00:00
Option<(&SetOutlineDepth, Changed<SetOutlineDepth>)>,
Option<&Children>,
),
2022-11-17 22:15:13 +00:00
Without<InheritOutlineDepth>,
>,
mut computed_query: Query<&mut ComputedOutlineDepth, With<InheritOutlineDepth>>,
child_query: Query<&Children>,
) {
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
};
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;
computed.inherited = None;
}
if let Some(cs) = children {
for child in cs.iter() {
2022-11-17 22:15:13 +00:00
propagate_outline_depth(
&computed,
2022-11-21 23:46:36 +00:00
changed,
entity,
*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,
parent: Entity,
entity: Entity,
computed_query: &mut Query<&mut ComputedOutlineDepth, With<InheritOutlineDepth>>,
child_query: &Query<&Children>,
) {
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 {
*computed = root_computed.clone();
computed.inherited = Some(parent);
}
if let Ok(cs) = child_query.get(entity) {
for child in cs.iter() {
2022-11-17 22:15:13 +00:00
propagate_outline_depth(
root_computed,
2022-11-21 23:46:36 +00:00
changed,
entity,
*child,
computed_query,
child_query,
);
}
}
}
}