use crate::{ BorderRadius, ContentSize, DefaultUiCamera, Display, Node, Outline, OverflowAxis, ScrollPosition, Style, TargetCamera, UiChildren, UiRootNodes, UiScale, }; use bevy_ecs::{ change_detection::{DetectChanges, DetectChangesMut}, entity::{Entity, EntityHashMap, EntityHashSet}, event::EventReader, query::With, removal_detection::RemovedComponents, system::{Commands, Local, Query, Res, ResMut, SystemParam}, world::Ref, }; use bevy_hierarchy::Children; use bevy_math::{UVec2, Vec2}; use bevy_render::camera::{Camera, NormalizedRenderTarget}; use bevy_sprite::BorderRect; use bevy_transform::components::Transform; use bevy_utils::tracing::warn; use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; use thiserror::Error; use ui_surface::UiSurface; #[cfg(feature = "bevy_text")] use bevy_text::CosmicBuffer; #[cfg(feature = "bevy_text")] use bevy_text::CosmicFontSystem; mod convert; pub mod debug; pub(crate) mod ui_surface; pub struct LayoutContext { pub scale_factor: f32, pub physical_size: Vec2, pub min_size: f32, pub max_size: f32, } impl LayoutContext { pub const DEFAULT: Self = Self { scale_factor: 1.0, physical_size: Vec2::ZERO, min_size: 0.0, max_size: 0.0, }; /// create new a [`LayoutContext`] from the window's physical size and scale factor fn new(scale_factor: f32, physical_size: Vec2) -> Self { Self { scale_factor, physical_size, min_size: physical_size.x.min(physical_size.y), max_size: physical_size.x.max(physical_size.y), } } } impl Default for LayoutContext { fn default() -> Self { Self::DEFAULT } } #[derive(Debug, Error)] pub enum LayoutError { #[error("Invalid hierarchy")] InvalidHierarchy, #[error("Taffy error: {0}")] TaffyError(#[from] taffy::TaffyError), } #[doc(hidden)] #[derive(SystemParam)] pub struct UiLayoutSystemRemovedComponentParam<'w, 's> { removed_cameras: RemovedComponents<'w, 's, Camera>, removed_children: RemovedComponents<'w, 's, Children>, removed_content_sizes: RemovedComponents<'w, 's, ContentSize>, removed_nodes: RemovedComponents<'w, 's, Node>, } #[doc(hidden)] #[derive(Default)] pub struct UiLayoutSystemBuffers { interned_root_nodes: Vec>, resized_windows: EntityHashSet, camera_layout_info: EntityHashMap, } struct CameraLayoutInfo { size: UVec2, resized: bool, scale_factor: f32, root_nodes: Vec, } /// Updates the UI's layout tree, computes the new layout geometry and then updates the sizes and transforms of all the UI nodes. #[allow(clippy::too_many_arguments)] pub fn ui_layout_system( mut commands: Commands, mut buffers: Local, primary_window: Query<(Entity, &Window), With>, camera_data: (Query<(Entity, &Camera)>, DefaultUiCamera), ui_scale: Res, mut scale_factor_events: EventReader, mut resize_events: EventReader, mut ui_surface: ResMut, root_nodes: UiRootNodes, mut style_query: Query< ( Entity, Ref