Skip to main content

bevy_ui_render/
debug_overlay.rs

1use super::ExtractedUiItem;
2use super::ExtractedUiNode;
3use super::ExtractedUiNodes;
4use super::NodeType;
5use super::UiCameraMap;
6use crate::shader_flags;
7use bevy_asset::AssetId;
8use bevy_camera::visibility::InheritedVisibility;
9use bevy_color::Hsla;
10use bevy_color::LinearRgba;
11use bevy_ecs::entity::Entity;
12use bevy_ecs::prelude::Component;
13use bevy_ecs::prelude::ReflectComponent;
14use bevy_ecs::prelude::ReflectResource;
15use bevy_ecs::resource::Resource;
16use bevy_ecs::system::Commands;
17use bevy_ecs::system::Query;
18use bevy_ecs::system::Res;
19use bevy_ecs::system::ResMut;
20use bevy_math::Affine2;
21use bevy_math::Rect;
22use bevy_math::Vec2;
23use bevy_reflect::Reflect;
24use bevy_render::sync_world::TemporaryRenderEntity;
25use bevy_render::Extract;
26use bevy_sprite::BorderRect;
27use bevy_ui::ui_transform::UiGlobalTransform;
28use bevy_ui::CalculatedClip;
29use bevy_ui::ComputedNode;
30use bevy_ui::ComputedStackIndex;
31use bevy_ui::ComputedUiTargetCamera;
32use bevy_ui::ResolvedBorderRadius;
33use bevy_ui::UiStack;
34
35/// Configuration for the UI debug overlay
36///
37/// Can be added as a `Component` to individual UI node entities.
38/// This overwrites the default [`GlobalUiDebugOptions`] resource.
39#[derive(impl bevy_ecs::component::Component for UiDebugOptions where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {
    const STORAGE_TYPE: bevy_ecs::component::StorageType =
        bevy_ecs::component::StorageType::Table;
    type Mutability = bevy_ecs::component::Mutable;
    fn register_required_components(_requiree:
            bevy_ecs::component::ComponentId,
        required_components:
            &mut bevy_ecs::component::RequiredComponentsRegistrator) {}
    fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
        use bevy_ecs::component::{
            DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
        };
        (&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
    }
    fn relationship_accessor()
        ->
            ::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
        ::core::option::Option::None
    }
}Component, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for UiDebugOptions where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectComponent, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <bool as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Option<LinearRgba> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for UiDebugOptions where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<bool>("enabled"),
                                                bevy_reflect::NamedField::new::<bool>("outline_border_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_padding_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_content_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_scrollbars"),
                                                bevy_reflect::NamedField::new::<f32>("line_width"),
                                                bevy_reflect::NamedField::new::<Option<LinearRgba>>("line_color_override"),
                                                bevy_reflect::NamedField::new::<bool>("show_hidden"),
                                                bevy_reflect::NamedField::new::<bool>("show_clipped"),
                                                bevy_reflect::NamedField::new::<bool>("ignore_border_radius")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for UiDebugOptions where  {
            fn type_path() -> &'static str {
                "bevy_ui_render::debug_overlay::UiDebugOptions"
            }
            fn short_type_path() -> &'static str { "UiDebugOptions" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("UiDebugOptions")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_ui_render::debug_overlay".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_ui_render::debug_overlay")
            }
        }
        impl bevy_reflect::Reflect for UiDebugOptions where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<UiDebugOptions
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::structs::Struct for UiDebugOptions where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "enabled" => ::core::option::Option::Some(&self.enabled),
                    "outline_border_box" =>
                        ::core::option::Option::Some(&self.outline_border_box),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(&self.outline_padding_box),
                    "outline_content_box" =>
                        ::core::option::Option::Some(&self.outline_content_box),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(&self.outline_scrollbars),
                    "line_width" =>
                        ::core::option::Option::Some(&self.line_width),
                    "line_color_override" =>
                        ::core::option::Option::Some(&self.line_color_override),
                    "show_hidden" =>
                        ::core::option::Option::Some(&self.show_hidden),
                    "show_clipped" =>
                        ::core::option::Option::Some(&self.show_clipped),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(&self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "enabled" =>
                        ::core::option::Option::Some(&mut self.enabled),
                    "outline_border_box" =>
                        ::core::option::Option::Some(&mut self.outline_border_box),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(&mut self.outline_padding_box),
                    "outline_content_box" =>
                        ::core::option::Option::Some(&mut self.outline_content_box),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(&mut self.outline_scrollbars),
                    "line_width" =>
                        ::core::option::Option::Some(&mut self.line_width),
                    "line_color_override" =>
                        ::core::option::Option::Some(&mut self.line_color_override),
                    "show_hidden" =>
                        ::core::option::Option::Some(&mut self.show_hidden),
                    "show_clipped" =>
                        ::core::option::Option::Some(&mut self.show_clipped),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(&mut self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.enabled),
                    1usize =>
                        ::core::option::Option::Some(&self.outline_border_box),
                    2usize =>
                        ::core::option::Option::Some(&self.outline_padding_box),
                    3usize =>
                        ::core::option::Option::Some(&self.outline_content_box),
                    4usize =>
                        ::core::option::Option::Some(&self.outline_scrollbars),
                    5usize => ::core::option::Option::Some(&self.line_width),
                    6usize =>
                        ::core::option::Option::Some(&self.line_color_override),
                    7usize => ::core::option::Option::Some(&self.show_hidden),
                    8usize => ::core::option::Option::Some(&self.show_clipped),
                    9usize =>
                        ::core::option::Option::Some(&self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.enabled),
                    1usize =>
                        ::core::option::Option::Some(&mut self.outline_border_box),
                    2usize =>
                        ::core::option::Option::Some(&mut self.outline_padding_box),
                    3usize =>
                        ::core::option::Option::Some(&mut self.outline_content_box),
                    4usize =>
                        ::core::option::Option::Some(&mut self.outline_scrollbars),
                    5usize =>
                        ::core::option::Option::Some(&mut self.line_width),
                    6usize =>
                        ::core::option::Option::Some(&mut self.line_color_override),
                    7usize =>
                        ::core::option::Option::Some(&mut self.show_hidden),
                    8usize =>
                        ::core::option::Option::Some(&mut self.show_clipped),
                    9usize =>
                        ::core::option::Option::Some(&mut self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("enabled"),
                    1usize =>
                        ::core::option::Option::Some("outline_border_box"),
                    2usize =>
                        ::core::option::Option::Some("outline_padding_box"),
                    3usize =>
                        ::core::option::Option::Some("outline_content_box"),
                    4usize =>
                        ::core::option::Option::Some("outline_scrollbars"),
                    5usize => ::core::option::Option::Some("line_width"),
                    6usize =>
                        ::core::option::Option::Some("line_color_override"),
                    7usize => ::core::option::Option::Some("show_hidden"),
                    8usize => ::core::option::Option::Some("show_clipped"),
                    9usize =>
                        ::core::option::Option::Some("ignore_border_radius"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "enabled" => ::core::option::Option::Some(0usize),
                    "outline_border_box" =>
                        ::core::option::Option::Some(1usize),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(2usize),
                    "outline_content_box" =>
                        ::core::option::Option::Some(3usize),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(4usize),
                    "line_width" => ::core::option::Option::Some(5usize),
                    "line_color_override" =>
                        ::core::option::Option::Some(6usize),
                    "show_hidden" => ::core::option::Option::Some(7usize),
                    "show_clipped" => ::core::option::Option::Some(8usize),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(9usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 10usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("enabled",
                    bevy_reflect::PartialReflect::to_dynamic(&self.enabled));
                dynamic.insert_boxed("outline_border_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_border_box));
                dynamic.insert_boxed("outline_padding_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_padding_box));
                dynamic.insert_boxed("outline_content_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_content_box));
                dynamic.insert_boxed("outline_scrollbars",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_scrollbars));
                dynamic.insert_boxed("line_width",
                    bevy_reflect::PartialReflect::to_dynamic(&self.line_width));
                dynamic.insert_boxed("line_color_override",
                    bevy_reflect::PartialReflect::to_dynamic(&self.line_color_override));
                dynamic.insert_boxed("show_hidden",
                    bevy_reflect::PartialReflect::to_dynamic(&self.show_hidden));
                dynamic.insert_boxed("show_clipped",
                    bevy_reflect::PartialReflect::to_dynamic(&self.show_clipped));
                dynamic.insert_boxed("ignore_border_radius",
                    bevy_reflect::PartialReflect::to_dynamic(&self.ignore_border_radius));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for UiDebugOptions where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
                            enabled: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.enabled)?,
                            outline_border_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_border_box)?,
                            outline_padding_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_padding_box)?,
                            outline_content_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_content_box)?,
                            outline_scrollbars: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_scrollbars)?,
                            line_width: <f32 as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.line_width)?,
                            line_color_override: <Option<LinearRgba> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.line_color_override)?,
                            show_hidden: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.show_hidden)?,
                            show_clipped: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.show_clipped)?,
                            ignore_border_radius: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.ignore_border_radius)?,
                        }))
            }
        }
        impl bevy_reflect::FromReflect for UiDebugOptions where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            enabled: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "enabled")?)?,
                            outline_border_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_border_box")?)?,
                            outline_padding_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_padding_box")?)?,
                            outline_content_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_content_box")?)?,
                            outline_scrollbars: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_scrollbars")?)?,
                            line_width: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "line_width")?)?,
                            line_color_override: <Option<LinearRgba> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "line_color_override")?)?,
                            show_hidden: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "show_hidden")?)?,
                            show_clipped: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "show_clipped")?)?,
                            ignore_border_radius: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "ignore_border_radius")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::marker::Copy for UiDebugOptions { }Copy, #[automatically_derived]
