mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 06:00:20 +00:00
Allow user to choose default ui camera (#11436)
# Objective - Resolves #11377 ## Solution - Add marker component `IsDefaultUiCamera` that will be choosen first as the default camera. If you want the IsDefaultUiCamera default camera to be in another window, thats now possible. - `IsDefaultUiCamera` is expected to be within a single Camera, if that assertion fails, one PrimaryWindow Camera will be choosen. --- ## Changelog ### Added - Added `IsDefaultUiCamera` marker component. --------- Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
This commit is contained in:
parent
3851679173
commit
1e241fb6b4
1 changed files with 57 additions and 10 deletions
|
@ -9,7 +9,7 @@ use bevy_render::{
|
||||||
texture::Image,
|
texture::Image,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::GlobalTransform;
|
use bevy_transform::prelude::GlobalTransform;
|
||||||
use bevy_utils::smallvec::SmallVec;
|
use bevy_utils::{smallvec::SmallVec, warn_once};
|
||||||
use bevy_window::{PrimaryWindow, WindowRef};
|
use bevy_window::{PrimaryWindow, WindowRef};
|
||||||
use std::num::{NonZeroI16, NonZeroU16};
|
use std::num::{NonZeroI16, NonZeroU16};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -1844,22 +1844,69 @@ impl TargetCamera {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
/// Marker used to identify default cameras, they will have priority over the [`PrimaryWindow`] camera.
|
||||||
|
///
|
||||||
|
/// This is useful if the [`PrimaryWindow`] has two cameras, one of them used
|
||||||
|
/// just for debug purposes and the user wants a way to choose the default [`Camera`]
|
||||||
|
/// without having to add a [`TargetCamera`] to the root node.
|
||||||
|
///
|
||||||
|
/// Another use is when the user wants the Ui to be in another window by default,
|
||||||
|
/// all that is needed is to place this component on the camera
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ui::prelude::*;
|
||||||
|
/// # use bevy_ecs::prelude::Commands;
|
||||||
|
/// # use bevy_render::camera::{Camera, RenderTarget};
|
||||||
|
/// # use bevy_core_pipeline::prelude::Camera2dBundle;
|
||||||
|
/// # use bevy_window::{Window, WindowRef};
|
||||||
|
///
|
||||||
|
/// fn spawn_camera(mut commands: Commands) {
|
||||||
|
/// let another_window = commands.spawn(Window {
|
||||||
|
/// title: String::from("Another window"),
|
||||||
|
/// ..Default::default()
|
||||||
|
/// }).id();
|
||||||
|
/// commands.spawn((
|
||||||
|
/// Camera2dBundle {
|
||||||
|
/// camera: Camera {
|
||||||
|
/// target: RenderTarget::Window(WindowRef::Entity(another_window)),
|
||||||
|
/// ..Default::default()
|
||||||
|
/// },
|
||||||
|
/// ..Default::default()
|
||||||
|
/// },
|
||||||
|
/// // We add the Marker here so all Ui will spawn in
|
||||||
|
/// // another window if no TargetCamera is specified
|
||||||
|
/// IsDefaultUiCamera
|
||||||
|
/// ));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub struct IsDefaultUiCamera;
|
||||||
|
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct DefaultUiCamera<'w, 's> {
|
pub struct DefaultUiCamera<'w, 's> {
|
||||||
cameras: Query<'w, 's, (Entity, &'static Camera)>,
|
cameras: Query<'w, 's, (Entity, &'static Camera)>,
|
||||||
|
default_cameras: Query<'w, 's, Entity, (With<Camera>, With<IsDefaultUiCamera>)>,
|
||||||
primary_window: Query<'w, 's, Entity, With<PrimaryWindow>>,
|
primary_window: Query<'w, 's, Entity, With<PrimaryWindow>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'w, 's> DefaultUiCamera<'w, 's> {
|
impl<'w, 's> DefaultUiCamera<'w, 's> {
|
||||||
pub fn get(&self) -> Option<Entity> {
|
pub fn get(&self) -> Option<Entity> {
|
||||||
self.cameras
|
self.default_cameras.get_single().ok().or_else(|| {
|
||||||
.iter()
|
// If there isn't a single camera and the query isn't empty, there is two or more cameras queried.
|
||||||
.filter(|(_, c)| match c.target {
|
if !self.default_cameras.is_empty() {
|
||||||
RenderTarget::Window(WindowRef::Primary) => true,
|
warn_once!("Two or more Entities with IsDefaultUiCamera found when only one Camera with this marker is allowed.");
|
||||||
RenderTarget::Window(WindowRef::Entity(w)) => self.primary_window.get(w).is_ok(),
|
}
|
||||||
_ => false,
|
self.cameras
|
||||||
})
|
.iter()
|
||||||
.max_by_key(|(e, c)| (c.order, *e))
|
.filter(|(_, c)| match c.target {
|
||||||
.map(|(e, _)| e)
|
RenderTarget::Window(WindowRef::Primary) => true,
|
||||||
|
RenderTarget::Window(WindowRef::Entity(w)) => {
|
||||||
|
self.primary_window.get(w).is_ok()
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.max_by_key(|(e, c)| (c.order, *e))
|
||||||
|
.map(|(e, _)| e)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue