1use bevy::camera::Viewport;
2use bevy::prelude::*;
3use bevy::ui::UiGlobalTransform;
4use bevy::window::PrimaryWindow;
5
6use crate::focus::{CuBevyMonSurface, CuBevyMonSurfaceNode, surface_local_rect};
7
8#[derive(Component, Clone, Copy, Debug, PartialEq, Eq)]
9pub struct CuBevyMonViewportSurface(pub CuBevyMonSurface);
10
11pub(crate) fn sync_camera_viewports_to_surfaces(
12 window: Single<&Window, With<PrimaryWindow>>,
13 surfaces: Query<(&ComputedNode, &UiGlobalTransform, &CuBevyMonSurfaceNode)>,
14 mut cameras: Query<(&CuBevyMonViewportSurface, &mut Camera)>,
15) {
16 let window_size = Vec2::new(
17 window.physical_width() as f32,
18 window.physical_height() as f32,
19 );
20
21 for (target_surface, mut camera) in &mut cameras {
22 let Some((node, transform, _)) = surfaces
23 .iter()
24 .find(|(_, _, surface)| surface.0 == target_surface.0)
25 else {
26 camera.viewport = None;
27 continue;
28 };
29
30 let rect = surface_local_rect(node.content_box(), transform);
31 let min = rect.min.max(Vec2::ZERO);
32 let max = rect.max.min(window_size);
33 let size = max - min;
34
35 if size.x <= 1.0 || size.y <= 1.0 {
36 camera.viewport = None;
37 continue;
38 }
39
40 camera.viewport = Some(Viewport {
41 physical_position: UVec2::new(min.x.floor() as u32, min.y.floor() as u32),
42 physical_size: UVec2::new(size.x.floor() as u32, size.y.floor() as u32),
43 ..default()
44 });
45 }
46}