@@ -2,43 +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 } ;
26- use bevy_ecs:: entity:: EntityHashMap ;
27- use bevy_ecs:: prelude:: * ;
28- use bevy_math:: { Mat4 , Rect , URect , UVec4 , Vec2 , Vec3 , Vec4Swizzles } ;
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+ } ;
28+ use bevy_ecs:: { entity:: EntityHashMap , prelude:: * } ;
29+ use bevy_hierarchy:: Parent ;
30+ use bevy_math:: { Mat4 , Rect , URect , UVec4 , Vec2 , Vec3 , Vec4 , Vec4Swizzles } ;
2931use bevy_render:: {
3032 camera:: Camera ,
3133 color:: Color ,
3234 render_asset:: RenderAssets ,
3335 render_graph:: { RenderGraph , RunGraphOnViewNode } ,
34- render_phase:: { sort_phase_system, AddRenderCommand , DrawFunctions , RenderPhase } ,
35- render_resource:: * ,
36+ render_phase:: { sort_phase_system, AddRenderCommand , DrawFunctions , PhaseItem , RenderPhase } ,
37+ render_resource:: { BindGroupEntries , * } ,
3638 renderer:: { RenderDevice , RenderQueue } ,
3739 texture:: Image ,
38- view:: { ExtractedView , ViewUniforms } ,
39- Extract , RenderApp , RenderSet ,
40+ view:: { ExtractedView , ViewUniforms , ViewVisibility } ,
41+ Extract , ExtractSchedule , Render , RenderApp , RenderSet ,
42+ } ;
43+ use bevy_sprite:: {
44+ TextureAtlasLayout , { SpriteAssetEvents , TextureAtlas } ,
4045} ;
41- use bevy_sprite:: TextureAtlasLayout ;
4246#[ cfg( feature = "bevy_text" ) ]
4347use bevy_text:: { PositionedGlyph , Text , TextLayoutInfo } ;
4448use bevy_transform:: components:: GlobalTransform ;
@@ -140,6 +144,9 @@ pub struct ExtractedUiNode {
140144 pub clip : Option < Rect > ,
141145 pub flip_x : bool ,
142146 pub flip_y : bool ,
147+ pub border_color : Option < Color > ,
148+ pub border_width : Option < f32 > ,
149+ pub corner_radius : Option < [ f32 ; 4 ] > ,
143150 // Camera to render this UI node to. By the time it is extracted,
144151 // it is defaulted to a single camera if only one exists.
145152 // Nodes with ambiguous camera will be ignored.
@@ -278,6 +285,9 @@ pub fn extract_uinode_borders(
278285 flip_x : false ,
279286 flip_y : false ,
280287 camera_entity,
288+ border_color : Default :: default ( ) ,
289+ border_width : Default :: default ( ) ,
290+ corner_radius : Default :: default ( ) ,
281291 } ,
282292 ) ;
283293 }
@@ -369,6 +379,9 @@ pub fn extract_uinode_outlines(
369379 flip_x : false ,
370380 flip_y : false ,
371381 camera_entity,
382+ border_color : Default :: default ( ) ,
383+ border_width : Default :: default ( ) ,
384+ corner_radius : Default :: default ( ) ,
372385 } ,
373386 ) ;
374387 }
@@ -393,6 +406,8 @@ pub fn extract_uinodes(
393406 Option < & TextureAtlas > ,
394407 Option < & TargetCamera > ,
395408 Option < & ComputedTextureSlices > ,
409+ Option < & CornerRadius > ,
410+ Option < & Border > ,
396411 ) > ,
397412 > ,
398413) {
@@ -407,6 +422,8 @@ pub fn extract_uinodes(
407422 atlas,
408423 camera,
409424 slices,
425+ corner_radius,
426+ border,
410427 ) in uinode_query. iter ( )
411428 {
412429 let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
@@ -421,7 +438,16 @@ pub fn extract_uinodes(
421438 if let Some ( ( image, slices) ) = maybe_image. zip ( slices) {
422439 extracted_uinodes. uinodes . extend (
423440 slices
424- . 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+ )
425451 . map ( |e| ( commands. spawn_empty ( ) . id ( ) , e) ) ,
426452 ) ;
427453 continue ;
@@ -469,6 +495,9 @@ pub fn extract_uinodes(
469495 flip_x,
470496 flip_y,
471497 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 ( ) ) ,
472501 } ,
473502 ) ;
474503 }
@@ -565,11 +594,22 @@ pub fn extract_text_uinodes(
565594 & ViewVisibility ,
566595 Option < & CalculatedClip > ,
567596 Option < & TargetCamera > ,
597+ Option < & CornerRadius > ,
598+ Option < & Border > ,
568599 ) > ,
569600 > ,
570601) {
571- for ( uinode, global_transform, text, text_layout_info, view_visibility, clip, camera) in
572- 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 ( )
573613 {
574614 let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
575615 else {
@@ -632,6 +672,9 @@ pub fn extract_text_uinodes(
632672 clip : clip. map ( |clip| clip. clip ) ,
633673 flip_x : false ,
634674 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 ( ) ) ,
635678 camera_entity,
636679 } ,
637680 ) ;
@@ -644,6 +687,26 @@ pub fn extract_text_uinodes(
644687struct UiVertex {
645688 pub position : [ f32 ; 3 ] ,
646689 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 ,
647710 pub color : [ f32 ; 4 ] ,
648711 pub mode : u32 ,
649712}
@@ -652,13 +715,17 @@ struct UiVertex {
652715pub struct UiMeta {
653716 vertices : BufferVec < UiVertex > ,
654717 view_bind_group : Option < BindGroup > ,
718+ ui_uniforms : UiUniform ,
719+ ui_uniform_bind_group : Option < BindGroup > ,
655720}
656721
657722impl Default for UiMeta {
658723 fn default ( ) -> Self {
659724 Self {
660725 vertices : BufferVec :: new ( BufferUsages :: VERTEX ) ,
661726 view_bind_group : None ,
727+ ui_uniforms : Default :: default ( ) ,
728+ ui_uniform_bind_group : None ,
662729 }
663730 }
664731}
@@ -672,10 +739,12 @@ pub(crate) const QUAD_VERTEX_POSITIONS: [Vec3; 4] = [
672739
673740pub ( crate ) const QUAD_INDICES : [ usize ; 6 ] = [ 0 , 2 , 3 , 0 , 1 , 2 ] ;
674741
675- #[ derive( Component ) ]
742+ #[ derive( Component , Debug ) ]
676743pub struct UiBatch {
677744 pub range : Range < u32 > ,
678745 pub image : AssetId < Image > ,
746+ pub ui_uniform_offset : u32 ,
747+ pub z : f32 ,
679748 pub camera : Entity ,
680749}
681750
@@ -788,6 +857,8 @@ pub fn prepare_uinodes(
788857 range : index..index,
789858 image : extracted_uinode. image ,
790859 camera : extracted_uinode. camera_entity ,
860+ ui_uniform_offset : 0 ,
861+ z : 0.0 ,
791862 } ;
792863
793864 batches. push ( ( item. entity , new_batch) ) ;
@@ -938,13 +1009,11 @@ pub fn prepare_uinodes(
9381009 . map ( |pos| pos / atlas_extent)
9391010 } ;
9401011
941- let color = extracted_uinode. color . as_linear_rgba_f32 ( ) ;
9421012 for i in QUAD_INDICES {
9431013 ui_meta. vertices . push ( UiVertex {
9441014 position : positions_clipped[ i] . into ( ) ,
9451015 uv : uvs[ i] . into ( ) ,
946- color,
947- mode,
1016+ uniform_index : 0 ,
9481017 } ) ;
9491018 }
9501019 index += QUAD_INDICES . len ( ) as u32 ;
0 commit comments