Skip to main content

bevy_camera/
projection.rs

1use core::fmt::Debug;
2use core::ops::{Deref, DerefMut};
3
4use crate::{primitives::Frustum, visibility::VisibilitySystems};
5use bevy_app::{App, Plugin, PostUpdate};
6use bevy_ecs::prelude::*;
7use bevy_math::{ops, proj, vec4, AspectRatio, Mat4, Rect, Vec2, Vec3A, Vec4};
8use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize};
9use bevy_shape::ViewFrustum;
10use bevy_transform::{components::GlobalTransform, TransformSystems};
11use derive_more::derive::From;
12use serde::{Deserialize, Serialize};
13
14/// Adds [`Camera`](crate::camera::Camera) driver systems for a given projection type.
15///
16/// If you are using `bevy_pbr`, then you need to add `PbrProjectionPlugin` along with this.
17#[derive(#[automatically_derived]
impl ::core::default::Default for CameraProjectionPlugin {
    #[inline]
    fn default() -> Self { Self }
}Default)]
18pub struct CameraProjectionPlugin;
19
20impl Plugin for CameraProjectionPlugin {
21    fn build(&self, app: &mut App) {
22        app.add_systems(
23            PostUpdate,
24            crate::visibility::update_frusta
25                .in_set(VisibilitySystems::UpdateFrusta)
26                .after(TransformSystems::Propagate),
27        );
28    }
29}
30
31/// Describes a type that can generate a projection matrix, allowing it to be added to a
32/// [`Camera`]'s [`Projection`] component.
33///
34/// Once implemented, the projection can be added to a camera using [`Projection::custom`].
35///
36/// The projection will be automatically updated as the render area is resized. This is useful when,
37/// for example, a projection type has a field like `fov` that should change when the window width
38/// is changed but not when the height changes.
39///
40/// This trait is implemented by bevy's built-in projections [`PerspectiveProjection`] and
41/// [`OrthographicProjection`].
42///
43/// [`Camera`]: crate::camera::Camera
44pub trait CameraProjection {
45    /// Generate the projection matrix.
46    fn get_clip_from_view(&self) -> Mat4;
47
48    /// Generate the projection matrix for a [`SubCameraView`](super::SubCameraView).
49    fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4;
50
51    /// When the area this camera renders to changes dimensions, this method will be automatically
52    /// called. Use this to update any projection properties that depend on the aspect ratio or
53    /// dimensions of the render area.
54    fn update(&mut self, width: f32, height: f32);
55
56    /// The far plane distance of the projection.
57    fn far(&self) -> f32;
58
59    /// The eight corners of the camera frustum, as defined by this projection.
60    ///
61    /// The corners should be provided in the following order: first the bottom right, top right,
62    /// top left, bottom left for the near plane, then similar for the far plane.
63    // TODO: This seems somewhat redundant with `compute_frustum`, and similarly should be possible
64    // to compute with a default impl.
65    fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8];
66
67    /// Compute camera frustum for camera with given projection and transform.
68    ///
69    /// This code is called by [`update_frusta`](crate::visibility::update_frusta) system
70    /// for each camera to update its frustum.
71    fn compute_frustum(&self, camera_transform: &GlobalTransform) -> Frustum {
72        let clip_from_world = self.get_clip_from_view() * camera_transform.affine().inverse();
73        Frustum(ViewFrustum::from_clip_from_world_custom_far(
74            &clip_from_world,
75            &camera_transform.translation(),
76            &camera_transform.back(),
77            self.far(),
78        ))
79    }
80}
81
82mod sealed {
83    use super::CameraProjection;
84
85    /// A wrapper trait to make it possible to implement Clone for boxed [`CameraProjection`](`super::CameraProjection`)
86    /// trait objects, without breaking object safety rules by making it `Sized`. Additional bounds
87    /// are included for downcasting, and fulfilling the trait bounds on `Projection`.
88    pub trait DynCameraProjection:
89        CameraProjection + core::fmt::Debug + Send + Sync + downcast_rs::Downcast
90    {
91        fn clone_box(&self) -> Box<dyn DynCameraProjection>;
92    }
93
94    impl dyn DynCameraProjection<> {
    /// Returns true if the trait object wraps an object of type `__T`.
    #[inline]
    pub fn is<__T: DynCameraProjection<>>(&self) -> bool {
        ::downcast_rs::Downcast::as_any(self).is::<__T>()
    }
    /// Returns a boxed object from a boxed trait object if the underlying object is of type
    /// `__T`. Returns the original boxed trait if it isn't.
    #[inline]
    pub fn downcast<__T: DynCameraProjection<>>(self:
            ::downcast_rs::__alloc::boxed::Box<Self>)
        ->
            ::downcast_rs::__std::result::Result<::downcast_rs::__alloc::boxed::Box<__T>,
            ::downcast_rs::__alloc::boxed::Box<Self>> {
        if self.is::<__T>() {
            Ok(::downcast_rs::Downcast::into_any(self).downcast::<__T>().unwrap())
        } else { Err(self) }
    }
    /// Returns an `Rc`-ed object from an `Rc`-ed trait object if the underlying object is of
    /// type `__T`. Returns the original `Rc`-ed trait if it isn't.
    #[inline]
    pub fn downcast_rc<__T: DynCameraProjection<>>(self:
            ::downcast_rs::__alloc::rc::Rc<Self>)
        ->
            ::downcast_rs::__std::result::Result<::downcast_rs::__alloc::rc::Rc<__T>,
            ::downcast_rs::__alloc::rc::Rc<Self>> {
        if self.is::<__T>() {
            Ok(::downcast_rs::Downcast::into_any_rc(self).downcast::<__T>().unwrap())
        } else { Err(self) }
    }
    /// Returns a reference to the object within the trait object if it is of type `__T`, or
    /// `None` if it isn't.
    #[inline]
    pub fn downcast_ref<__T: DynCameraProjection<>>(&self)
        -> ::downcast_rs::__std::option::Option<&__T> {
        ::downcast_rs::Downcast::as_any(self).downcast_ref::<__T>()
    }
    /// Returns a mutable reference to the object within the trait object if it is of type
    /// `__T`, or `None` if it isn't.
    #[inline]
    pub fn downcast_mut<__T: DynCameraProjection<>>(&mut self)
        -> ::downcast_rs::__std::option::Option<&mut __T> {
        ::downcast_rs::Downcast::as_any_mut(self).downcast_mut::<__T>()
    }
}downcast_rs::impl_downcast!(DynCameraProjection);
95
96    impl<T> DynCameraProjection for T
97    where
98        T: 'static + CameraProjection + core::fmt::Debug + Send + Sync + Clone,
99    {
100        fn clone_box(&self) -> Box<dyn DynCameraProjection> {
101            Box::new(self.clone())
102        }
103    }
104}
105
106/// Holds a dynamic [`CameraProjection`] trait object. Use [`Projection::custom()`] to construct a
107/// custom projection.
108///
109/// The contained dynamic object can be downcast into a static type using [`CustomProjection::get`].
110#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CustomProjection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "CustomProjection", "dyn_projection", &&self.dyn_projection)
    }
}Debug, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for CustomProjection where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectDefault, Self,
                    _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {}
        }
        impl bevy_reflect::Typed for CustomProjection where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for CustomProjection where  {
            fn type_path() -> &'static str {
                "bevy_camera::projection::CustomProjection"
            }
            fn short_type_path() -> &'static str { "CustomProjection" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("CustomProjection")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection")
            }
        }
        impl bevy_reflect::Reflect for CustomProjection 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(<CustomProjection
                                        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 CustomProjection where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index { _ => ::core::option::Option::None, }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name { _ => ::core::option::Option::None, }
            }
            fn field_len(&self) -> usize { 0usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for CustomProjection 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]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for CustomProjection 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
