Skip to content

Commit 1e241fb

Browse files
pablo-luamatiqo15
andauthored
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 <[email protected]>
1 parent 3851679 commit 1e241fb

File tree

1 file changed

+57
-10
lines changed

1 file changed

+57
-10
lines changed

crates/bevy_ui/src/ui_node.rs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use bevy_render::{
99
texture::Image,
1010
};
1111
use bevy_transform::prelude::GlobalTransform;
12-
use bevy_utils::smallvec::SmallVec;
12+
use bevy_utils::{smallvec::SmallVec, warn_once};
1313
use bevy_window::{PrimaryWindow, WindowRef};
1414
use std::num::{NonZeroI16, NonZeroU16};
1515
use thiserror::Error;
@@ -1844,22 +1844,69 @@ impl TargetCamera {
18441844
}
18451845
}
18461846

1847+
#[derive(Component)]
1848+
/// Marker used to identify default cameras, they will have priority over the [`PrimaryWindow`] camera.
1849+
///
1850+
/// This is useful if the [`PrimaryWindow`] has two cameras, one of them used
1851+
/// just for debug purposes and the user wants a way to choose the default [`Camera`]
1852+
/// without having to add a [`TargetCamera`] to the root node.
1853+
///
1854+
/// Another use is when the user wants the Ui to be in another window by default,
1855+
/// all that is needed is to place this component on the camera
1856+
///
1857+
/// ```
1858+
/// # use bevy_ui::prelude::*;
1859+
/// # use bevy_ecs::prelude::Commands;
1860+
/// # use bevy_render::camera::{Camera, RenderTarget};
1861+
/// # use bevy_core_pipeline::prelude::Camera2dBundle;
1862+
/// # use bevy_window::{Window, WindowRef};
1863+
///
1864+
/// fn spawn_camera(mut commands: Commands) {
1865+
/// let another_window = commands.spawn(Window {
1866+
/// title: String::from("Another window"),
1867+
/// ..Default::default()
1868+
/// }).id();
1869+
/// commands.spawn((
1870+
/// Camera2dBundle {
1871+
/// camera: Camera {
1872+
/// target: RenderTarget::Window(WindowRef::Entity(another_window)),
1873+
/// ..Default::default()
1874+
/// },
1875+
/// ..Default::default()
1876+
/// },
1877+
/// // We add the Marker here so all Ui will spawn in
1878+
/// // another window if no TargetCamera is specified
1879+
/// IsDefaultUiCamera
1880+
/// ));
1881+
/// }
1882+
/// ```
1883+
pub struct IsDefaultUiCamera;
1884+
18471885
#[derive(SystemParam)]
18481886
pub struct DefaultUiCamera<'w, 's> {
18491887
cameras: Query<'w, 's, (Entity, &'static Camera)>,
1888+
default_cameras: Query<'w, 's, Entity, (With<Camera>, With<IsDefaultUiCamera>)>,
18501889
primary_window: Query<'w, 's, Entity, With<PrimaryWindow>>,
18511890
}
18521891

18531892
impl<'w, 's> DefaultUiCamera<'w, 's> {
18541893
pub fn get(&self) -> Option<Entity> {
1855-
self.cameras
1856-
.iter()
1857-
.filter(|(_, c)| match c.target {
1858-
RenderTarget::Window(WindowRef::Primary) => true,
1859-
RenderTarget::Window(WindowRef::Entity(w)) => self.primary_window.get(w).is_ok(),
1860-
_ => false,
1861-
})
1862-
.max_by_key(|(e, c)| (c.order, *e))
1863-
.map(|(e, _)| e)
1894+
self.default_cameras.get_single().ok().or_else(|| {
1895+
// If there isn't a single camera and the query isn't empty, there is two or more cameras queried.
1896+
if !self.default_cameras.is_empty() {
1897+
warn_once!("Two or more Entities with IsDefaultUiCamera found when only one Camera with this marker is allowed.");
1898+
}
1899+
self.cameras
1900+
.iter()
1901+
.filter(|(_, c)| match c.target {
1902+
RenderTarget::Window(WindowRef::Primary) => true,
1903+
RenderTarget::Window(WindowRef::Entity(w)) => {
1904+
self.primary_window.get(w).is_ok()
1905+
}
1906+
_ => false,
1907+
})
1908+
.max_by_key(|(e, c)| (c.order, *e))
1909+
.map(|(e, _)| e)
1910+
})
18641911
}
18651912
}

0 commit comments

Comments
 (0)