@@ -2,42 +2,47 @@ mod pipeline;
22mod render_pass;
33mod ui_material_pipeline;
44
5- use bevy_core_pipeline:: core_2d:: graph:: { Labels2d , SubGraph2d } ;
6- use bevy_core_pipeline:: core_3d:: graph:: { Labels3d , SubGraph3d } ;
7- use bevy_core_pipeline:: { core_2d:: Camera2d , core_3d:: Camera3d } ;
8- use bevy_hierarchy:: Parent ;
9- use bevy_render:: {
10- render_phase:: PhaseItem , render_resource:: BindGroupEntries , view:: ViewVisibility ,
11- ExtractSchedule , Render ,
12- } ;
13- use bevy_sprite:: { SpriteAssetEvents , TextureAtlas } ;
145pub use pipeline:: * ;
156pub use render_pass:: * ;
167pub use ui_material_pipeline:: * ;
178
18- use crate :: graph:: { LabelsUi , SubGraphUi } ;
199use crate :: {
20- texture_slice:: ComputedTextureSlices , BackgroundColor , BorderColor , CalculatedClip ,
21- ContentSize , DefaultUiCamera , Node , Outline , Style , TargetCamera , UiImage , UiScale , Val ,
10+ graph:: { LabelsUi , SubGraphUi } ,
11+ texture_slice:: ComputedTextureSlices ,
12+ BackgroundColor , Border , BorderColor , CalculatedClip , ContentSize , CornerRadius ,
13+ DefaultUiCamera , Node , Outline , Style , TargetCamera , UiImage , UiScale , Val ,
2214} ;
2315
2416use bevy_app:: prelude:: * ;
2517use bevy_asset:: { load_internal_asset, AssetEvent , AssetId , Assets , Handle } ;
18+ use bevy_core_pipeline:: {
19+ core_2d:: {
20+ graph:: { Labels2d , SubGraph2d } ,
21+ Camera2d ,
22+ } ,
23+ core_3d:: {
24+ graph:: { Labels3d , SubGraph3d } ,
25+ Camera3d ,
26+ } ,
27+ } ;
2628use bevy_ecs:: prelude:: * ;
27- use bevy_math:: { Mat4 , Rect , URect , UVec4 , Vec2 , Vec3 , Vec4Swizzles } ;
29+ use bevy_hierarchy:: Parent ;
30+ use bevy_math:: { Mat4 , Rect , URect , UVec4 , Vec2 , Vec3 , Vec4 , Vec4Swizzles } ;
2831use bevy_render:: {
2932 camera:: Camera ,
3033 color:: Color ,
3134 render_asset:: RenderAssets ,
3235 render_graph:: { RenderGraph , RunGraphOnViewNode } ,
33- render_phase:: { sort_phase_system, AddRenderCommand , DrawFunctions , RenderPhase } ,
34- render_resource:: * ,
36+ render_phase:: { sort_phase_system, AddRenderCommand , DrawFunctions , PhaseItem , RenderPhase } ,
37+ render_resource:: { BindGroupEntries , * } ,
3538 renderer:: { RenderDevice , RenderQueue } ,
3639 texture:: Image ,
37- view:: { ExtractedView , ViewUniforms } ,
38- Extract , RenderApp , RenderSet ,
40+ view:: { ExtractedView , ViewUniforms , ViewVisibility } ,
41+ Extract , ExtractSchedule , Render , RenderApp , RenderSet ,
42+ } ;
43+ use bevy_sprite:: {
44+ TextureAtlasLayout , { SpriteAssetEvents , TextureAtlas } ,
3945} ;
40- use bevy_sprite:: TextureAtlasLayout ;
4146#[ cfg( feature = "bevy_text" ) ]
4247use bevy_text:: { PositionedGlyph , Text , TextLayoutInfo } ;
4348use bevy_transform:: components:: GlobalTransform ;
@@ -139,6 +144,9 @@ pub struct ExtractedUiNode {
139144 pub clip : Option < Rect > ,
140145 pub flip_x : bool ,
141146 pub flip_y : bool ,
147+ pub border_color : Option < Color > ,
148+ pub border_width : Option < f32 > ,
149+ pub corner_radius : Option < [ f32 ; 4 ] > ,
142150 // Camera to render this UI node to. By the time it is extracted,
143151 // it is defaulted to a single camera if only one exists.
144152 // Nodes with ambiguous camera will be ignored.
@@ -277,6 +285,9 @@ pub fn extract_uinode_borders(
277285 flip_x : false ,
278286 flip_y : false ,
279287 camera_entity,
288+ border_color : Default :: default ( ) ,
289+ border_width : Default :: default ( ) ,
290+ corner_radius : Default :: default ( ) ,
280291 } ,
281292 ) ;
282293 }
@@ -368,6 +379,9 @@ pub fn extract_uinode_outlines(
368379 flip_x : false ,
369380 flip_y : false ,
370381 camera_entity,
382+ border_color : Default :: default ( ) ,
383+ border_width : Default :: default ( ) ,
384+ corner_radius : Default :: default ( ) ,
371385 } ,
372386 ) ;
373387 }
@@ -392,6 +406,8 @@ pub fn extract_uinodes(
392406 Option < & TextureAtlas > ,
393407 Option < & TargetCamera > ,
394408 Option < & ComputedTextureSlices > ,
409+ Option < & CornerRadius > ,
410+ Option < & Border > ,
395411 ) > ,
396412 > ,
397413) {
@@ -406,6 +422,8 @@ pub fn extract_uinodes(
406422 atlas,
407423 camera,
408424 slices,
425+ corner_radius,
426+ border,
409427 ) in uinode_query. iter ( )
410428 {
411429 let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
@@ -420,7 +438,16 @@ pub fn extract_uinodes(
420438 if let Some ( ( image, slices) ) = maybe_image. zip ( slices) {
421439 extracted_uinodes. uinodes . extend (
422440 slices
423- . extract_ui_nodes ( transform, uinode, color, image, clip, camera_entity)
441+ . extract_ui_nodes (
442+ transform,
443+ uinode,
444+ color,
445+ image,
446+ clip,
447+ camera_entity,
448+ * corner_radius. unwrap ( ) ,
449+ * border. unwrap ( ) ,
450+ )
424451 . map ( |e| ( commands. spawn_empty ( ) . id ( ) , e) ) ,
425452 ) ;
426453 continue ;
@@ -468,6 +495,9 @@ pub fn extract_uinodes(
468495 flip_x,
469496 flip_y,
470497 camera_entity,
498+ border_color : border. map ( |border| border. color ) ,
499+ border_width : border. map ( |border| border. width ) ,
500+ corner_radius : corner_radius. map ( |corner_radius| corner_radius. to_array ( ) ) ,
471501 } ,
472502 ) ;
473503 }
@@ -564,11 +594,22 @@ pub fn extract_text_uinodes(
564594 & ViewVisibility ,
565595 Option < & CalculatedClip > ,
566596 Option < & TargetCamera > ,
597+ Option < & CornerRadius > ,
598+ Option < & Border > ,
567599 ) > ,
568600 > ,
569601) {
570- for ( uinode, global_transform, text, text_layout_info, view_visibility, clip, camera) in
571- uinode_query. iter ( )
602+ for (
603+ uinode,
604+ global_transform,
605+ text,
606+ text_layout_info,
607+ view_visibility,
608+ clip,
609+ camera,
610+ corner_radius,
611+ border,
612+ ) in uinode_query. iter ( )
572613 {
573614 let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
574615 else {
@@ -631,6 +672,9 @@ pub fn extract_text_uinodes(
631672 clip : clip. map ( |clip| clip. clip ) ,
632673 flip_x : false ,
633674 flip_y : false ,
675+ border_color : border. map ( |border| border. color ) ,
676+ border_width : border. map ( |border| border. width ) ,
677+ corner_radius : corner_radius. map ( |corner_radius| corner_radius. to_array ( ) ) ,
634678 camera_entity,
635679 } ,
636680 ) ;
@@ -643,6 +687,26 @@ pub fn extract_text_uinodes(
643687struct UiVertex {
644688 pub position : [ f32 ; 3 ] ,
645689 pub uv : [ f32 ; 2 ] ,
690+ pub uniform_index : u32 ,
691+ }
692+
693+ const MAX_UI_UNIFORM_ENTRIES : usize = 256 ;
694+
695+ #[ repr( C ) ]
696+ #[ derive( Copy , Clone , Debug ) ]
697+ pub struct UiUniform {
698+ entries : [ UiUniformEntry ; MAX_UI_UNIFORM_ENTRIES ] ,
699+ }
700+
701+ #[ repr( C ) ]
702+ #[ derive( Copy , Clone , Debug , Default ) ]
703+ pub struct UiUniformEntry {
704+ pub size : Vec2 ,
705+ pub center : Vec2 ,
706+ pub border_color : u32 ,
707+ pub border_width : f32 ,
708+ /// NOTE: This is a Vec4 because using [f32; 4] with AsStd140 results in a 16-bytes alignment.
709+ pub corner_radius : Vec4 ,
646710 pub color : [ f32 ; 4 ] ,
647711 pub mode : u32 ,
648712}
@@ -651,13 +715,17 @@ struct UiVertex {
651715pub struct UiMeta {
652716 vertices : BufferVec < UiVertex > ,
653717 view_bind_group : Option < BindGroup > ,
718+ ui_uniforms : UiUniform ,
719+ ui_uniform_bind_group : Option < BindGroup > ,
654720}
655721
656722impl Default for UiMeta {
657723 fn default ( ) -> Self {
658724 Self {
659725 vertices : BufferVec :: new ( BufferUsages :: VERTEX ) ,
660726 view_bind_group : None ,
727+ ui_uniforms : Default :: default ( ) ,
728+ ui_uniform_bind_group : None ,
661729 }
662730 }
663731}
@@ -671,10 +739,12 @@ pub(crate) const QUAD_VERTEX_POSITIONS: [Vec3; 4] = [
671739
672740pub ( crate ) const QUAD_INDICES : [ usize ; 6 ] = [ 0 , 2 , 3 , 0 , 1 , 2 ] ;
673741
674- #[ derive( Component ) ]
742+ #[ derive( Component , Debug ) ]
675743pub struct UiBatch {
676744 pub range : Range < u32 > ,
677745 pub image : AssetId < Image > ,
746+ pub ui_uniform_offset : u32 ,
747+ pub z : f32 ,
678748 pub camera : Entity ,
679749}
680750
@@ -787,6 +857,8 @@ pub fn prepare_uinodes(
787857 range : index..index,
788858 image : extracted_uinode. image ,
789859 camera : extracted_uinode. camera_entity ,
860+ ui_uniform_offset : 0 ,
861+ z : 0.0 ,
790862 } ;
791863
792864 batches. push ( ( item. entity , new_batch) ) ;
@@ -937,13 +1009,11 @@ pub fn prepare_uinodes(
9371009 . map ( |pos| pos / atlas_extent)
9381010 } ;
9391011
940- let color = extracted_uinode. color . as_linear_rgba_f32 ( ) ;
9411012 for i in QUAD_INDICES {
9421013 ui_meta. vertices . push ( UiVertex {
9431014 position : positions_clipped[ i] . into ( ) ,
9441015 uv : uvs[ i] . into ( ) ,
945- color,
946- mode,
1016+ uniform_index : 0 ,
9471017 } ) ;
9481018 }
9491019 index += QUAD_INDICES . len ( ) as u32 ;
0 commit comments