111#[reflect(Default, Clone)]
112pub struct CustomProjection {
113    #[reflect(ignore)]
114    dyn_projection: Box<dyn sealed::DynCameraProjection>,
115}
116
117impl Default for CustomProjection {
118    fn default() -> Self {
119        Self {
120            dyn_projection: Box::new(PerspectiveProjection::default()),
121        }
122    }
123}
124
125impl Clone for CustomProjection {
126    fn clone(&self) -> Self {
127        Self {
128            dyn_projection: self.dyn_projection.clone_box(),
129        }
130    }
131}
132
133impl CustomProjection {
134    /// Returns a reference to the [`CameraProjection`] `P`.
135    ///
136    /// Returns `None` if this dynamic object is not a projection of type `P`.
137    ///
138    /// ```
139    /// # use bevy_camera::{Projection, PerspectiveProjection};
140    /// // For simplicity's sake, use perspective as a custom projection:
141    /// let projection = Projection::custom(PerspectiveProjection::default());
142    /// let Projection::Custom(custom) = projection else { return };
143    ///
144    /// // At this point the projection type is erased.
145    /// // We can use `get()` if we know what kind of projection we have.
146    /// let perspective = custom.get::<PerspectiveProjection>().unwrap();
147    ///
148    /// assert_eq!(perspective.fov, PerspectiveProjection::default().fov);
149    /// ```
150    pub fn get<P>(&self) -> Option<&P>
151    where
152        P: CameraProjection + Debug + Send + Sync + Clone + 'static,
153    {
154        self.dyn_projection.downcast_ref()
155    }
156
157    /// Returns a mutable  reference to the [`CameraProjection`] `P`.
158    ///
159    /// Returns `None` if this dynamic object is not a projection of type `P`.
160    ///
161    /// ```
162    /// # use bevy_camera::{Projection, PerspectiveProjection};
163    /// // For simplicity's sake, use perspective as a custom projection:
164    /// let mut projection = Projection::custom(PerspectiveProjection::default());
165    /// let Projection::Custom(mut custom) = projection else { return };
166    ///
167    /// // At this point the projection type is erased.
168    /// // We can use `get_mut()` if we know what kind of projection we have.
169    /// let perspective = custom.get_mut::<PerspectiveProjection>().unwrap();
170    ///
171    /// assert_eq!(perspective.fov, PerspectiveProjection::default().fov);
172    /// perspective.fov = 1.0;
173    /// ```
174    pub fn get_mut<P>(&mut self) -> Option<&mut P>
175    where
176        P: CameraProjection + Debug + Send + Sync + Clone + 'static,
177    {
178        self.dyn_projection.downcast_mut()
179    }
180}
181
182impl Deref for CustomProjection {
183    type Target = dyn CameraProjection;
184
185    fn deref(&self) -> &Self::Target {
186        self.dyn_projection.as_ref()
187    }
188}
189
190impl DerefMut for CustomProjection {
191    fn deref_mut(&mut self) -> &mut Self::Target {
192        self.dyn_projection.as_mut()
193    }
194}
195
196/// Component that defines how to compute a [`Camera`]'s projection matrix.
197///
198/// Common projections, like perspective and orthographic, are provided out of the box to handle the
199/// majority of use cases. Custom projections can be added using the [`CameraProjection`] trait and
200/// the [`Projection::custom`] constructor.
201///
202/// ## What's a projection?
203///
204/// A camera projection essentially describes how 3d points from the point of view of a camera are
205/// projected onto a 2d screen. This is where properties like a camera's field of view are defined.
206/// More specifically, a projection is a 4x4 matrix that transforms points from view space (the
207/// point of view of the camera) into clip space. Clip space is almost, but not quite, equivalent to
208/// the rectangle that is rendered to your screen, with a depth axis. Any points that land outside
209/// the bounds of this cuboid are "clipped" and not rendered.
210///
211/// You can also think of the projection as the thing that describes the shape of a camera's
212/// frustum: the volume in 3d space that is visible to a camera.
213///
214/// [`Camera`]: crate::camera::Camera
215#[derive(impl bevy_ecs::component::Component for Projection 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 map_entities<M: bevy_ecs::entity::EntityMapper>(this: &mut Self,
        mapper: &mut M) {
        use bevy_ecs::entity::MapEntities;
        match this {
            Self::Perspective { .. } => {}
            Self::Orthographic { .. } => {}
            Self::Custom { .. } => {}
            _ => {}
        }
    }
    fn relationship_accessor()
        ->
            ::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
        ::core::option::Option::None
    }
}Component, #[automatically_derived]
impl ::core::fmt::Debug for Projection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Perspective(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Perspective", &__self_0),
            Self::Orthographic(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Orthographic", &__self_0),
            Self::Custom(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Custom",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Projection {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Perspective(__self_0) =>
                Self::Perspective(::core::clone::Clone::clone(__self_0)),
            Self::Orthographic(__self_0) =>
                Self::Orthographic(::core::clone::Clone::clone(__self_0)),
            Self::Custom(__self_0) =>
                Self::Custom(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Projection where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectComponent, Self,
                    _>(());
                registration.register_type_data_with::<ReflectDefault, Self,
                    _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <PerspectiveProjection as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <OrthographicProjection as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <CustomProjection as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Projection where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Perspective",
                                                        &[bevy_reflect::UnnamedField::new::<PerspectiveProjection>(0usize)])),
                                                bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Orthographic",
                                                        &[bevy_reflect::UnnamedField::new::<OrthographicProjection>(0usize)])),
                                                bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Custom",
                                                        &[bevy_reflect::UnnamedField::new::<CustomProjection>(0usize)]))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Projection where  {
            fn type_path() -> &'static str {
                "bevy_camera::projection::Projection"
            }
            fn short_type_path() -> &'static str { "Projection" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Projection")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection")
            }
        }
        impl bevy_reflect::Reflect for Projection 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(<Projection
                                        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::enums::Enum for Projection where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    Projection::Perspective { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    Projection::Orthographic { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    Projection::Custom { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    Projection::Perspective { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    Projection::Orthographic { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    Projection::Custom { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    Projection::Perspective { .. } => 1usize,
                    Projection::Orthographic { .. } => 1usize,
                    Projection::Custom { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    Projection::Perspective { .. } => "Perspective",
                    Projection::Orthographic { .. } => "Orthographic",
                    Projection::Custom { .. } => "Custom",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    Projection::Perspective { .. } => 0usize,
                    Projection::Orthographic { .. } => 1usize,
                    Projection::Custom { .. } => 2usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    Projection::Perspective { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    Projection::Orthographic { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    Projection::Custom { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self)
                ->
                    ::core::result::Result<bevy_reflect::enums::DynamicEnum,
                    bevy_reflect::ReflectCloneError> {
                bevy_reflect::enums::DynamicEnum::try_from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for Projection 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_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Perspective" => {
                                *self =
                                    Projection::Perspective {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Perspective"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <PerspectiveProjection as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<PerspectiveProjection
                                                                    as bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Orthographic" => {
                                *self =
                                    Projection::Orthographic {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Orthographic"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <OrthographicProjection as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<OrthographicProjection
                                                                    as bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Custom" => {
                                *self =
                                    Projection::Custom {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Custom"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <CustomProjection as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<CustomProjection as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(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_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for Projection where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Perspective" =>
                            ::core::option::Option::Some(Projection::Perspective {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <PerspectiveProjection as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Orthographic" =>
                            ::core::option::Option::Some(Projection::Orthographic {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <OrthographicProjection as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Custom" =>
                            ::core::option::Option::Some(Projection::Custom {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <CustomProjection as
                                                    bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[allow(deprecated)]
#[allow(unreachable_code)]
#[automatically_derived]
impl derive_more::core::convert::From<(PerspectiveProjection)> for Projection
    {
    #[inline]
    fn from(value: (PerspectiveProjection)) -> Self {
        Projection::Perspective(value)
    }
}
#[allow(deprecated)]
#[allow(unreachable_code)]
#[automatically_derived]
impl derive_more::core::convert::From<(OrthographicProjection)> for Projection
    {
    #[inline]
    fn from(value: (OrthographicProjection)) -> Self {
        Projection::Orthographic(value)
    }
}
#[allow(deprecated)]
#[allow(unreachable_code)]
#[automatically_derived]
impl derive_more::core::convert::From<(CustomProjection)> for Projection {
    #[inline]
    fn from(value: (CustomProjection)) -> Self { Projection::Custom(value) }
}From)]
216#[reflect(Component, Default, Debug, Clone)]
217pub enum Projection {
218    Perspective(PerspectiveProjection),
219    Orthographic(OrthographicProjection),
220    Custom(CustomProjection),
221}
222
223impl Projection {
224    /// Construct a new custom camera projection from a type that implements [`CameraProjection`].
225    pub fn custom<P>(projection: P) -> Self
226    where
227        // Implementation note: pushing these trait bounds all the way out to this function makes
228        // errors nice for users. If a trait is missing, they will get a helpful error telling them
229        // that, say, the `Debug` implementation is missing. Wrapping these traits behind a super
230        // trait or some other indirection will make the errors harder to understand.
231        //
232        // For example, we don't use the `DynCameraProjection` trait bound, because it is not the
233        // trait the user should be implementing - they only need to worry about implementing
234        // `CameraProjection`.
235        P: CameraProjection + Debug + Send + Sync + Clone + 'static,
236    {
237        Projection::Custom(CustomProjection {
238            dyn_projection: Box::new(projection),
239        })
240    }
241
242    /// Check if the projection is perspective.
243    /// For [`CustomProjection`], this checks if the projection matrix's w-axis's w is 0.0.
244    pub fn is_perspective(&self) -> bool {
245        match self {
246            Projection::Perspective(_) => true,
247            Projection::Orthographic(_) => false,
248            Projection::Custom(projection) => projection.get_clip_from_view().w_axis.w == 0.0,
249        }
250    }
251}
252
253impl Deref for Projection {
254    type Target = dyn CameraProjection;
255
256    fn deref(&self) -> &Self::Target {
257        match self {
258            Projection::Perspective(projection) => projection,
259            Projection::Orthographic(projection) => projection,
260            Projection::Custom(projection) => projection.deref(),
261        }
262    }
263}
264
265impl DerefMut for Projection {
266    fn deref_mut(&mut self) -> &mut Self::Target {
267        match self {
268            Projection::Perspective(projection) => projection,
269            Projection::Orthographic(projection) => projection,
270            Projection::Custom(projection) => projection.deref_mut(),
271        }
272    }
273}
274
275impl Default for Projection {
276    fn default() -> Self {
277        Projection::Perspective(Default::default())
278    }
279}
280
281/// A 3D camera projection in which distant objects appear smaller than close objects.
282#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PerspectiveProjection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f,
            "PerspectiveProjection", "fov", &self.fov, "aspect_ratio",
            &self.aspect_ratio, "near", &self.near, "far", &self.far,
            "near_clip_plane", &&self.near_clip_plane)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for PerspectiveProjection {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            fov: ::core::clone::Clone::clone(&self.fov),
            aspect_ratio: ::core::clone::Clone::clone(&self.aspect_ratio),
            near: ::core::clone::Clone::clone(&self.near),
            far: ::core::clone::Clone::clone(&self.far),
            near_clip_plane: ::core::clone::Clone::clone(&self.near_clip_plane),
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for PerspectiveProjection where
             {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectDefault, Self,
                    _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec4 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for PerspectiveProjection where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<f32>("fov"),
                                                bevy_reflect::NamedField::new::<f32>("aspect_ratio"),
                                                bevy_reflect::NamedField::new::<f32>("near"),
                                                bevy_reflect::NamedField::new::<f32>("far"),
                                                bevy_reflect::NamedField::new::<Vec4>("near_clip_plane")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for PerspectiveProjection where  {
            fn type_path() -> &'static str {
                "bevy_camera::projection::PerspectiveProjection"
            }
            fn short_type_path() -> &'static str { "PerspectiveProjection" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("PerspectiveProjection")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection")
            }
        }
        impl bevy_reflect::Reflect for PerspectiveProjection 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(<PerspectiveProjection
                                        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 PerspectiveProjection where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "fov" => ::core::option::Option::Some(&self.fov),
                    "aspect_ratio" =>
                        ::core::option::Option::Some(&self.aspect_ratio),
                    "near" => ::core::option::Option::Some(&self.near),
                    "far" => ::core::option::Option::Some(&self.far),
                    "near_clip_plane" =>
                        ::core::option::Option::Some(&self.near_clip_plane),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "fov" => ::core::option::Option::Some(&mut self.fov),
                    "aspect_ratio" =>
                        ::core::option::Option::Some(&mut self.aspect_ratio),
                    "near" => ::core::option::Option::Some(&mut self.near),
                    "far" => ::core::option::Option::Some(&mut self.far),
                    "near_clip_plane" =>
                        ::core::option::Option::Some(&mut self.near_clip_plane),
                    _ => ::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.fov),
                    1usize => ::core::option::Option::Some(&self.aspect_ratio),
                    2usize => ::core::option::Option::Some(&self.near),
                    3usize => ::core::option::Option::Some(&self.far),
                    4usize =>
                        ::core::option::Option::Some(&self.near_clip_plane),
                    _ => ::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.fov),
                    1usize =>
                        ::core::option::Option::Some(&mut self.aspect_ratio),
                    2usize => ::core::option::Option::Some(&mut self.near),
                    3usize => ::core::option::Option::Some(&mut self.far),
                    4usize =>
                        ::core::option::Option::Some(&mut self.near_clip_plane),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("fov"),
                    1usize => ::core::option::Option::Some("aspect_ratio"),
                    2usize => ::core::option::Option::Some("near"),
                    3usize => ::core::option::Option::Some("far"),
                    4usize => ::core::option::Option::Some("near_clip_plane"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "fov" => ::core::option::Option::Some(0usize),
                    "aspect_ratio" => ::core::option::Option::Some(1usize),
                    "near" => ::core::option::Option::Some(2usize),
                    "far" => ::core::option::Option::Some(3usize),
                    "near_clip_plane" => ::core::option::Option::Some(4usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 5usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                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("fov",
                    bevy_reflect::PartialReflect::to_dynamic(&self.fov)?);
                dynamic.insert_boxed("aspect_ratio",
                    bevy_reflect::PartialReflect::to_dynamic(&self.aspect_ratio)?);
                dynamic.insert_boxed("near",
                    bevy_reflect::PartialReflect::to_dynamic(&self.near)?);
                dynamic.insert_boxed("far",
                    bevy_reflect::PartialReflect::to_dynamic(&self.far)?);
                dynamic.insert_boxed("near_clip_plane",
                    bevy_reflect::PartialReflect::to_dynamic(&self.near_clip_plane)?);
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for PerspectiveProjection 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)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for PerspectiveProjection 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "fov")?))() {
                        __this.fov = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "aspect_ratio")?))() {
                        __this.aspect_ratio = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "near")?))() {
                        __this.near = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <f32 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "far")?))() {
                        __this.far = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Vec4 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "near_clip_plane")?))() {
                        __this.near_clip_plane = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
283#[reflect(Default, Debug, Clone)]
284pub struct PerspectiveProjection {
285    /// The vertical field of view (FOV) in radians.
286    ///
287    /// Defaults to a value of π/4 radians or 45 degrees.
288    pub fov: f32,
289
290    /// The aspect ratio (width divided by height) of the viewing frustum.
291    ///
292    /// Bevy's `camera_system` automatically updates this value when the aspect ratio
293    /// of the associated window changes.
294    ///
295    /// Defaults to a value of `1.0`.
296    pub aspect_ratio: f32,
297
298    /// The distance from the camera in world units of the viewing frustum's near plane.
299    ///
300    /// Objects closer to the camera than this value will not be visible.
301    ///
302    /// Defaults to a value of `0.1`.
303    pub near: f32,
304
305    /// The distance from the camera in world units of the viewing frustum's far plane.
306    ///
307    /// Objects farther from the camera than this value will not be visible.
308    ///
309    /// Defaults to a value of `1000.0`.
310    pub far: f32,
311
312    /// The orientation of a custom clipping plane, as well as its distance from
313    /// the camera.
314    ///
315    /// If you supply a plane here, anything in front of the plane will be
316    /// clipped out. This is useful for portals and mirrors, in order to clip
317    /// any geometry that would pass through the plane of the portal or mirror.
318    ///
319    /// The X, Y, and Z components of the vector describe its normal, in view
320    /// space. This normal vector must have length 1, and it should point away
321    /// from the camera. (That is, only geometry on the side of the plane that
322    /// the normal points toward will be rendered.) The W component of the
323    /// vector must be the *negative shortest signed distance* from the camera
324    /// to the plane, again in view space.  This final component can also be
325    /// computed as -(N ·  Q), where N is the normal of the plane and Q is any
326    /// point on it.
327    ///
328    /// By default, this is (0, 0, -1, -[`Self::near`]), which describes a near
329    /// plane located [`Self::near`] meters away pointing directly away from the
330    /// camera.
331    ///
332    /// See the `calculate_mirror_camera_transform_and_projection` function in
333    /// the `mirror` example for an exhaustive example of usage.
334    pub near_clip_plane: Vec4,
335}
336
337impl CameraProjection for PerspectiveProjection {
338    fn get_clip_from_view(&self) -> Mat4 {
339        let mut matrix = proj::perspective_infinite_reverse(self.fov, self.aspect_ratio, self.near);
340        self.adjust_perspective_matrix_for_clip_plane(&mut matrix);
341        matrix
342    }
343
344    fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4 {
345        let full_width = sub_view.full_size.x as f32;
346        let full_height = sub_view.full_size.y as f32;
347        let sub_width = sub_view.size.x as f32;
348        let sub_height = sub_view.size.y as f32;
349        let offset_x = sub_view.offset.x;
350        // Y-axis increases from top to bottom
351        let offset_y = full_height - (sub_view.offset.y + sub_height);
352
353        let full_aspect = full_width / full_height;
354
355        // Original frustum parameters
356        let top = self.near * ops::tan(0.5 * self.fov);
357        let bottom = -top;
358        let right = top * full_aspect;
359        let left = -right;
360
361        // Calculate scaling factors
362        let width = right - left;
363        let height = top - bottom;
364
365        // Calculate the new frustum parameters
366        let left_prime = left + (width * offset_x) / full_width;
367        let right_prime = left + (width * (offset_x + sub_width)) / full_width;
368        let bottom_prime = bottom + (height * offset_y) / full_height;
369        let top_prime = bottom + (height * (offset_y + sub_height)) / full_height;
370
371        // Compute the new projection matrix
372        let x = (2.0 * self.near) / (right_prime - left_prime);
373        let y = (2.0 * self.near) / (top_prime - bottom_prime);
374        let a = (right_prime + left_prime) / (right_prime - left_prime);
375        let b = (top_prime + bottom_prime) / (top_prime - bottom_prime);
376
377        let mut matrix = Mat4::from_cols(
378            Vec4::new(x, 0.0, 0.0, 0.0),
379            Vec4::new(0.0, y, 0.0, 0.0),
380            Vec4::new(a, b, 0.0, -1.0),
381            Vec4::new(0.0, 0.0, self.near, 0.0),
382        );
383
384        self.adjust_perspective_matrix_for_clip_plane(&mut matrix);
385        matrix
386    }
387
388    fn update(&mut self, width: f32, height: f32) {
389        self.aspect_ratio = AspectRatio::try_new(width, height)
390            .expect("Failed to update PerspectiveProjection: width and height must be positive, non-zero values")
391            .ratio();
392    }
393
394    fn far(&self) -> f32 {
395        self.far
396    }
397
398    fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
399        let tan_half_fov = ops::tan(self.fov / 2.);
400        let a = z_near.abs() * tan_half_fov;
401        let b = z_far.abs() * tan_half_fov;
402        let aspect_ratio = self.aspect_ratio;
403        // NOTE: These vertices are in the specific order required by [`calculate_cascade`].
404        [
405            Vec3A::new(a * aspect_ratio, -a, z_near),  // bottom right
406            Vec3A::new(a * aspect_ratio, a, z_near),   // top right
407            Vec3A::new(-a * aspect_ratio, a, z_near),  // top left
408            Vec3A::new(-a * aspect_ratio, -a, z_near), // bottom left
409            Vec3A::new(b * aspect_ratio, -b, z_far),   // bottom right
410            Vec3A::new(b * aspect_ratio, b, z_far),    // top right
411            Vec3A::new(-b * aspect_ratio, b, z_far),   // top left
412            Vec3A::new(-b * aspect_ratio, -b, z_far),  // bottom left
413        ]
414    }
415}
416
417impl Default for PerspectiveProjection {
418    fn default() -> Self {
419        PerspectiveProjection {
420            fov: core::f32::consts::PI / 4.0,
421            near: 0.1,
422            far: 1000.0,
423            aspect_ratio: 1.0,
424            near_clip_plane: vec4(0.0, 0.0, -1.0, -0.1),
425        }
426    }
427}
428
429impl PerspectiveProjection {
430    /// Adjusts the perspective matrix for an oblique clip plane if necessary.
431    ///
432    /// This changes the near and (infinite) far planes so that they correctly
433    /// clip everything in front of the [`Self::near_clip_plane`]. See [Lengyel
434    /// 2005] for an exhaustive treatment of the way this works. Custom near
435    /// clip planes are typically used for portals and mirrors; see
436    /// `examples/3d/mirror.rs` for an example of usage.
437    fn adjust_perspective_matrix_for_clip_plane(&self, matrix: &mut Mat4) {
438        // If we don't have an oblique clip plane, save ourselves the trouble.
439        if self.near_clip_plane.x == 0.0
440            && self.near_clip_plane.y == 0.0
441            && self.near_clip_plane.z == -1.0
442        {
443            return;
444        }
445
446        // To understand this, refer to [Lengyel 2005]. The notation follows the
447        // paper. The formulas are different because the paper uses a standard
448        // OpenGL convention (near -1, far 1), while we use a reversed Vulkan
449        // convention (near 1, far 0).
450        //
451        // [Lengyel 2005]: https://terathon.com/lengyel/Lengyel-Oblique.pdf
452        let c = self.near_clip_plane;
453
454        // First, calculate the position of Q′, the corner in clip space lying
455        // opposite from the near clip plane. This is identical to equation (7).
456        // Note that this is a point at infinity in view space, because we use
457        // an infinite far plane, but in clip space it's finite.
458        let q_prime = vec4(c.x.signum(), c.y.signum(), 0.0, 1.0);
459
460        // Now convert that point to view space. This *will* be a point at
461        // infinity, but that's OK because we're in homogeneous coordinates.
462        let q = matrix.inverse() * q_prime;
463
464        // Here we're computing the scaling factor to apply to the near plane so
465        // that the far plane will intersect Q. This one differs from the paper.
466        // Using the notation Máµ¢ to mean the *i*th row of the matrix M, start by
467        // observing that the near plane (z = 1) is described by M₄ - M₃ and the
468        // far plane (z = 0) is described by simply M₃. So:
469        //
470        // * Equation (4) becomes C = M₄ - M₃.
471        // * Equation (5) becomes M′₃ = M₄ - C.
472        // * Equation (6) becomes F = M′₃ = M₄ - C.
473        // * Equation (8) becomes F = Mâ‚„ - aC.
474        // * Equation (9) becomes F ·  Q = 0 ⇒ (M₄ - aC) ·  Q = 0.
475        //
476        // And, solving the modified equation (9), we get:
477        //
478        //          M₄ ·  Q
479        //      a = ⎯⎯⎯⎯⎯⎯
480        //           C ·  Q
481        //
482        // Because Mâ‚„ = (0, 0, -1, 0) (just as it is in the paper), this reduces to:
483        //
484        //           -Qz
485        //      a = ⎯⎯⎯⎯⎯
486        //          C ·  Q
487        //
488        // Which is what we calculate here.
489        let a = -q.z / c.dot(q);
490
491        // Finally, we have the revised equation (10), which is M′₃ = M₄ - aC.
492        // Similarly to the above, this simplifies to M′₃ = (0, 0, -1, 0) - aC.
493        let m3_prime = Vec4::NEG_Z - c * a;
494
495        // We have the replacement third row; write it in.
496        matrix.x_axis.z = m3_prime.x;
497        matrix.y_axis.z = m3_prime.y;
498        matrix.z_axis.z = m3_prime.z;
499        matrix.w_axis.z = m3_prime.w;
500    }
501}
502
503/// Scaling mode for [`OrthographicProjection`].
504///
505/// The effect of these scaling modes are combined with the [`OrthographicProjection::scale`] property.
506///
507/// For example, if the scaling mode is `ScalingMode::Fixed { width: 100.0, height: 300 }` and the scale is `2.0`,
508/// the projection will be 200 world units wide and 600 world units tall.
509///
510/// # Examples
511///
512/// Configure the orthographic projection to two world units per window height:
513///
514/// ```
515/// # use bevy_camera::{OrthographicProjection, Projection, ScalingMode};
516/// let projection = Projection::Orthographic(OrthographicProjection {
517///    scaling_mode: ScalingMode::FixedVertical { viewport_height: 2.0 },
518///    ..OrthographicProjection::default_2d()
519/// });
520/// ```
521#[derive(#[automatically_derived]
impl ::core::default::Default for ScalingMode {
    #[inline]
    fn default() -> Self { Self::WindowSize }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for ScalingMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::WindowSize =>
                ::core::fmt::Formatter::write_str(f, "WindowSize"),
            Self::Fixed { width: __self_0, height: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Fixed",
                    "width", __self_0, "height", &__self_1),
            Self::AutoMin { min_width: __self_0, min_height: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "AutoMin", "min_width", __self_0, "min_height", &__self_1),
            Self::AutoMax { max_width: __self_0, max_height: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "AutoMax", "max_width", __self_0, "max_height", &__self_1),
            Self::FixedVertical { viewport_height: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "FixedVertical", "viewport_height", &__self_0),
            Self::FixedHorizontal { viewport_width: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "FixedHorizontal", "viewport_width", &__self_0),
        }
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ScalingMode { }
#[automatically_derived]
impl ::core::clone::Clone for ScalingMode {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<f32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ScalingMode { }Copy, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for ScalingMode where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectSerialize, Self,
                    _>(());
                registration.register_type_data_with::<ReflectDeserialize,
                    Self, _>(());
                registration.register_type_data_with::<ReflectDefault, Self,
                    _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for ScalingMode where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("WindowSize")),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("Fixed",
                                                        &[bevy_reflect::NamedField::new::<f32>("width"),
                                                                    bevy_reflect::NamedField::new::<f32>("height")])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("AutoMin",
                                                        &[bevy_reflect::NamedField::new::<f32>("min_width"),
                                                                    bevy_reflect::NamedField::new::<f32>("min_height")])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("AutoMax",
                                                        &[bevy_reflect::NamedField::new::<f32>("max_width"),
                                                                    bevy_reflect::NamedField::new::<f32>("max_height")])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("FixedVertical",
                                                        &[bevy_reflect::NamedField::new::<f32>("viewport_height")])),
                                                bevy_reflect::enums::VariantInfo::Struct(bevy_reflect::enums::StructVariantInfo::new("FixedHorizontal",
                                                        &[bevy_reflect::NamedField::new::<f32>("viewport_width")]))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for ScalingMode where  {
            fn type_path() -> &'static str {
                "bevy_camera::projection::ScalingMode"
            }
            fn short_type_path() -> &'static str { "ScalingMode" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ScalingMode")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection")
            }
        }
        impl bevy_reflect::Reflect for ScalingMode 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(<ScalingMode
                                        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::enums::Enum for ScalingMode where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    ScalingMode::Fixed { width: __value, .. } if
                        __name_param == "width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::Fixed { height: __value, .. } if
                        __name_param == "height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_width: __value, .. } if
                        __name_param == "min_width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_height: __value, .. } if
                        __name_param == "min_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_width: __value, .. } if
                        __name_param == "max_width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_height: __value, .. } if
                        __name_param == "max_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedVertical { viewport_height: __value, .. }
                        if __name_param == "viewport_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedHorizontal { viewport_width: __value, .. }
                        if __name_param == "viewport_width" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    ScalingMode::Fixed { width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::Fixed { height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedVertical { viewport_height: __value, .. }
                        if __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedHorizontal { viewport_width: __value, .. }
                        if __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    ScalingMode::Fixed { width: __value, .. } if
                        __name_param == "width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::Fixed { height: __value, .. } if
                        __name_param == "height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_width: __value, .. } if
                        __name_param == "min_width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_height: __value, .. } if
                        __name_param == "min_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_width: __value, .. } if
                        __name_param == "max_width" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_height: __value, .. } if
                        __name_param == "max_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedVertical { viewport_height: __value, .. }
                        if __name_param == "viewport_height" =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedHorizontal { viewport_width: __value, .. }
                        if __name_param == "viewport_width" =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    ScalingMode::Fixed { width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::Fixed { height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMin { min_height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_width: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::AutoMax { max_height: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedVertical { viewport_height: __value, .. }
                        if __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    ScalingMode::FixedHorizontal { viewport_width: __value, .. }
                        if __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self {
                    ScalingMode::Fixed { .. } if __name_param == "width" =>
                        ::core::option::Option::Some(0usize),
                    ScalingMode::Fixed { .. } if __name_param == "height" =>
                        ::core::option::Option::Some(1usize),
                    ScalingMode::AutoMin { .. } if __name_param == "min_width"
                        => ::core::option::Option::Some(0usize),
                    ScalingMode::AutoMin { .. } if __name_param == "min_height"
                        => ::core::option::Option::Some(1usize),
                    ScalingMode::AutoMax { .. } if __name_param == "max_width"
                        => ::core::option::Option::Some(0usize),
                    ScalingMode::AutoMax { .. } if __name_param == "max_height"
                        => ::core::option::Option::Some(1usize),
                    ScalingMode::FixedVertical { .. } if
                        __name_param == "viewport_height" =>
                        ::core::option::Option::Some(0usize),
                    ScalingMode::FixedHorizontal { .. } if
                        __name_param == "viewport_width" =>
                        ::core::option::Option::Some(0usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self {
                    ScalingMode::Fixed { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("width"),
                    ScalingMode::Fixed { .. } if __index_param == 1usize =>
                        ::core::option::Option::Some("height"),
                    ScalingMode::AutoMin { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("min_width"),
                    ScalingMode::AutoMin { .. } if __index_param == 1usize =>
                        ::core::option::Option::Some("min_height"),
                    ScalingMode::AutoMax { .. } if __index_param == 0usize =>
                        ::core::option::Option::Some("max_width"),
                    ScalingMode::AutoMax { .. } if __index_param == 1usize =>
                        ::core::option::Option::Some("max_height"),
                    ScalingMode::FixedVertical { .. } if __index_param == 0usize
                        => ::core::option::Option::Some("viewport_height"),
                    ScalingMode::FixedHorizontal { .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some("viewport_width"),
                    _ => ::core::option::Option::None,
                }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    ScalingMode::WindowSize { .. } => 0usize,
                    ScalingMode::Fixed { .. } => 2usize,
                    ScalingMode::AutoMin { .. } => 2usize,
                    ScalingMode::AutoMax { .. } => 2usize,
                    ScalingMode::FixedVertical { .. } => 1usize,
                    ScalingMode::FixedHorizontal { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    ScalingMode::WindowSize { .. } => "WindowSize",
                    ScalingMode::Fixed { .. } => "Fixed",
                    ScalingMode::AutoMin { .. } => "AutoMin",
                    ScalingMode::AutoMax { .. } => "AutoMax",
                    ScalingMode::FixedVertical { .. } => "FixedVertical",
                    ScalingMode::FixedHorizontal { .. } => "FixedHorizontal",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    ScalingMode::WindowSize { .. } => 0usize,
                    ScalingMode::Fixed { .. } => 1usize,
                    ScalingMode::AutoMin { .. } => 2usize,
                    ScalingMode::AutoMax { .. } => 3usize,
                    ScalingMode::FixedVertical { .. } => 4usize,
                    ScalingMode::FixedHorizontal { .. } => 5usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    ScalingMode::WindowSize { .. } =>
                        bevy_reflect::enums::VariantType::Unit,
                    ScalingMode::Fixed { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    ScalingMode::AutoMin { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    ScalingMode::AutoMax { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    ScalingMode::FixedVertical { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    ScalingMode::FixedHorizontal { .. } =>
                        bevy_reflect::enums::VariantType::Struct,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self)
                ->
                    ::core::result::Result<bevy_reflect::enums::DynamicEnum,
                    bevy_reflect::ReflectCloneError> {
                bevy_reflect::enums::DynamicEnum::try_from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for ScalingMode 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_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "WindowSize" => { *self = ScalingMode::WindowSize {} }
                            "Fixed" => {
                                *self =
                                    ScalingMode::Fixed {
                                        width: {
                                            let __width = __value_param.field("width");
                                            let __width =
                                                __width.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Fixed"),
                                                            field_name: ::core::convert::Into::into("width"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__width).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__width)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        height: {
                                            let __height = __value_param.field("height");
                                            let __height =
                                                __height.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Fixed"),
                                                            field_name: ::core::convert::Into::into("height"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__height).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__height)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "AutoMin" => {
                                *self =
                                    ScalingMode::AutoMin {
                                        min_width: {
                                            let __min_width = __value_param.field("min_width");
                                            let __min_width =
                                                __min_width.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("AutoMin"),
                                                            field_name: ::core::convert::Into::into("min_width"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__min_width).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__min_width)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        min_height: {
                                            let __min_height = __value_param.field("min_height");
                                            let __min_height =
                                                __min_height.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("AutoMin"),
                                                            field_name: ::core::convert::Into::into("min_height"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__min_height).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__min_height)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "AutoMax" => {
                                *self =
                                    ScalingMode::AutoMax {
                                        max_width: {
                                            let __max_width = __value_param.field("max_width");
                                            let __max_width =
                                                __max_width.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("AutoMax"),
                                                            field_name: ::core::convert::Into::into("max_width"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__max_width).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__max_width)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        max_height: {
                                            let __max_height = __value_param.field("max_height");
                                            let __max_height =
                                                __max_height.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("AutoMax"),
                                                            field_name: ::core::convert::Into::into("max_height"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__max_height).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__max_height)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "FixedVertical" => {
                                *self =
                                    ScalingMode::FixedVertical {
                                        viewport_height: {
                                            let __viewport_height =
                                                __value_param.field("viewport_height");
                                            let __viewport_height =
                                                __viewport_height.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("FixedVertical"),
                                                            field_name: ::core::convert::Into::into("viewport_height"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__viewport_height).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__viewport_height)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "FixedHorizontal" => {
                                *self =
                                    ScalingMode::FixedHorizontal {
                                        viewport_width: {
                                            let __viewport_width =
                                                __value_param.field("viewport_width");
                                            let __viewport_width =
                                                __viewport_width.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("FixedHorizontal"),
                                                            field_name: ::core::convert::Into::into("viewport_width"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__viewport_width).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__viewport_width)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(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_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for ScalingMode where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "WindowSize" =>
                            ::core::option::Option::Some(ScalingMode::WindowSize {}),
                        "Fixed" =>
                            ::core::option::Option::Some(ScalingMode::Fixed {
                                    width: {
                                        let __width = __param0.field("width");
                                        let __width = __width?;
                                        <f32 as bevy_reflect::FromReflect>::from_reflect(__width)?
                                    },
                                    height: {
                                        let __height = __param0.field("height");
                                        let __height = __height?;
                                        <f32 as bevy_reflect::FromReflect>::from_reflect(__height)?
                                    },
                                }),
                        "AutoMin" =>
                            ::core::option::Option::Some(ScalingMode::AutoMin {
                                    min_width: {
                                        let __min_width = __param0.field("min_width");
                                        let __min_width = __min_width?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__min_width)?
                                    },
                                    min_height: {
                                        let __min_height = __param0.field("min_height");
                                        let __min_height = __min_height?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__min_height)?
                                    },
                                }),
                        "AutoMax" =>
                            ::core::option::Option::Some(ScalingMode::AutoMax {
                                    max_width: {
                                        let __max_width = __param0.field("max_width");
                                        let __max_width = __max_width?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__max_width)?
                                    },
                                    max_height: {
                                        let __max_height = __param0.field("max_height");
                                        let __max_height = __max_height?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__max_height)?
                                    },
                                }),
                        "FixedVertical" =>
                            ::core::option::Option::Some(ScalingMode::FixedVertical {
                                    viewport_height: {
                                        let __viewport_height = __param0.field("viewport_height");
                                        let __viewport_height = __viewport_height?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__viewport_height)?
                                    },
                                }),
                        "FixedHorizontal" =>
                            ::core::option::Option::Some(ScalingMode::FixedHorizontal {
                                    viewport_width: {
                                        let __viewport_width = __param0.field("viewport_width");
                                        let __viewport_width = __viewport_width?;
                                        <f32 as
                                                    bevy_reflect::FromReflect>::from_reflect(__viewport_width)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for ScalingMode {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private229::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                match *self {
                    ScalingMode::WindowSize =>
                        _serde::Serializer::serialize_unit_variant(__serializer,
                            "ScalingMode", 0u32, "WindowSize"),
                    ScalingMode::Fixed { ref width, ref height } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "ScalingMode", 1u32, "Fixed", 0 + 1 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "width", width)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "height", height)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                    ScalingMode::AutoMin { ref min_width, ref min_height } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "ScalingMode", 2u32, "AutoMin", 0 + 1 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "min_width", min_width)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "min_height", min_height)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                    ScalingMode::AutoMax { ref max_width, ref max_height } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "ScalingMode", 3u32, "AutoMax", 0 + 1 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "max_width", max_width)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "max_height", max_height)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                    ScalingMode::FixedVertical { ref viewport_height } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "ScalingMode", 4u32, "FixedVertical", 0 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "viewport_height", viewport_height)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                    ScalingMode::FixedHorizontal { ref viewport_width } => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_struct_variant(__serializer,
                                    "ScalingMode", 5u32, "FixedHorizontal", 0 + 1)?;
                        _serde::ser::SerializeStructVariant::serialize_field(&mut __serde_state,
                                "viewport_width", viewport_width)?;
                        _serde::ser::SerializeStructVariant::end(__serde_state)
                    }
                }
            }
        }
    };Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for ScalingMode {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private229::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field {
                    __field0,
                    __field1,
                    __field2,
                    __field3,
                    __field4,
                    __field5,
                }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "variant identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private229::Ok(__Field::__field0),
                            1u64 => _serde::__private229::Ok(__Field::__field1),
                            2u64 => _serde::__private229::Ok(__Field::__field2),
                            3u64 => _serde::__private229::Ok(__Field::__field3),
                            4u64 => _serde::__private229::Ok(__Field::__field4),
                            5u64 => _serde::__private229::Ok(__Field::__field5),
                            _ =>
                                _serde::__private229::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
                                        &"variant index 0 <= i < 6")),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "WindowSize" => _serde::__private229::Ok(__Field::__field0),
                            "Fixed" => _serde::__private229::Ok(__Field::__field1),
                            "AutoMin" => _serde::__private229::Ok(__Field::__field2),
                            "AutoMax" => _serde::__private229::Ok(__Field::__field3),
                            "FixedVertical" =>
                                _serde::__private229::Ok(__Field::__field4),
                            "FixedHorizontal" =>
                                _serde::__private229::Ok(__Field::__field5),
                            _ => {
                                _serde::__private229::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"WindowSize" =>
                                _serde::__private229::Ok(__Field::__field0),
                            b"Fixed" => _serde::__private229::Ok(__Field::__field1),
                            b"AutoMin" => _serde::__private229::Ok(__Field::__field2),
                            b"AutoMax" => _serde::__private229::Ok(__Field::__field3),
                            b"FixedVertical" =>
                                _serde::__private229::Ok(__Field::__field4),
                            b"FixedHorizontal" =>
                                _serde::__private229::Ok(__Field::__field5),
                            _ => {
                                let __value =
                                    &_serde::__private229::from_utf8_lossy(__value);
                                _serde::__private229::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private229::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private229::PhantomData<ScalingMode>,
                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = ScalingMode;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "enum ScalingMode")
                    }
                    fn visit_enum<__A>(self, __data: __A)
                        -> _serde::__private229::Result<Self::Value, __A::Error>
                        where __A: _serde::de::EnumAccess<'de> {
                        match _serde::de::EnumAccess::variant(__data) {
                            _serde::__private229::Ok((__Field::__field0, __variant)) =>
                                {
                                _serde::de::VariantAccess::unit_variant(__variant)?;
                                _serde::__private229::Ok(ScalingMode::WindowSize)
                            }
                            _serde::__private229::Ok((__Field::__field1, __variant)) =>
                                {
                                #[allow(non_camel_case_types)]
                                #[doc(hidden)]
                                enum __Field { __field0, __field1, __ignore, }
                                #[doc(hidden)]
                                struct __FieldVisitor;
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                                    type Value = __Field;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "field identifier")
                                    }
                                    fn visit_u64<__E>(self, __value: u64)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            0u64 => _serde::__private229::Ok(__Field::__field0),
                                            1u64 => _serde::__private229::Ok(__Field::__field1),
                                            _ => _serde::__private229::Ok(__Field::__ignore),
                                        }
                                    }
                                    fn visit_str<__E>(self, __value: &str)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            "width" => _serde::__private229::Ok(__Field::__field0),
                                            "height" => _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                    fn visit_bytes<__E>(self, __value: &[u8])
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            b"width" => _serde::__private229::Ok(__Field::__field0),
                                            b"height" => _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                }
                                #[automatically_derived]
                                impl<'de> _serde::Deserialize<'de> for __Field {
                                    #[inline]
                                    fn deserialize<__D>(__deserializer: __D)
                                        -> _serde::__private229::Result<Self, __D::Error> where
                                        __D: _serde::Deserializer<'de> {
                                        _serde::Deserializer::deserialize_identifier(__deserializer,
                                            __FieldVisitor)
                                    }
                                }
                                #[doc(hidden)]
                                struct __Visitor<'de> {
                                    marker: _serde::__private229::PhantomData<ScalingMode>,
                                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                                    type Value = ScalingMode;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "struct variant ScalingMode::Fixed")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"struct variant ScalingMode::Fixed with 2 elements")),
                                            };
                                        let __field1 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(1usize,
                                                                &"struct variant ScalingMode::Fixed with 2 elements")),
                                            };
                                        _serde::__private229::Ok(ScalingMode::Fixed {
                                                width: __field0,
                                                height: __field1,
                                            })
                                    }
                                    #[inline]
                                    fn visit_map<__A>(self, mut __map: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::MapAccess<'de> {
                                        let mut __field0: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        let mut __field1: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        while let _serde::__private229::Some(__key) =
                                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                                            match __key {
                                                __Field::__field0 => {
                                                    if _serde::__private229::Option::is_some(&__field0) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("width"));
                                                    }
                                                    __field0 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                __Field::__field1 => {
                                                    if _serde::__private229::Option::is_some(&__field1) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("height"));
                                                    }
                                                    __field1 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                _ => {
                                                    let _ =
                                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                                }
                                            }
                                        }
                                        let __field0 =
                                            match __field0 {
                                                _serde::__private229::Some(__field0) => __field0,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("width")?,
                                            };
                                        let __field1 =
                                            match __field1 {
                                                _serde::__private229::Some(__field1) => __field1,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("height")?,
                                            };
                                        _serde::__private229::Ok(ScalingMode::Fixed {
                                                width: __field0,
                                                height: __field1,
                                            })
                                    }
                                }
                                #[doc(hidden)]
                                const FIELDS: &'static [&'static str] =
                                    &["width", "height"];
                                _serde::de::VariantAccess::struct_variant(__variant, FIELDS,
                                    __Visitor {
                                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                                        lifetime: _serde::__private229::PhantomData,
                                    })
                            }
                            _serde::__private229::Ok((__Field::__field2, __variant)) =>
                                {
                                #[allow(non_camel_case_types)]
                                #[doc(hidden)]
                                enum __Field { __field0, __field1, __ignore, }
                                #[doc(hidden)]
                                struct __FieldVisitor;
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                                    type Value = __Field;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "field identifier")
                                    }
                                    fn visit_u64<__E>(self, __value: u64)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            0u64 => _serde::__private229::Ok(__Field::__field0),
                                            1u64 => _serde::__private229::Ok(__Field::__field1),
                                            _ => _serde::__private229::Ok(__Field::__ignore),
                                        }
                                    }
                                    fn visit_str<__E>(self, __value: &str)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            "min_width" => _serde::__private229::Ok(__Field::__field0),
                                            "min_height" => _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                    fn visit_bytes<__E>(self, __value: &[u8])
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            b"min_width" => _serde::__private229::Ok(__Field::__field0),
                                            b"min_height" =>
                                                _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                }
                                #[automatically_derived]
                                impl<'de> _serde::Deserialize<'de> for __Field {
                                    #[inline]
                                    fn deserialize<__D>(__deserializer: __D)
                                        -> _serde::__private229::Result<Self, __D::Error> where
                                        __D: _serde::Deserializer<'de> {
                                        _serde::Deserializer::deserialize_identifier(__deserializer,
                                            __FieldVisitor)
                                    }
                                }
                                #[doc(hidden)]
                                struct __Visitor<'de> {
                                    marker: _serde::__private229::PhantomData<ScalingMode>,
                                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                                    type Value = ScalingMode;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "struct variant ScalingMode::AutoMin")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"struct variant ScalingMode::AutoMin with 2 elements")),
                                            };
                                        let __field1 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(1usize,
                                                                &"struct variant ScalingMode::AutoMin with 2 elements")),
                                            };
                                        _serde::__private229::Ok(ScalingMode::AutoMin {
                                                min_width: __field0,
                                                min_height: __field1,
                                            })
                                    }
                                    #[inline]
                                    fn visit_map<__A>(self, mut __map: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::MapAccess<'de> {
                                        let mut __field0: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        let mut __field1: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        while let _serde::__private229::Some(__key) =
                                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                                            match __key {
                                                __Field::__field0 => {
                                                    if _serde::__private229::Option::is_some(&__field0) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("min_width"));
                                                    }
                                                    __field0 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                __Field::__field1 => {
                                                    if _serde::__private229::Option::is_some(&__field1) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("min_height"));
                                                    }
                                                    __field1 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                _ => {
                                                    let _ =
                                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                                }
                                            }
                                        }
                                        let __field0 =
                                            match __field0 {
                                                _serde::__private229::Some(__field0) => __field0,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("min_width")?,
                                            };
                                        let __field1 =
                                            match __field1 {
                                                _serde::__private229::Some(__field1) => __field1,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("min_height")?,
                                            };
                                        _serde::__private229::Ok(ScalingMode::AutoMin {
                                                min_width: __field0,
                                                min_height: __field1,
                                            })
                                    }
                                }
                                #[doc(hidden)]
                                const FIELDS: &'static [&'static str] =
                                    &["min_width", "min_height"];
                                _serde::de::VariantAccess::struct_variant(__variant, FIELDS,
                                    __Visitor {
                                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                                        lifetime: _serde::__private229::PhantomData,
                                    })
                            }
                            _serde::__private229::Ok((__Field::__field3, __variant)) =>
                                {
                                #[allow(non_camel_case_types)]
                                #[doc(hidden)]
                                enum __Field { __field0, __field1, __ignore, }
                                #[doc(hidden)]
                                struct __FieldVisitor;
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                                    type Value = __Field;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "field identifier")
                                    }
                                    fn visit_u64<__E>(self, __value: u64)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            0u64 => _serde::__private229::Ok(__Field::__field0),
                                            1u64 => _serde::__private229::Ok(__Field::__field1),
                                            _ => _serde::__private229::Ok(__Field::__ignore),
                                        }
                                    }
                                    fn visit_str<__E>(self, __value: &str)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            "max_width" => _serde::__private229::Ok(__Field::__field0),
                                            "max_height" => _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                    fn visit_bytes<__E>(self, __value: &[u8])
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            b"max_width" => _serde::__private229::Ok(__Field::__field0),
                                            b"max_height" =>
                                                _serde::__private229::Ok(__Field::__field1),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                }
                                #[automatically_derived]
                                impl<'de> _serde::Deserialize<'de> for __Field {
                                    #[inline]
                                    fn deserialize<__D>(__deserializer: __D)
                                        -> _serde::__private229::Result<Self, __D::Error> where
                                        __D: _serde::Deserializer<'de> {
                                        _serde::Deserializer::deserialize_identifier(__deserializer,
                                            __FieldVisitor)
                                    }
                                }
                                #[doc(hidden)]
                                struct __Visitor<'de> {
                                    marker: _serde::__private229::PhantomData<ScalingMode>,
                                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                                    type Value = ScalingMode;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "struct variant ScalingMode::AutoMax")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"struct variant ScalingMode::AutoMax with 2 elements")),
                                            };
                                        let __field1 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(1usize,
                                                                &"struct variant ScalingMode::AutoMax with 2 elements")),
                                            };
                                        _serde::__private229::Ok(ScalingMode::AutoMax {
                                                max_width: __field0,
                                                max_height: __field1,
                                            })
                                    }
                                    #[inline]
                                    fn visit_map<__A>(self, mut __map: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::MapAccess<'de> {
                                        let mut __field0: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        let mut __field1: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        while let _serde::__private229::Some(__key) =
                                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                                            match __key {
                                                __Field::__field0 => {
                                                    if _serde::__private229::Option::is_some(&__field0) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("max_width"));
                                                    }
                                                    __field0 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                __Field::__field1 => {
                                                    if _serde::__private229::Option::is_some(&__field1) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("max_height"));
                                                    }
                                                    __field1 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                _ => {
                                                    let _ =
                                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                                }
                                            }
                                        }
                                        let __field0 =
                                            match __field0 {
                                                _serde::__private229::Some(__field0) => __field0,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("max_width")?,
                                            };
                                        let __field1 =
                                            match __field1 {
                                                _serde::__private229::Some(__field1) => __field1,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("max_height")?,
                                            };
                                        _serde::__private229::Ok(ScalingMode::AutoMax {
                                                max_width: __field0,
                                                max_height: __field1,
                                            })
                                    }
                                }
                                #[doc(hidden)]
                                const FIELDS: &'static [&'static str] =
                                    &["max_width", "max_height"];
                                _serde::de::VariantAccess::struct_variant(__variant, FIELDS,
                                    __Visitor {
                                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                                        lifetime: _serde::__private229::PhantomData,
                                    })
                            }
                            _serde::__private229::Ok((__Field::__field4, __variant)) =>
                                {
                                #[allow(non_camel_case_types)]
                                #[doc(hidden)]
                                enum __Field { __field0, __ignore, }
                                #[doc(hidden)]
                                struct __FieldVisitor;
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                                    type Value = __Field;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "field identifier")
                                    }
                                    fn visit_u64<__E>(self, __value: u64)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            0u64 => _serde::__private229::Ok(__Field::__field0),
                                            _ => _serde::__private229::Ok(__Field::__ignore),
                                        }
                                    }
                                    fn visit_str<__E>(self, __value: &str)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            "viewport_height" =>
                                                _serde::__private229::Ok(__Field::__field0),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                    fn visit_bytes<__E>(self, __value: &[u8])
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            b"viewport_height" =>
                                                _serde::__private229::Ok(__Field::__field0),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                }
                                #[automatically_derived]
                                impl<'de> _serde::Deserialize<'de> for __Field {
                                    #[inline]
                                    fn deserialize<__D>(__deserializer: __D)
                                        -> _serde::__private229::Result<Self, __D::Error> where
                                        __D: _serde::Deserializer<'de> {
                                        _serde::Deserializer::deserialize_identifier(__deserializer,
                                            __FieldVisitor)
                                    }
                                }
                                #[doc(hidden)]
                                struct __Visitor<'de> {
                                    marker: _serde::__private229::PhantomData<ScalingMode>,
                                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                                    type Value = ScalingMode;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "struct variant ScalingMode::FixedVertical")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"struct variant ScalingMode::FixedVertical with 1 element")),
                                            };
                                        _serde::__private229::Ok(ScalingMode::FixedVertical {
                                                viewport_height: __field0,
                                            })
                                    }
                                    #[inline]
                                    fn visit_map<__A>(self, mut __map: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::MapAccess<'de> {
                                        let mut __field0: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        while let _serde::__private229::Some(__key) =
                                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                                            match __key {
                                                __Field::__field0 => {
                                                    if _serde::__private229::Option::is_some(&__field0) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("viewport_height"));
                                                    }
                                                    __field0 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                _ => {
                                                    let _ =
                                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                                }
                                            }
                                        }
                                        let __field0 =
                                            match __field0 {
                                                _serde::__private229::Some(__field0) => __field0,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("viewport_height")?,
                                            };
                                        _serde::__private229::Ok(ScalingMode::FixedVertical {
                                                viewport_height: __field0,
                                            })
                                    }
                                }
                                #[doc(hidden)]
                                const FIELDS: &'static [&'static str] =
                                    &["viewport_height"];
                                _serde::de::VariantAccess::struct_variant(__variant, FIELDS,
                                    __Visitor {
                                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                                        lifetime: _serde::__private229::PhantomData,
                                    })
                            }
                            _serde::__private229::Ok((__Field::__field5, __variant)) =>
                                {
                                #[allow(non_camel_case_types)]
                                #[doc(hidden)]
                                enum __Field { __field0, __ignore, }
                                #[doc(hidden)]
                                struct __FieldVisitor;
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                                    type Value = __Field;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "field identifier")
                                    }
                                    fn visit_u64<__E>(self, __value: u64)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            0u64 => _serde::__private229::Ok(__Field::__field0),
                                            _ => _serde::__private229::Ok(__Field::__ignore),
                                        }
                                    }
                                    fn visit_str<__E>(self, __value: &str)
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            "viewport_width" =>
                                                _serde::__private229::Ok(__Field::__field0),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                    fn visit_bytes<__E>(self, __value: &[u8])
                                        -> _serde::__private229::Result<Self::Value, __E> where
                                        __E: _serde::de::Error {
                                        match __value {
                                            b"viewport_width" =>
                                                _serde::__private229::Ok(__Field::__field0),
                                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                                        }
                                    }
                                }
                                #[automatically_derived]
                                impl<'de> _serde::Deserialize<'de> for __Field {
                                    #[inline]
                                    fn deserialize<__D>(__deserializer: __D)
                                        -> _serde::__private229::Result<Self, __D::Error> where
                                        __D: _serde::Deserializer<'de> {
                                        _serde::Deserializer::deserialize_identifier(__deserializer,
                                            __FieldVisitor)
                                    }
                                }
                                #[doc(hidden)]
                                struct __Visitor<'de> {
                                    marker: _serde::__private229::PhantomData<ScalingMode>,
                                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                                    type Value = ScalingMode;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private229::Formatter)
                                        -> _serde::__private229::fmt::Result {
                                        _serde::__private229::Formatter::write_str(__formatter,
                                            "struct variant ScalingMode::FixedHorizontal")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private229::Some(__value) => __value,
                                                _serde::__private229::None =>
                                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"struct variant ScalingMode::FixedHorizontal with 1 element")),
                                            };
                                        _serde::__private229::Ok(ScalingMode::FixedHorizontal {
                                                viewport_width: __field0,
                                            })
                                    }
                                    #[inline]
                                    fn visit_map<__A>(self, mut __map: __A)
                                        -> _serde::__private229::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::MapAccess<'de> {
                                        let mut __field0: _serde::__private229::Option<f32> =
                                            _serde::__private229::None;
                                        while let _serde::__private229::Some(__key) =
                                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                                            match __key {
                                                __Field::__field0 => {
                                                    if _serde::__private229::Option::is_some(&__field0) {
                                                        return _serde::__private229::Err(<__A::Error as
                                                                        _serde::de::Error>::duplicate_field("viewport_width"));
                                                    }
                                                    __field0 =
                                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<f32>(&mut __map)?);
                                                }
                                                _ => {
                                                    let _ =
                                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                                }
                                            }
                                        }
                                        let __field0 =
                                            match __field0 {
                                                _serde::__private229::Some(__field0) => __field0,
                                                _serde::__private229::None =>
                                                    _serde::__private229::de::missing_field("viewport_width")?,
                                            };
                                        _serde::__private229::Ok(ScalingMode::FixedHorizontal {
                                                viewport_width: __field0,
                                            })
                                    }
                                }
                                #[doc(hidden)]
                                const FIELDS: &'static [&'static str] = &["viewport_width"];
                                _serde::de::VariantAccess::struct_variant(__variant, FIELDS,
                                    __Visitor {
                                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                                        lifetime: _serde::__private229::PhantomData,
                                    })
                            }
                            _serde::__private229::Err(__err) =>
                                _serde::__private229::Err(__err),
                        }
                    }
                }
                #[doc(hidden)]
                const VARIANTS: &'static [&'static str] =
                    &["WindowSize", "Fixed", "AutoMin", "AutoMax",
                                "FixedVertical", "FixedHorizontal"];
                _serde::Deserializer::deserialize_enum(__deserializer,
                    "ScalingMode", VARIANTS,
                    __Visitor {
                        marker: _serde::__private229::PhantomData::<ScalingMode>,
                        lifetime: _serde::__private229::PhantomData,
                    })
            }
        }
    };Deserialize)]
