@@ -2,42 +2,47 @@ mod pipeline;
2
2
mod render_pass;
3
3
mod ui_material_pipeline;
4
4
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 } ;
14
5
pub use pipeline:: * ;
15
6
pub use render_pass:: * ;
16
7
pub use ui_material_pipeline:: * ;
17
8
18
- use crate :: graph:: { LabelsUi , SubGraphUi } ;
19
9
use 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 ,
22
14
} ;
23
15
24
16
use bevy_app:: prelude:: * ;
25
17
use 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
+ } ;
26
28
use 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 } ;
28
31
use bevy_render:: {
29
32
camera:: Camera ,
30
33
color:: Color ,
31
34
render_asset:: RenderAssets ,
32
35
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 , * } ,
35
38
renderer:: { RenderDevice , RenderQueue } ,
36
39
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 } ,
39
45
} ;
40
- use bevy_sprite:: TextureAtlasLayout ;
41
46
#[ cfg( feature = "bevy_text" ) ]
42
47
use bevy_text:: { PositionedGlyph , Text , TextLayoutInfo } ;
43
48
use bevy_transform:: components:: GlobalTransform ;
@@ -139,6 +144,9 @@ pub struct ExtractedUiNode {
139
144
pub clip : Option < Rect > ,
140
145
pub flip_x : bool ,
141
146
pub flip_y : bool ,
147
+ pub border_color : Option < Color > ,
148
+ pub border_width : Option < f32 > ,
149
+ pub corner_radius : Option < [ f32 ; 4 ] > ,
142
150
// Camera to render this UI node to. By the time it is extracted,
143
151
// it is defaulted to a single camera if only one exists.
144
152
// Nodes with ambiguous camera will be ignored.
@@ -277,6 +285,9 @@ pub fn extract_uinode_borders(
277
285
flip_x : false ,
278
286
flip_y : false ,
279
287
camera_entity,
288
+ border_color : Default :: default ( ) ,
289
+ border_width : Default :: default ( ) ,
290
+ corner_radius : Default :: default ( ) ,
280
291
} ,
281
292
) ;
282
293
}
@@ -368,6 +379,9 @@ pub fn extract_uinode_outlines(
368
379
flip_x : false ,
369
380
flip_y : false ,
370
381
camera_entity,
382
+ border_color : Default :: default ( ) ,
383
+ border_width : Default :: default ( ) ,
384
+ corner_radius : Default :: default ( ) ,
371
385
} ,
372
386
) ;
373
387
}
@@ -392,6 +406,8 @@ pub fn extract_uinodes(
392
406
Option < & TextureAtlas > ,
393
407
Option < & TargetCamera > ,
394
408
Option < & ComputedTextureSlices > ,
409
+ Option < & CornerRadius > ,
410
+ Option < & Border > ,
395
411
) > ,
396
412
> ,
397
413
) {
@@ -406,6 +422,8 @@ pub fn extract_uinodes(
406
422
atlas,
407
423
camera,
408
424
slices,
425
+ corner_radius,
426
+ border,
409
427
) in uinode_query. iter ( )
410
428
{
411
429
let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
@@ -420,7 +438,16 @@ pub fn extract_uinodes(
420
438
if let Some ( ( image, slices) ) = maybe_image. zip ( slices) {
421
439
extracted_uinodes. uinodes . extend (
422
440
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
+ )
424
451
. map ( |e| ( commands. spawn_empty ( ) . id ( ) , e) ) ,
425
452
) ;
426
453
continue ;
@@ -468,6 +495,9 @@ pub fn extract_uinodes(
468
495
flip_x,
469
496
flip_y,
470
497
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 ( ) ) ,
471
501
} ,
472
502
) ;
473
503
}
@@ -564,11 +594,22 @@ pub fn extract_text_uinodes(
564
594
& ViewVisibility ,
565
595
Option < & CalculatedClip > ,
566
596
Option < & TargetCamera > ,
597
+ Option < & CornerRadius > ,
598
+ Option < & Border > ,
567
599
) > ,
568
600
> ,
569
601
) {
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 ( )
572
613
{
573
614
let Some ( camera_entity) = camera. map ( TargetCamera :: entity) . or ( default_ui_camera. get ( ) )
574
615
else {
@@ -631,6 +672,9 @@ pub fn extract_text_uinodes(
631
672
clip : clip. map ( |clip| clip. clip ) ,
632
673
flip_x : false ,
633
674
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 ( ) ) ,
634
678
camera_entity,
635
679
} ,
636
680
) ;
@@ -643,6 +687,26 @@ pub fn extract_text_uinodes(
643
687
struct UiVertex {
644
688
pub position : [ f32 ; 3 ] ,
645
689
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 ,
646
710
pub color : [ f32 ; 4 ] ,
647
711
pub mode : u32 ,
648
712
}
@@ -651,13 +715,17 @@ struct UiVertex {
651
715
pub struct UiMeta {
652
716
vertices : BufferVec < UiVertex > ,
653
717
view_bind_group : Option < BindGroup > ,
718
+ ui_uniforms : UiUniform ,
719
+ ui_uniform_bind_group : Option < BindGroup > ,
654
720
}
655
721
656
722
impl Default for UiMeta {
657
723
fn default ( ) -> Self {
658
724
Self {
659
725
vertices : BufferVec :: new ( BufferUsages :: VERTEX ) ,
660
726
view_bind_group : None ,
727
+ ui_uniforms : Default :: default ( ) ,
728
+ ui_uniform_bind_group : None ,
661
729
}
662
730
}
663
731
}
@@ -671,10 +739,12 @@ pub(crate) const QUAD_VERTEX_POSITIONS: [Vec3; 4] = [
671
739
672
740
pub ( crate ) const QUAD_INDICES : [ usize ; 6 ] = [ 0 , 2 , 3 , 0 , 1 , 2 ] ;
673
741
674
- #[ derive( Component ) ]
742
+ #[ derive( Component , Debug ) ]
675
743
pub struct UiBatch {
676
744
pub range : Range < u32 > ,
677
745
pub image : AssetId < Image > ,
746
+ pub ui_uniform_offset : u32 ,
747
+ pub z : f32 ,
678
748
pub camera : Entity ,
679
749
}
680
750
@@ -787,6 +857,8 @@ pub fn prepare_uinodes(
787
857
range : index..index,
788
858
image : extracted_uinode. image ,
789
859
camera : extracted_uinode. camera_entity ,
860
+ ui_uniform_offset : 0 ,
861
+ z : 0.0 ,
790
862
} ;
791
863
792
864
batches. push ( ( item. entity , new_batch) ) ;
@@ -937,13 +1009,11 @@ pub fn prepare_uinodes(
937
1009
. map ( |pos| pos / atlas_extent)
938
1010
} ;
939
1011
940
- let color = extracted_uinode. color . as_linear_rgba_f32 ( ) ;
941
1012
for i in QUAD_INDICES {
942
1013
ui_meta. vertices . push ( UiVertex {
943
1014
position : positions_clipped[ i] . into ( ) ,
944
1015
uv : uvs[ i] . into ( ) ,
945
- color,
946
- mode,
1016
+ uniform_index : 0 ,
947
1017
} ) ;
948
1018
}
949
1019
index += QUAD_INDICES . len ( ) as u32 ;
0 commit comments