impl ::core::clone::Clone for UiDebugOptions {
    #[inline]
    fn clone(&self) -> UiDebugOptions {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<f32>;
        let _: ::core::clone::AssertParamIsClone<Option<LinearRgba>>;
        *self
    }
}Clone)]
40#[reflect(Component)]
41pub struct UiDebugOptions {
42    /// Set to true to enable the UI debug overlay
43    pub enabled: bool,
44    /// Show outlines for the border boxes of UI nodes
45    pub outline_border_box: bool,
46    /// Show outlines for the padding boxes of UI nodes
47    pub outline_padding_box: bool,
48    /// Show outlines for the content boxes of UI nodes
49    pub outline_content_box: bool,
50    /// Show outlines for the scrollbar regions of UI nodes
51    pub outline_scrollbars: bool,
52    /// Width of the overlay's lines in logical pixels
53    pub line_width: f32,
54    /// Override Color for the overlay's lines
55    pub line_color_override: Option<LinearRgba>,
56    /// Show outlines for non-visible UI nodes
57    pub show_hidden: bool,
58    /// Show outlines for clipped sections of UI nodes
59    pub show_clipped: bool,
60    /// Draw outlines with sharp corners even if the UI nodes have border radii
61    pub ignore_border_radius: bool,
62}
63
64impl UiDebugOptions {
65    pub fn toggle(&mut self) {
66        self.enabled = !self.enabled;
67    }
68}
69
70impl Default for UiDebugOptions {
71    fn default() -> Self {
72        Self {
73            enabled: false,
74            line_width: 1.,
75            line_color_override: None,
76            show_hidden: false,
77            show_clipped: false,
78            ignore_border_radius: false,
79            outline_border_box: true,
80            outline_padding_box: false,
81            outline_content_box: false,
82            outline_scrollbars: false,
83        }
84    }
85}
86
87impl From<GlobalUiDebugOptions> for UiDebugOptions {
88    fn from(other: GlobalUiDebugOptions) -> Self {
89        Self {
90            enabled: other.enabled,
91            outline_border_box: other.outline_border_box,
92            outline_padding_box: other.outline_padding_box,
93            outline_content_box: other.outline_content_box,
94            outline_scrollbars: other.outline_scrollbars,
95            line_width: other.line_width,
96            line_color_override: other.line_color_override,
97            show_hidden: other.show_hidden,
98            show_clipped: other.show_clipped,
99            ignore_border_radius: other.ignore_border_radius,
100        }
101    }
102}
103
104/// Configuration for the UI debug overlay
105///
106/// A global `resource` that can be overridden by local component [`UiDebugOptions`] override on individual UI node entities
107#[derive(impl bevy_ecs::resource::Resource for GlobalUiDebugOptions where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for GlobalUiDebugOptions where
            {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectResource, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <bool as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Option<LinearRgba> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for GlobalUiDebugOptions where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<bool>("enabled"),
                                                bevy_reflect::NamedField::new::<bool>("outline_border_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_padding_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_content_box"),
                                                bevy_reflect::NamedField::new::<bool>("outline_scrollbars"),
                                                bevy_reflect::NamedField::new::<f32>("line_width"),
                                                bevy_reflect::NamedField::new::<Option<LinearRgba>>("line_color_override"),
                                                bevy_reflect::NamedField::new::<bool>("show_hidden"),
                                                bevy_reflect::NamedField::new::<bool>("show_clipped"),
                                                bevy_reflect::NamedField::new::<bool>("ignore_border_radius")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for GlobalUiDebugOptions where  {
            fn type_path() -> &'static str {
                "bevy_ui_render::debug_overlay::GlobalUiDebugOptions"
            }
            fn short_type_path() -> &'static str { "GlobalUiDebugOptions" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("GlobalUiDebugOptions")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_ui_render::debug_overlay".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_ui_render::debug_overlay")
            }
        }
        impl bevy_reflect::Reflect for GlobalUiDebugOptions where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<GlobalUiDebugOptions
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::structs::Struct for GlobalUiDebugOptions where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "enabled" => ::core::option::Option::Some(&self.enabled),
                    "outline_border_box" =>
                        ::core::option::Option::Some(&self.outline_border_box),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(&self.outline_padding_box),
                    "outline_content_box" =>
                        ::core::option::Option::Some(&self.outline_content_box),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(&self.outline_scrollbars),
                    "line_width" =>
                        ::core::option::Option::Some(&self.line_width),
                    "line_color_override" =>
                        ::core::option::Option::Some(&self.line_color_override),
                    "show_hidden" =>
                        ::core::option::Option::Some(&self.show_hidden),
                    "show_clipped" =>
                        ::core::option::Option::Some(&self.show_clipped),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(&self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "enabled" =>
                        ::core::option::Option::Some(&mut self.enabled),
                    "outline_border_box" =>
                        ::core::option::Option::Some(&mut self.outline_border_box),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(&mut self.outline_padding_box),
                    "outline_content_box" =>
                        ::core::option::Option::Some(&mut self.outline_content_box),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(&mut self.outline_scrollbars),
                    "line_width" =>
                        ::core::option::Option::Some(&mut self.line_width),
                    "line_color_override" =>
                        ::core::option::Option::Some(&mut self.line_color_override),
                    "show_hidden" =>
                        ::core::option::Option::Some(&mut self.show_hidden),
                    "show_clipped" =>
                        ::core::option::Option::Some(&mut self.show_clipped),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(&mut self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.enabled),
                    1usize =>
                        ::core::option::Option::Some(&self.outline_border_box),
                    2usize =>
                        ::core::option::Option::Some(&self.outline_padding_box),
                    3usize =>
                        ::core::option::Option::Some(&self.outline_content_box),
                    4usize =>
                        ::core::option::Option::Some(&self.outline_scrollbars),
                    5usize => ::core::option::Option::Some(&self.line_width),
                    6usize =>
                        ::core::option::Option::Some(&self.line_color_override),
                    7usize => ::core::option::Option::Some(&self.show_hidden),
                    8usize => ::core::option::Option::Some(&self.show_clipped),
                    9usize =>
                        ::core::option::Option::Some(&self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.enabled),
                    1usize =>
                        ::core::option::Option::Some(&mut self.outline_border_box),
                    2usize =>
                        ::core::option::Option::Some(&mut self.outline_padding_box),
                    3usize =>
                        ::core::option::Option::Some(&mut self.outline_content_box),
                    4usize =>
                        ::core::option::Option::Some(&mut self.outline_scrollbars),
                    5usize =>
                        ::core::option::Option::Some(&mut self.line_width),
                    6usize =>
                        ::core::option::Option::Some(&mut self.line_color_override),
                    7usize =>
                        ::core::option::Option::Some(&mut self.show_hidden),
                    8usize =>
                        ::core::option::Option::Some(&mut self.show_clipped),
                    9usize =>
                        ::core::option::Option::Some(&mut self.ignore_border_radius),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("enabled"),
                    1usize =>
                        ::core::option::Option::Some("outline_border_box"),
                    2usize =>
                        ::core::option::Option::Some("outline_padding_box"),
                    3usize =>
                        ::core::option::Option::Some("outline_content_box"),
                    4usize =>
                        ::core::option::Option::Some("outline_scrollbars"),
                    5usize => ::core::option::Option::Some("line_width"),
                    6usize =>
                        ::core::option::Option::Some("line_color_override"),
                    7usize => ::core::option::Option::Some("show_hidden"),
                    8usize => ::core::option::Option::Some("show_clipped"),
                    9usize =>
                        ::core::option::Option::Some("ignore_border_radius"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "enabled" => ::core::option::Option::Some(0usize),
                    "outline_border_box" =>
                        ::core::option::Option::Some(1usize),
                    "outline_padding_box" =>
                        ::core::option::Option::Some(2usize),
                    "outline_content_box" =>
                        ::core::option::Option::Some(3usize),
                    "outline_scrollbars" =>
                        ::core::option::Option::Some(4usize),
                    "line_width" => ::core::option::Option::Some(5usize),
                    "line_color_override" =>
                        ::core::option::Option::Some(6usize),
                    "show_hidden" => ::core::option::Option::Some(7usize),
                    "show_clipped" => ::core::option::Option::Some(8usize),
                    "ignore_border_radius" =>
                        ::core::option::Option::Some(9usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 10usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("enabled",
                    bevy_reflect::PartialReflect::to_dynamic(&self.enabled));
                dynamic.insert_boxed("outline_border_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_border_box));
                dynamic.insert_boxed("outline_padding_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_padding_box));
                dynamic.insert_boxed("outline_content_box",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_content_box));
                dynamic.insert_boxed("outline_scrollbars",
                    bevy_reflect::PartialReflect::to_dynamic(&self.outline_scrollbars));
                dynamic.insert_boxed("line_width",
                    bevy_reflect::PartialReflect::to_dynamic(&self.line_width));
                dynamic.insert_boxed("line_color_override",
                    bevy_reflect::PartialReflect::to_dynamic(&self.line_color_override));
                dynamic.insert_boxed("show_hidden",
                    bevy_reflect::PartialReflect::to_dynamic(&self.show_hidden));
                dynamic.insert_boxed("show_clipped",
                    bevy_reflect::PartialReflect::to_dynamic(&self.show_clipped));
                dynamic.insert_boxed("ignore_border_radius",
                    bevy_reflect::PartialReflect::to_dynamic(&self.ignore_border_radius));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for GlobalUiDebugOptions where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
                            enabled: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.enabled)?,
                            outline_border_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_border_box)?,
                            outline_padding_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_padding_box)?,
                            outline_content_box: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_content_box)?,
                            outline_scrollbars: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.outline_scrollbars)?,
                            line_width: <f32 as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.line_width)?,
                            line_color_override: <Option<LinearRgba> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.line_color_override)?,
                            show_hidden: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.show_hidden)?,
                            show_clipped: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.show_clipped)?,
                            ignore_border_radius: <bool as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.ignore_border_radius)?,
                        }))
            }
        }
        impl bevy_reflect::FromReflect for GlobalUiDebugOptions where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            enabled: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "enabled")?)?,
                            outline_border_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_border_box")?)?,
                            outline_padding_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_padding_box")?)?,
                            outline_content_box: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_content_box")?)?,
                            outline_scrollbars: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "outline_scrollbars")?)?,
                            line_width: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "line_width")?)?,
                            line_color_override: <Option<LinearRgba> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "line_color_override")?)?,
                            show_hidden: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "show_hidden")?)?,
                            show_clipped: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "show_clipped")?)?,
                            ignore_border_radius: <bool as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "ignore_border_radius")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::marker::Copy for GlobalUiDebugOptions { }Copy, #[automatically_derived]
