@@ -9,7 +9,7 @@ use bevy_render::{
9
9
texture:: Image ,
10
10
} ;
11
11
use bevy_transform:: prelude:: GlobalTransform ;
12
- use bevy_utils:: smallvec:: SmallVec ;
12
+ use bevy_utils:: { smallvec:: SmallVec , warn_once } ;
13
13
use bevy_window:: { PrimaryWindow , WindowRef } ;
14
14
use std:: num:: { NonZeroI16 , NonZeroU16 } ;
15
15
use thiserror:: Error ;
@@ -1844,22 +1844,69 @@ impl TargetCamera {
1844
1844
}
1845
1845
}
1846
1846
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
+
1847
1885
#[ derive( SystemParam ) ]
1848
1886
pub struct DefaultUiCamera < ' w , ' s > {
1849
1887
cameras : Query < ' w , ' s , ( Entity , & ' static Camera ) > ,
1888
+ default_cameras : Query < ' w , ' s , Entity , ( With < Camera > , With < IsDefaultUiCamera > ) > ,
1850
1889
primary_window : Query < ' w , ' s , Entity , With < PrimaryWindow > > ,
1851
1890
}
1852
1891
1853
1892
impl < ' w , ' s > DefaultUiCamera < ' w , ' s > {
1854
1893
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
+ } )
1864
1911
}
1865
1912
}
0 commit comments