522#[reflect(Serialize, Deserialize, Default, Clone)]
523pub enum ScalingMode {
524    /// Match the viewport size.
525    ///
526    /// With a scale of 1, lengths in world units will map 1:1 with the number of pixels used to render it.
527    /// For example, if we have a 64x64 sprite with a [`Transform::scale`](bevy_transform::prelude::Transform) of 1.0,
528    /// no custom size and no inherited scale, the sprite will be 64 world units wide and 64 world units tall.
529    /// When rendered with [`OrthographicProjection::scaling_mode`] set to `WindowSize` when the window scale factor is 1
530    /// the sprite will be rendered at 64 pixels wide and 64 pixels tall.
531    ///
532    /// Changing any of these properties will multiplicatively affect the final size.
533    #[default]
534    WindowSize,
535    /// Manually specify the projection's size, ignoring window resizing. The image will stretch.
536    ///
537    /// Arguments describe the area of the world that is shown (in world units).
538    Fixed { width: f32, height: f32 },
539    /// Keeping the aspect ratio while the axes can't be smaller than given minimum.
540    ///
541    /// Arguments are in world units.
542    AutoMin { min_width: f32, min_height: f32 },
543    /// Keeping the aspect ratio while the axes can't be bigger than given maximum.
544    ///
545    /// Arguments are in world units.
546    AutoMax { max_width: f32, max_height: f32 },
547    /// Keep the projection's height constant; width will be adjusted to match aspect ratio.
548    ///
549    /// The argument is the desired height of the projection in world units.
550    FixedVertical { viewport_height: f32 },
551    /// Keep the projection's width constant; height will be adjusted to match aspect ratio.
552    ///
553    /// The argument is the desired width of the projection in world units.
554    FixedHorizontal { viewport_width: f32 },
555}
556
557/// Project a 3D space onto a 2D surface using parallel lines, i.e., unlike [`PerspectiveProjection`],
558/// the size of objects remains the same regardless of their distance to the camera.
559///
560/// The volume contained in the projection is called the *view frustum*. Since the viewport is rectangular
561/// and projection lines are parallel, the view frustum takes the shape of a cuboid.
562///
563/// Note that the scale of the projection and the apparent size of objects are inversely proportional.
564/// As the size of the projection increases, the size of objects decreases.
565///
566/// # Examples
567///
568/// Configure the orthographic projection to one world unit per 100 window pixels:
569///
570/// ```
571/// # use bevy_camera::{OrthographicProjection, Projection, ScalingMode};
572/// let projection = Projection::Orthographic(OrthographicProjection {
573///     scaling_mode: ScalingMode::WindowSize,
574///     scale: 0.01,
575///     ..OrthographicProjection::default_2d()
576/// });
577/// ```
578#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OrthographicProjection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["near", "far", "viewport_origin", "scaling_mode", "scale",
                        "area"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.near, &self.far, &self.viewport_origin,
                        &self.scaling_mode, &self.scale, &&self.area];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "OrthographicProjection", names, values)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for OrthographicProjection {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            near: ::core::clone::Clone::clone(&self.near),
            far: ::core::clone::Clone::clone(&self.far),
            viewport_origin: ::core::clone::Clone::clone(&self.viewport_origin),
            scaling_mode: ::core::clone::Clone::clone(&self.scaling_mode),
            scale: ::core::clone::Clone::clone(&self.scale),
            area: ::core::clone::Clone::clone(&self.area),
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for OrthographicProjection
            where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectFromWorld, Self,
                    _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <ScalingMode as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Rect as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for OrthographicProjection where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<f32>("near"),
                                                bevy_reflect::NamedField::new::<f32>("far"),
                                                bevy_reflect::NamedField::new::<Vec2>("viewport_origin"),
                                                bevy_reflect::NamedField::new::<ScalingMode>("scaling_mode"),
                                                bevy_reflect::NamedField::new::<f32>("scale"),
                                                bevy_reflect::NamedField::new::<Rect>("area")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for OrthographicProjection where  {
            fn type_path() -> &'static str {
                "bevy_camera::projection::OrthographicProjection"
            }
            fn short_type_path() -> &'static str { "OrthographicProjection" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("OrthographicProjection")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_camera::projection")
            }
        }
        impl bevy_reflect::Reflect for OrthographicProjection 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(<OrthographicProjection
                                        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 OrthographicProjection where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "near" => ::core::option::Option::Some(&self.near),
                    "far" => ::core::option::Option::Some(&self.far),
                    "viewport_origin" =>
                        ::core::option::Option::Some(&self.viewport_origin),
                    "scaling_mode" =>
                        ::core::option::Option::Some(&self.scaling_mode),
                    "scale" => ::core::option::Option::Some(&self.scale),
                    "area" => ::core::option::Option::Some(&self.area),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "near" => ::core::option::Option::Some(&mut self.near),
                    "far" => ::core::option::Option::Some(&mut self.far),
                    "viewport_origin" =>
                        ::core::option::Option::Some(&mut self.viewport_origin),
                    "scaling_mode" =>
                        ::core::option::Option::Some(&mut self.scaling_mode),
                    "scale" => ::core::option::Option::Some(&mut self.scale),
                    "area" => ::core::option::Option::Some(&mut self.area),
                    _ => ::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.near),
                    1usize => ::core::option::Option::Some(&self.far),
                    2usize =>
                        ::core::option::Option::Some(&self.viewport_origin),
                    3usize => ::core::option::Option::Some(&self.scaling_mode),
                    4usize => ::core::option::Option::Some(&self.scale),
                    5usize => ::core::option::Option::Some(&self.area),
                    _ => ::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.near),
                    1usize => ::core::option::Option::Some(&mut self.far),
                    2usize =>
                        ::core::option::Option::Some(&mut self.viewport_origin),
                    3usize =>
                        ::core::option::Option::Some(&mut self.scaling_mode),
                    4usize => ::core::option::Option::Some(&mut self.scale),
                    5usize => ::core::option::Option::Some(&mut self.area),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("near"),
                    1usize => ::core::option::Option::Some("far"),
                    2usize => ::core::option::Option::Some("viewport_origin"),
                    3usize => ::core::option::Option::Some("scaling_mode"),
                    4usize => ::core::option::Option::Some("scale"),
                    5usize => ::core::option::Option::Some("area"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "near" => ::core::option::Option::Some(0usize),
                    "far" => ::core::option::Option::Some(1usize),
                    "viewport_origin" => ::core::option::Option::Some(2usize),
                    "scaling_mode" => ::core::option::Option::Some(3usize),
                    "scale" => ::core::option::Option::Some(4usize),
                    "area" => ::core::option::Option::Some(5usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 6usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                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("near",
                    bevy_reflect::PartialReflect::to_dynamic(&self.near)?);
                dynamic.insert_boxed("far",
                    bevy_reflect::PartialReflect::to_dynamic(&self.far)?);
                dynamic.insert_boxed("viewport_origin",
                    bevy_reflect::PartialReflect::to_dynamic(&self.viewport_origin)?);
                dynamic.insert_boxed("scaling_mode",
                    bevy_reflect::PartialReflect::to_dynamic(&self.scaling_mode)?);
                dynamic.insert_boxed("scale",
                    bevy_reflect::PartialReflect::to_dynamic(&self.scale)?);
                dynamic.insert_boxed("area",
                    bevy_reflect::PartialReflect::to_dynamic(&self.area)?);
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for OrthographicProjection 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)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            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(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for OrthographicProjection 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 {
                            near: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "near")?)?,
                            far: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "far")?)?,
                            viewport_origin: <Vec2 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "viewport_origin")?)?,
                            scaling_mode: <ScalingMode as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "scaling_mode")?)?,
                            scale: <f32 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "scale")?)?,
                            area: <Rect as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "area")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect)]
