Path: blob/main/crates/bevy_ui_render/src/debug_overlay.rs
6849 views
use super::ExtractedUiItem;1use super::ExtractedUiNode;2use super::ExtractedUiNodes;3use super::NodeType;4use super::UiCameraMap;5use crate::shader_flags;6use bevy_asset::AssetId;7use bevy_camera::visibility::InheritedVisibility;8use bevy_color::Hsla;9use bevy_ecs::entity::Entity;10use bevy_ecs::prelude::ReflectResource;11use bevy_ecs::resource::Resource;12use bevy_ecs::system::Commands;13use bevy_ecs::system::Query;14use bevy_ecs::system::Res;15use bevy_ecs::system::ResMut;16use bevy_math::Rect;17use bevy_math::Vec2;18use bevy_reflect::Reflect;19use bevy_render::sync_world::TemporaryRenderEntity;20use bevy_render::Extract;21use bevy_sprite::BorderRect;22use bevy_ui::ui_transform::UiGlobalTransform;23use bevy_ui::CalculatedClip;24use bevy_ui::ComputedNode;25use bevy_ui::ComputedUiTargetCamera;26use bevy_ui::UiStack;2728/// Configuration for the UI debug overlay29#[derive(Resource, Reflect)]30#[reflect(Resource)]31pub struct UiDebugOptions {32/// Set to true to enable the UI debug overlay33pub enabled: bool,34/// Width of the overlay's lines in logical pixels35pub line_width: f32,36/// Show outlines for non-visible UI nodes37pub show_hidden: bool,38/// Show outlines for clipped sections of UI nodes39pub show_clipped: bool,40}4142impl UiDebugOptions {43pub fn toggle(&mut self) {44self.enabled = !self.enabled;45}46}4748impl Default for UiDebugOptions {49fn default() -> Self {50Self {51enabled: false,52line_width: 1.,53show_hidden: false,54show_clipped: false,55}56}57}5859pub fn extract_debug_overlay(60mut commands: Commands,61debug_options: Extract<Res<UiDebugOptions>>,62mut extracted_uinodes: ResMut<ExtractedUiNodes>,63uinode_query: Extract<64Query<(65Entity,66&ComputedNode,67&UiGlobalTransform,68&InheritedVisibility,69Option<&CalculatedClip>,70&ComputedUiTargetCamera,71)>,72>,73ui_stack: Extract<Res<UiStack>>,74camera_map: Extract<UiCameraMap>,75) {76if !debug_options.enabled {77return;78}7980let mut camera_mapper = camera_map.get_mapper();8182for (entity, uinode, transform, visibility, maybe_clip, computed_target) in &uinode_query {83if !debug_options.show_hidden && !visibility.get() {84continue;85}8687let Some(extracted_camera_entity) = camera_mapper.map(computed_target) else {88continue;89};9091// Extract a border box to display an outline for every UI Node in the layout92extracted_uinodes.uinodes.push(ExtractedUiNode {93render_entity: commands.spawn(TemporaryRenderEntity).id(),94// Add a large number to the UI node's stack index so that the overlay is always drawn on top95z_order: (ui_stack.uinodes.len() as u32 + uinode.stack_index()) as f32,96clip: maybe_clip97.filter(|_| !debug_options.show_clipped)98.map(|clip| clip.clip),99image: AssetId::default(),100extracted_camera_entity,101transform: transform.into(),102item: ExtractedUiItem::Node {103color: Hsla::sequential_dispersed(entity.index()).into(),104rect: Rect {105min: Vec2::ZERO,106max: uinode.size,107},108atlas_scaling: None,109flip_x: false,110flip_y: false,111border: BorderRect::all(debug_options.line_width / uinode.inverse_scale_factor()),112border_radius: uinode.border_radius(),113node_type: NodeType::Border(shader_flags::BORDER_ALL),114},115main_entity: entity.into(),116});117}118}119120121