impl ::core::clone::Clone for GlobalUiDebugOptions {
    #[inline]
    fn clone(&self) -> GlobalUiDebugOptions {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<f32>;
        let _: ::core::clone::AssertParamIsClone<Option<LinearRgba>>;
        *self
    }
}Clone)]
108#[reflect(Resource)]
109pub struct GlobalUiDebugOptions {
110    /// Set to true to enable the UI debug overlay
111    pub enabled: bool,
112    /// Show outlines for the border boxes of UI nodes
113    pub outline_border_box: bool,
114    /// Show outlines for the padding boxes of UI nodes
115    pub outline_padding_box: bool,
116    /// Show outlines for the content boxes of UI nodes
117    pub outline_content_box: bool,
118    /// Show outlines for the scrollbar regions of UI nodes
119    pub outline_scrollbars: bool,
120    /// Width of the overlay's lines in logical pixels
121    pub line_width: f32,
122    /// Override Color for the overlay's lines
123    pub line_color_override: Option<LinearRgba>,
124    /// Show outlines for non-visible UI nodes
125    pub show_hidden: bool,
126    /// Show outlines for clipped sections of UI nodes
127    pub show_clipped: bool,
128    /// Draw outlines with sharp corners even if the UI nodes have border radii
129    pub ignore_border_radius: bool,
130}
131
132impl GlobalUiDebugOptions {
133    pub fn toggle(&mut self) {
134        self.enabled = !self.enabled;
135    }
136}
137
138impl Default for GlobalUiDebugOptions {
139    fn default() -> Self {
140        Self {
141            enabled: false,
142            line_width: 1.,
143            line_color_override: None,
144            show_hidden: false,
145            show_clipped: false,
146            ignore_border_radius: false,
147            outline_border_box: true,
148            outline_padding_box: false,
149            outline_content_box: false,
150            outline_scrollbars: false,
151        }
152    }
153}
154
155impl From<UiDebugOptions> for GlobalUiDebugOptions {
156    fn from(other: UiDebugOptions) -> Self {
157        Self {
158            enabled: other.enabled,
159            outline_border_box: other.outline_border_box,
160            outline_padding_box: other.outline_padding_box,
161            outline_content_box: other.outline_content_box,
162            outline_scrollbars: other.outline_scrollbars,
163            line_width: other.line_width,
164            line_color_override: other.line_color_override,
165            show_hidden: other.show_hidden,
166            show_clipped: other.show_clipped,
167            ignore_border_radius: other.ignore_border_radius,
168        }
169    }
170}
171
172pub fn extract_debug_overlay(
173    mut commands: Commands,
174    debug_options: Extract<Res<GlobalUiDebugOptions>>,
175    mut extracted_uinodes: ResMut<ExtractedUiNodes>,
176    uinode_query: Extract<
177        Query<(
178            Entity,
179            &ComputedNode,
180            &ComputedStackIndex,
181            &UiGlobalTransform,
182            &InheritedVisibility,
183            Option<&CalculatedClip>,
184            &ComputedUiTargetCamera,
185            Option<&UiDebugOptions>,
186        )>,
187    >,
188    ui_stack: Extract<Res<UiStack>>,
189    camera_map: Extract<UiCameraMap>,
190) {
191    let mut camera_mapper = camera_map.get_mapper();
192
193    for (entity, uinode, stack_index, transform, visibility, maybe_clip, computed_target, debug) in
194        &uinode_query
195    {
196        let debug_options = debug.copied().unwrap_or((*debug_options.as_ref()).into());
197        if !debug_options.enabled {
198            continue;
199        }
200        if !debug_options.show_hidden && !visibility.get() {
201            continue;
202        }
203
204        let Some(extracted_camera_entity) = camera_mapper.map(computed_target) else {
205            continue;
206        };
207
208        let color = debug_options
209            .line_color_override
210            .unwrap_or_else(|| Hsla::sequential_dispersed(entity.index_u32()).into());
211        let z_order = (ui_stack.uinodes.len() as u32 + stack_index.0) as f32;
212        let border = BorderRect::all(debug_options.line_width / uinode.inverse_scale_factor());
213        let transform = transform.affine();
214
215        let mut push_outline = |rect: Rect, radius: ResolvedBorderRadius| {
216            if rect.is_empty() {
217                return;
218            }
219
220            extracted_uinodes.uinodes.push(ExtractedUiNode {
221                render_entity: commands.spawn(TemporaryRenderEntity).id(),
222                // Keep all overlays above UI, and nudge each type slightly in Z so ordering is stable.
223                z_order,
224                clip: maybe_clip
225                    .filter(|_| !debug_options.show_clipped)
226                    .map(|clip| clip.clip),
227                image: AssetId::default(),
228                extracted_camera_entity,
229                transform: transform * Affine2::from_translation(rect.center()),
230                item: ExtractedUiItem::Node {
231                    color,
232                    rect: Rect {
233                        min: Vec2::ZERO,
234                        max: rect.size(),
235                    },
236                    atlas_scaling: None,
237                    flip_x: false,
238                    flip_y: false,
239                    border,
240                    border_radius: radius,
241                    node_type: NodeType::Border(shader_flags::BORDER_ALL),
242                },
243                main_entity: entity.into(),
244            });
245        };
246
247        let border_box = Rect::from_center_size(Vec2::ZERO, uinode.size);
248
249        if debug_options.outline_border_box {
250            push_outline(border_box, uinode.border_radius());
251        }
252
253        if debug_options.outline_padding_box {
254            let mut padding_box = border_box;
255            padding_box.min += uinode.border.min_inset;
256            padding_box.max -= uinode.border.max_inset;
257            push_outline(padding_box, uinode.inner_radius());
258        }
259
260        if debug_options.outline_content_box {
261            let mut content_box = border_box;
262            let content_inset = uinode.content_inset();
263            content_box.min += content_inset.min_inset;
264            content_box.max -= content_inset.max_inset;
265            push_outline(content_box, ResolvedBorderRadius::ZERO);
266        }
267
268        if debug_options.outline_scrollbars {
269            if let Some((gutter, [thumb_min, thumb_max])) = uinode.horizontal_scrollbar() {
270                push_outline(gutter, ResolvedBorderRadius::ZERO);
271                push_outline(
272                    Rect {
273                        min: Vec2::new(thumb_min, gutter.min.y),
274                        max: Vec2::new(thumb_max, gutter.max.y),
275                    },
276                    ResolvedBorderRadius::ZERO,
277                );
278            }
279            if let Some((gutter, [thumb_min, thumb_max])) = uinode.vertical_scrollbar() {
280                push_outline(gutter, ResolvedBorderRadius::ZERO);
281                push_outline(
282                    Rect {
283                        min: Vec2::new(gutter.min.x, thumb_min),
284                        max: Vec2::new(gutter.max.x, thumb_max),
285                    },
286                    ResolvedBorderRadius::ZERO,
287                );
288            }
289        }
290    }
291}