use bevy::prelude::*;
pub(crate) const KIND_LAYER_CAMERA: &str = "layerCamera";
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CameraCandidate {
pub entity: Entity,
pub is_default_ui: bool,
pub window_target: bool,
}
impl CameraCandidate {
fn rank(&self) -> u8 {
(self.is_default_ui as u8) << 1 | self.window_target as u8
}
}
pub fn pick_stock_camera(candidates: impl IntoIterator<Item = CameraCandidate>) -> Option<Entity> {
candidates
.into_iter()
.min_by_key(|c| std::cmp::Reverse(c.rank()))
.map(|c| c.entity)
}
pub(crate) fn warn_skipped(camera: Entity, stock: Entity) {
crate::diag::log_warn(
KIND_LAYER_CAMERA,
&format!("{camera:?}"),
&format!(
"promoted layers under camera {camera:?} are skipped (their subtrees render \
unpromoted): v1 composites layers on a single UI camera, {stock:?} this session — \
opacity/filter/transform3d/morph styles inside a <surface> or under a second UI \
camera have no effect"
),
);
}
#[cfg(test)]
mod tests {
use super::*;
fn cand(index: u32, is_default_ui: bool, window_target: bool) -> CameraCandidate {
CameraCandidate {
entity: Entity::from_raw_u32(index).unwrap(),
is_default_ui,
window_target,
}
}
#[test]
fn default_ui_camera_wins_regardless_of_order() {
let surface = cand(1, false, false);
let main = cand(2, true, true);
assert_eq!(pick_stock_camera([surface, main]), Some(main.entity));
assert_eq!(pick_stock_camera([main, surface]), Some(main.entity));
}
#[test]
fn window_target_then_first_seen() {
let image_a = cand(1, false, false);
let window = cand(2, false, true);
let image_b = cand(3, false, false);
assert_eq!(
pick_stock_camera([image_a, window, image_b]),
Some(window.entity)
);
assert_eq!(
pick_stock_camera([image_a, image_b]),
Some(image_a.entity),
"ties keep the first seen"
);
assert_eq!(pick_stock_camera([]), None);
}
}