@@ -20,6 +20,7 @@ use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
2020use bevy_core_pipeline:: { core_2d:: Camera2d , core_3d:: Camera3d } ;
2121use bevy_ecs:: entity:: hash_map:: EntityHashMap ;
2222use bevy_ecs:: prelude:: * ;
23+ use bevy_ecs:: system:: SystemParam ;
2324use bevy_image:: prelude:: * ;
2425use bevy_math:: { FloatOrd , Mat4 , Rect , UVec4 , Vec2 , Vec3 , Vec3Swizzles , Vec4Swizzles } ;
2526use bevy_render:: render_graph:: { NodeRunError , RenderGraphContext } ;
@@ -251,6 +252,54 @@ impl ExtractedUiNodes {
251252 }
252253}
253254
255+ #[ derive( SystemParam ) ]
256+ pub struct UiCameraMap < ' w , ' s > {
257+ default : DefaultUiCamera < ' w , ' s > ,
258+ mapping : Query < ' w , ' s , RenderEntity > ,
259+ }
260+
261+ impl < ' w , ' s > UiCameraMap < ' w , ' s > {
262+ /// Get the default camera and create the mapper
263+ pub fn get_mapper ( & ' w self ) -> UiCameraMapper < ' w , ' s > {
264+ let default_camera_entity = self . default . get ( ) ;
265+ UiCameraMapper {
266+ mapping : & self . mapping ,
267+ default_camera_entity,
268+ camera_entity : Entity :: PLACEHOLDER ,
269+ render_entity : Entity :: PLACEHOLDER ,
270+ }
271+ }
272+ }
273+
274+ pub struct UiCameraMapper < ' w , ' s > {
275+ mapping : & ' w Query < ' w , ' s , RenderEntity > ,
276+ default_camera_entity : Option < Entity > ,
277+ camera_entity : Entity ,
278+ render_entity : Entity ,
279+ }
280+
281+ impl < ' w , ' s > UiCameraMapper < ' w , ' s > {
282+ /// Returns the render entity corresponding to the given `UiTargetCamera` or the default camera if `None`.
283+ pub fn map ( & mut self , camera : Option < & UiTargetCamera > ) -> Option < Entity > {
284+ let camera_entity = camera
285+ . map ( UiTargetCamera :: entity)
286+ . or ( self . default_camera_entity ) ?;
287+ if self . camera_entity != camera_entity {
288+ let Ok ( new_render_camera_entity) = self . mapping . get ( camera_entity) else {
289+ return None ;
290+ } ;
291+ self . render_entity = new_render_camera_entity;
292+ self . camera_entity = camera_entity;
293+ }
294+
295+ Some ( self . render_entity )
296+ }
297+
298+ pub fn current_camera ( & self ) -> Entity {
299+ self . camera_entity
300+ }
301+ }
302+
254303/// A [`RenderGraphNode`] that executes the UI rendering subgraph on the UI
255304/// view.
256305struct RunUiSubgraphOnUiViewNode ;
@@ -279,7 +328,6 @@ impl RenderGraphNode for RunUiSubgraphOnUiViewNode {
279328pub fn extract_uinode_background_colors (
280329 mut commands : Commands ,
281330 mut extracted_uinodes : ResMut < ExtractedUiNodes > ,
282- default_ui_camera : Extract < DefaultUiCamera > ,
283331 uinode_query : Extract <
284332 Query < (
285333 Entity ,
@@ -291,21 +339,13 @@ pub fn extract_uinode_background_colors(
291339 & BackgroundColor ,
292340 ) > ,
293341 > ,
294- mapping : Extract < Query < RenderEntity > > ,
342+ camera_map : Extract < UiCameraMap > ,
295343) {
296- let default_camera_entity = default_ui_camera. get ( ) ;
344+ let mut camera_mapper = camera_map. get_mapper ( ) ;
345+
297346 for ( entity, uinode, transform, inherited_visibility, clip, camera, background_color) in
298347 & uinode_query
299348 {
300- let Some ( camera_entity) = camera. map ( UiTargetCamera :: entity) . or ( default_camera_entity)
301- else {
302- continue ;
303- } ;
304-
305- let Ok ( extracted_camera_entity) = mapping. get ( camera_entity) else {
306- continue ;
307- } ;
308-
309349 // Skip invisible backgrounds
310350 if !inherited_visibility. get ( )
311351 || background_color. 0 . is_fully_transparent ( )
@@ -314,6 +354,10 @@ pub fn extract_uinode_background_colors(
314354 continue ;
315355 }
316356
357+ let Some ( extracted_camera_entity) = camera_mapper. map ( camera) else {
358+ continue ;
359+ } ;
360+
317361 extracted_uinodes. uinodes . insert (
318362 commands. spawn ( TemporaryRenderEntity ) . id ( ) ,
319363 ExtractedUiNode {
@@ -345,7 +389,6 @@ pub fn extract_uinode_images(
345389 mut commands : Commands ,
346390 mut extracted_uinodes : ResMut < ExtractedUiNodes > ,
347391 texture_atlases : Extract < Res < Assets < TextureAtlasLayout > > > ,
348- default_ui_camera : Extract < DefaultUiCamera > ,
349392 uinode_query : Extract <
350393 Query < (
351394 Entity ,
@@ -357,19 +400,10 @@ pub fn extract_uinode_images(
357400 & ImageNode ,
358401 ) > ,
359402 > ,
360- mapping : Extract < Query < RenderEntity > > ,
403+ camera_map : Extract < UiCameraMap > ,
361404) {
362- let default_camera_entity = default_ui_camera . get ( ) ;
405+ let mut camera_mapper = camera_map . get_mapper ( ) ;
363406 for ( entity, uinode, transform, inherited_visibility, clip, camera, image) in & uinode_query {
364- let Some ( camera_entity) = camera. map ( UiTargetCamera :: entity) . or ( default_camera_entity)
365- else {
366- continue ;
367- } ;
368-
369- let Ok ( extracted_camera_entity) = mapping. get ( camera_entity) else {
370- continue ;
371- } ;
372-
373407 // Skip invisible images
374408 if !inherited_visibility. get ( )
375409 || image. color . is_fully_transparent ( )
@@ -380,6 +414,10 @@ pub fn extract_uinode_images(
380414 continue ;
381415 }
382416
417+ let Some ( extracted_camera_entity) = camera_mapper. map ( camera) else {
418+ continue ;
419+ } ;
420+
383421 let atlas_rect = image
384422 . texture_atlas
385423 . as_ref ( )
@@ -436,7 +474,6 @@ pub fn extract_uinode_images(
436474pub fn extract_uinode_borders (
437475 mut commands : Commands ,
438476 mut extracted_uinodes : ResMut < ExtractedUiNodes > ,
439- default_ui_camera : Extract < DefaultUiCamera > ,
440477 uinode_query : Extract <
441478 Query < (
442479 Entity ,
@@ -449,10 +486,11 @@ pub fn extract_uinode_borders(
449486 AnyOf < ( & BorderColor , & Outline ) > ,
450487 ) > ,
451488 > ,
452- mapping : Extract < Query < RenderEntity > > ,
489+ camera_map : Extract < UiCameraMap > ,
453490) {
454491 let image = AssetId :: < Image > :: default ( ) ;
455- let default_camera_entity = default_ui_camera. get ( ) ;
492+ let mut camera_mapper = camera_map. get_mapper ( ) ;
493+
456494 for (
457495 entity,
458496 node,
@@ -464,22 +502,15 @@ pub fn extract_uinode_borders(
464502 ( maybe_border_color, maybe_outline) ,
465503 ) in & uinode_query
466504 {
467- let Some ( camera_entity) = maybe_camera
468- . map ( UiTargetCamera :: entity)
469- . or ( default_camera_entity)
470- else {
471- continue ;
472- } ;
473-
474- let Ok ( extracted_camera_entity) = mapping. get ( camera_entity) else {
475- continue ;
476- } ;
477-
478505 // Skip invisible borders and removed nodes
479506 if !inherited_visibility. get ( ) || node. display == Display :: None {
480507 continue ;
481508 }
482509
510+ let Some ( extracted_camera_entity) = camera_mapper. map ( maybe_camera) else {
511+ continue ;
512+ } ;
513+
483514 // Don't extract borders with zero width along all edges
484515 if computed_node. border ( ) != BorderRect :: ZERO {
485516 if let Some ( border_color) = maybe_border_color. filter ( |bc| !bc. 0 . is_fully_transparent ( ) )
@@ -675,7 +706,6 @@ pub fn extract_ui_camera_view(
675706pub fn extract_text_sections (
676707 mut commands : Commands ,
677708 mut extracted_uinodes : ResMut < ExtractedUiNodes > ,
678- default_ui_camera : Extract < DefaultUiCamera > ,
679709 texture_atlases : Extract < Res < Assets < TextureAtlasLayout > > > ,
680710 uinode_query : Extract <
681711 Query < (
@@ -690,12 +720,12 @@ pub fn extract_text_sections(
690720 ) > ,
691721 > ,
692722 text_styles : Extract < Query < & TextColor > > ,
693- mapping : Extract < Query < RenderEntity > > ,
723+ camera_map : Extract < UiCameraMap > ,
694724) {
695725 let mut start = 0 ;
696726 let mut end = 1 ;
697727
698- let default_ui_camera = default_ui_camera . get ( ) ;
728+ let mut camera_mapper = camera_map . get_mapper ( ) ;
699729 for (
700730 entity,
701731 uinode,
@@ -707,16 +737,12 @@ pub fn extract_text_sections(
707737 text_layout_info,
708738 ) in & uinode_query
709739 {
710- let Some ( camera_entity) = camera. map ( UiTargetCamera :: entity) . or ( default_ui_camera) else {
711- continue ;
712- } ;
713-
714740 // Skip if not visible or if size is set to zero (e.g. when a parent is set to `Display::None`)
715741 if !inherited_visibility. get ( ) || uinode. is_empty ( ) {
716742 continue ;
717743 }
718744
719- let Ok ( extracted_camera_entity) = mapping . get ( camera_entity ) else {
745+ let Some ( extracted_camera_entity) = camera_mapper . map ( camera ) else {
720746 continue ;
721747 } ;
722748
0 commit comments