579#[reflect(Debug, FromWorld, Clone)]
580pub struct OrthographicProjection {
581    /// The distance of the near clipping plane in world units.
582    ///
583    /// Objects closer than this will not be rendered.
584    ///
585    /// Defaults to `0.0`
586    pub near: f32,
587    /// The distance of the far clipping plane in world units.
588    ///
589    /// Objects further than this will not be rendered.
590    ///
591    /// Defaults to `1000.0`
592    pub far: f32,
593    /// Specifies the origin of the viewport as a normalized position from 0 to 1, where (0, 0) is the bottom left
594    /// and (1, 1) is the top right. This determines where the camera's position sits inside the viewport.
595    ///
596    /// When the projection scales due to viewport resizing, the position of the camera, and thereby `viewport_origin`,
597    /// remains at the same relative point.
598    ///
599    /// Consequently, this is pivot point when scaling. With a bottom left pivot, the projection will expand
600    /// upwards and to the right. With a top right pivot, the projection will expand downwards and to the left.
601    /// Values in between will caused the projection to scale proportionally on each axis.
602    ///
603    /// Defaults to `(0.5, 0.5)`, which makes scaling affect opposite sides equally, keeping the center
604    /// point of the viewport centered.
605    pub viewport_origin: Vec2,
606    /// How the projection will scale to the viewport.
607    ///
608    /// Defaults to [`ScalingMode::WindowSize`],
609    /// and works in concert with [`OrthographicProjection::scale`] to determine the final effect.
610    ///
611    /// For simplicity, zooming should be done by changing [`OrthographicProjection::scale`],
612    /// rather than changing the parameters of the scaling mode.
613    pub scaling_mode: ScalingMode,
614    /// Scales the projection.
615    ///
616    /// As scale increases, the apparent size of objects decreases, and vice versa.
617    ///
618    /// Note: scaling can be set by [`scaling_mode`](Self::scaling_mode) as well.
619    /// This parameter scales on top of that.
620    ///
621    /// This property is particularly useful in implementing zoom functionality.
622    ///
623    /// Defaults to `1.0`, which under standard settings corresponds to a 1:1 mapping of world units to rendered pixels.
624    /// See [`ScalingMode::WindowSize`] for more information.
625    pub scale: f32,
626    /// The area that the projection covers relative to `viewport_origin`.
627    ///
628    /// Bevy's `camera_system` automatically
629    /// updates this value when the viewport is resized depending on `OrthographicProjection`'s other fields.
630    /// In this case, `area` should not be manually modified.
631    ///
632    /// It may be necessary to set this manually for shadow projections and such.
633    pub area: Rect,
634}
635
636impl CameraProjection for OrthographicProjection {
637    fn get_clip_from_view(&self) -> Mat4 {
638        proj::orthographic(
639            self.area.min.x,
640            self.area.max.x,
641            self.area.min.y,
642            self.area.max.y,
643            // NOTE: near and far are swapped to invert the depth range from [0,1] to [1,0]
644            // This is for interoperability with pipelines using infinite reverse perspective projections.
645            self.far,
646            self.near,
647        )
648    }
649
650    fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4 {
651        let full_width = sub_view.full_size.x as f32;
652        let full_height = sub_view.full_size.y as f32;
653        let offset_x = sub_view.offset.x;
654        let offset_y = sub_view.offset.y;
655        let sub_width = sub_view.size.x as f32;
656        let sub_height = sub_view.size.y as f32;
657
658        let full_aspect = full_width / full_height;
659
660        // Base the vertical size on self.area and adjust the horizontal size
661        let top = self.area.max.y;
662        let bottom = self.area.min.y;
663        let ortho_height = top - bottom;
664        let ortho_width = ortho_height * full_aspect;
665
666        // Center the orthographic area horizontally
667        let center_x = (self.area.max.x + self.area.min.x) / 2.0;
668        let left = center_x - ortho_width / 2.0;
669        let right = center_x + ortho_width / 2.0;
670
671        // Calculate scaling factors
672        let scale_w = (right - left) / full_width;
673        let scale_h = (top - bottom) / full_height;
674
675        // Calculate the new orthographic bounds
676        let left_prime = left + scale_w * offset_x;
677        let right_prime = left_prime + scale_w * sub_width;
678        let top_prime = top - scale_h * offset_y;
679        let bottom_prime = top_prime - scale_h * sub_height;
680
681        proj::orthographic(
682            left_prime,
683            right_prime,
684            bottom_prime,
685            top_prime,
686            // NOTE: near and far are swapped to invert the depth range from [0,1] to [1,0]
687            // This is for interoperability with pipelines using infinite reverse perspective projections.
688            self.far,
689            self.near,
690        )
691    }
692
693    fn update(&mut self, width: f32, height: f32) {
694        let (projection_width, projection_height) = match self.scaling_mode {
695            ScalingMode::WindowSize => (width, height),
696            ScalingMode::AutoMin {
697                min_width,
698                min_height,
699            } => {
700                // Compare Pixels of current width and minimal height and Pixels of minimal width with current height.
701                // Then use bigger (min_height when true) as what it refers to (height when true) and calculate rest so it can't get under minimum.
702                if width * min_height > min_width * height {
703                    (width * min_height / height, min_height)
704                } else {
705                    (min_width, height * min_width / width)
706                }
707            }
708            ScalingMode::AutoMax {
709                max_width,
710                max_height,
711            } => {
712                // Compare Pixels of current width and maximal height and Pixels of maximal width with current height.
713                // Then use smaller (max_height when true) as what it refers to (height when true) and calculate rest so it can't get over maximum.
714                if width * max_height < max_width * height {
715                    (width * max_height / height, max_height)
716                } else {
717                    (max_width, height * max_width / width)
718                }
719            }
720            ScalingMode::FixedVertical { viewport_height } => {
721                (width * viewport_height / height, viewport_height)
722            }
723            ScalingMode::FixedHorizontal { viewport_width } => {
724                (viewport_width, height * viewport_width / width)
725            }
726            ScalingMode::Fixed { width, height } => (width, height),
727        };
728
729        let origin_x = projection_width * self.viewport_origin.x;
730        let origin_y = projection_height * self.viewport_origin.y;
731
732        self.area = Rect::new(
733            self.scale * -origin_x,
734            self.scale * -origin_y,
735            self.scale * (projection_width - origin_x),
736            self.scale * (projection_height - origin_y),
737        );
738    }
739
740    fn far(&self) -> f32 {
741        self.far
742    }
743
744    fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
745        let area = self.area;
746        // NOTE: These vertices are in the specific order required by [`calculate_cascade`].
747        [
748            Vec3A::new(area.max.x, area.min.y, z_near), // bottom right
749            Vec3A::new(area.max.x, area.max.y, z_near), // top right
750            Vec3A::new(area.min.x, area.max.y, z_near), // top left
751            Vec3A::new(area.min.x, area.min.y, z_near), // bottom left
752            Vec3A::new(area.max.x, area.min.y, z_far),  // bottom right
753            Vec3A::new(area.max.x, area.max.y, z_far),  // top right
754            Vec3A::new(area.min.x, area.max.y, z_far),  // top left
755            Vec3A::new(area.min.x, area.min.y, z_far),  // bottom left
756        ]
757    }
758}
759
760impl FromWorld for OrthographicProjection {
761    fn from_world(_world: &mut World) -> Self {
762        OrthographicProjection::default_3d()
763    }
764}
765
766impl OrthographicProjection {
767    /// Returns the default orthographic projection for a 2D context.
768    ///
769    /// The near plane is set to a negative value so that the camera can still
770    /// render the scene when using positive z coordinates to order foreground elements.
771    pub fn default_2d() -> Self {
772        OrthographicProjection {
773            near: -1000.0,
774            ..OrthographicProjection::default_3d()
775        }
776    }
777
778    /// Returns the default orthographic projection for a 3D context.
779    ///
780    /// The near plane is set to 0.0 so that the camera doesn't render
781    /// objects that are behind it.
782    pub fn default_3d() -> Self {
783        OrthographicProjection {
784            scale: 1.0,
785            near: 0.0,
786            far: 1000.0,
787            viewport_origin: Vec2::new(0.5, 0.5),
788            scaling_mode: ScalingMode::WindowSize,
789            area: Rect::new(-1.0, -1.0, 1.0, 1.0),
790        }
791    }
792}
793
794#[cfg(test)]
795mod tests {
796    use super::*;
797
798    /// The projection matrix must respect a custom near plane value.
799    /// A smaller near plane should produce a different matrix than the default.
800    #[test]
801    fn custom_near_plane_is_respected() {
802        let default_proj = PerspectiveProjection::default();
803        let custom_proj = PerspectiveProjection {
804            near: 0.01,
805            ..Default::default()
806        };
807
808        let default_matrix = default_proj.get_clip_from_view();
809        let custom_matrix = custom_proj.get_clip_from_view();
810
811        assert_ne!(
812            default_matrix, custom_matrix,
813            "A near plane of 0.01 should produce a different projection matrix than the default 0.1"
814        );
815
816        // The w_axis.z element of an infinite reverse perspective matrix equals
817        // the near plane distance. Verify it matches what we requested.
818        assert_eq!(custom_matrix.w_axis.z, 0.01);
819    }
820}