@@ -24,22 +24,208 @@ impl VisibleEntities {
24
24
}
25
25
}
26
26
27
+ type LayerMask = u32 ;
28
+
29
+ /// An identifier for a rendering layer.
30
+ pub type Layer = u8 ;
31
+
32
+ /// Describes which rendering layers an entity belongs to.
33
+ ///
34
+ /// Cameras with this component will only render entities with intersecting
35
+ /// layers.
36
+ ///
37
+ /// There are 32 layers numbered `0` - [`TOTAL_LAYERS`]. Entities may belong to one or more
38
+ /// layers, or no layer at all.
39
+ ///
40
+ /// The [`Default`] instance of `RenderLayers` contains layer `0`, the first layer.
41
+ ///
42
+ /// An entity with this component without any layers is invisible.
43
+ ///
44
+ /// Entities without this component belong to layer `0`.
45
+ #[ derive( Copy , Clone , Reflect , PartialEq , Eq , PartialOrd , Ord ) ]
46
+ #[ reflect( Component ) ]
47
+ pub struct RenderLayers ( LayerMask ) ;
48
+
49
+ impl std:: fmt:: Debug for RenderLayers {
50
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
51
+ f. debug_tuple ( "RenderLayers" )
52
+ . field ( & self . iter ( ) . collect :: < Vec < _ > > ( ) )
53
+ . finish ( )
54
+ }
55
+ }
56
+
57
+ impl std:: iter:: FromIterator < Layer > for RenderLayers {
58
+ fn from_iter < T : IntoIterator < Item = Layer > > ( i : T ) -> Self {
59
+ i. into_iter ( ) . fold ( Self :: none ( ) , |mask, g| mask. with ( g) )
60
+ }
61
+ }
62
+
63
+ /// Defaults to containing to layer `0`, the first layer.
64
+ impl Default for RenderLayers {
65
+ fn default ( ) -> Self {
66
+ RenderLayers :: layer ( 0 )
67
+ }
68
+ }
69
+
70
+ impl RenderLayers {
71
+ /// The total number of layers supported.
72
+ pub const TOTAL_LAYERS : usize = std:: mem:: size_of :: < LayerMask > ( ) * 8 ;
73
+
74
+ /// Create a new `RenderLayers` belonging to the given layer.
75
+ pub fn layer ( n : Layer ) -> Self {
76
+ RenderLayers ( 0 ) . with ( n)
77
+ }
78
+
79
+ /// Create a new `RenderLayers` that belongs to all layers.
80
+ pub fn all ( ) -> Self {
81
+ RenderLayers ( u32:: MAX )
82
+ }
83
+
84
+ /// Create a new `RenderLayers` that belongs to no layers.
85
+ pub fn none ( ) -> Self {
86
+ RenderLayers ( 0 )
87
+ }
88
+
89
+ /// Create a `RenderLayers` from a list of layers.
90
+ pub fn from_layers ( layers : & [ Layer ] ) -> Self {
91
+ layers. iter ( ) . copied ( ) . collect ( )
92
+ }
93
+
94
+ /// Add the given layer.
95
+ ///
96
+ /// This may be called multiple times to allow an entity to belong
97
+ /// to multiple rendering layers. The maximum layer is `TOTAL_LAYERS - 1`.
98
+ ///
99
+ /// # Panics
100
+ /// Panics when called with a layer greater than `TOTAL_LAYERS - 1`.
101
+ pub fn with ( mut self , layer : Layer ) -> Self {
102
+ assert ! ( usize :: from( layer) < Self :: TOTAL_LAYERS ) ;
103
+ self . 0 |= 1 << layer;
104
+ self
105
+ }
106
+
107
+ /// Removes the given rendering layer.
108
+ ///
109
+ /// # Panics
110
+ /// Panics when called with a layer greater than `TOTAL_LAYERS - 1`.
111
+ pub fn without ( mut self , layer : Layer ) -> Self {
112
+ assert ! ( usize :: from( layer) < Self :: TOTAL_LAYERS ) ;
113
+ self . 0 |= 0 << layer;
114
+ self
115
+ }
116
+
117
+ /// Get an iterator of the layers.
118
+ pub fn iter ( & self ) -> impl Iterator < Item = Layer > {
119
+ let total: Layer = std:: convert:: TryInto :: try_into ( Self :: TOTAL_LAYERS ) . unwrap ( ) ;
120
+ let mask = * self ;
121
+ ( 0 ..total) . filter ( move |g| RenderLayers :: layer ( * g) . intersects ( & mask) )
122
+ }
123
+
124
+ /// Determine if a `RenderLayers` intersects another.
125
+ ///
126
+ /// `RenderLayers`s intersect if they share any common layers.
127
+ ///
128
+ /// A `RenderLayers` with no layers will not match any other
129
+ /// `RenderLayers`, even another with no layers.
130
+ pub fn intersects ( & self , other : & RenderLayers ) -> bool {
131
+ ( self . 0 & other. 0 ) > 0
132
+ }
133
+ }
134
+
135
+ #[ cfg( test) ]
136
+ mod rendering_mask_tests {
137
+ use super :: { Layer , RenderLayers } ;
138
+
139
+ #[ test]
140
+ fn rendering_mask_sanity ( ) {
141
+ assert_eq ! (
142
+ RenderLayers :: TOTAL_LAYERS ,
143
+ 32 ,
144
+ "total layers is what we think it is"
145
+ ) ;
146
+ assert_eq ! ( RenderLayers :: layer( 0 ) . 0 , 1 , "layer 0 is mask 1" ) ;
147
+ assert_eq ! ( RenderLayers :: layer( 1 ) . 0 , 2 , "layer 1 is mask 2" ) ;
148
+ assert_eq ! ( RenderLayers :: layer( 0 ) . with( 1 ) . 0 , 3 , "layer 0 + 1 is mask 3" ) ;
149
+ assert ! (
150
+ RenderLayers :: layer( 1 ) . intersects( & RenderLayers :: layer( 1 ) ) ,
151
+ "layers match like layers"
152
+ ) ;
153
+ assert ! (
154
+ RenderLayers :: layer( 0 ) . intersects( & RenderLayers ( 1 ) ) ,
155
+ "a layer of 0 means the mask is just 1 bit"
156
+ ) ;
157
+
158
+ assert ! (
159
+ RenderLayers :: layer( 0 )
160
+ . with( 3 )
161
+ . intersects( & RenderLayers :: layer( 3 ) ) ,
162
+ "a mask will match another mask containing any similar layers"
163
+ ) ;
164
+
165
+ assert ! (
166
+ RenderLayers :: default ( ) . intersects( & RenderLayers :: default ( ) ) ,
167
+ "default masks match each other"
168
+ ) ;
169
+
170
+ assert_eq ! (
171
+ RenderLayers :: layer( 0 ) . intersects( & RenderLayers :: layer( 1 ) ) ,
172
+ false ,
173
+ "masks with differing layers do not match"
174
+ ) ;
175
+ assert_eq ! (
176
+ RenderLayers ( 0 ) . intersects( & RenderLayers ( 0 ) ) ,
177
+ false ,
178
+ "empty masks don't match"
179
+ ) ;
180
+ assert_eq ! (
181
+ RenderLayers :: from_layers( & [ 0 , 2 , 16 , 30 ] )
182
+ . iter( )
183
+ . collect:: <Vec <_>>( ) ,
184
+ vec![ 0 , 2 , 16 , 30 ] ,
185
+ "from_layers and get_layers should roundtrip"
186
+ ) ;
187
+ assert_eq ! (
188
+ format!( "{:?}" , RenderLayers :: from_layers( & [ 0 , 1 , 2 , 3 ] ) ) . as_str( ) ,
189
+ "RenderLayers([0, 1, 2, 3])" ,
190
+ "Debug instance shows layers"
191
+ ) ;
192
+ assert_eq ! (
193
+ RenderLayers :: from_layers( & [ 0 , 1 , 2 ] ) ,
194
+ <RenderLayers as std:: iter:: FromIterator <Layer >>:: from_iter( vec![ 0 , 1 , 2 ] ) ,
195
+ "from_layers and from_iter are equivalent"
196
+ )
197
+ }
198
+ }
199
+
27
200
pub fn visible_entities_system (
28
- mut camera_query : Query < ( & Camera , & GlobalTransform , & mut VisibleEntities ) > ,
29
- visible_query : Query < ( Entity , & Visible ) > ,
201
+ mut camera_query : Query < (
202
+ & Camera ,
203
+ & GlobalTransform ,
204
+ & mut VisibleEntities ,
205
+ Option < & RenderLayers > ,
206
+ ) > ,
207
+ visible_query : Query < ( Entity , & Visible , Option < & RenderLayers > ) > ,
30
208
visible_transform_query : Query < & GlobalTransform , With < Visible > > ,
31
209
) {
32
- for ( camera, camera_global_transform, mut visible_entities) in camera_query. iter_mut ( ) {
210
+ for ( camera, camera_global_transform, mut visible_entities, maybe_camera_mask) in
211
+ camera_query. iter_mut ( )
212
+ {
33
213
visible_entities. value . clear ( ) ;
34
214
let camera_position = camera_global_transform. translation ;
215
+ let camera_mask = maybe_camera_mask. copied ( ) . unwrap_or_default ( ) ;
35
216
36
217
let mut no_transform_order = 0.0 ;
37
218
let mut transparent_entities = Vec :: new ( ) ;
38
- for ( entity, visible) in visible_query. iter ( ) {
219
+ for ( entity, visible, maybe_entity_mask ) in visible_query. iter ( ) {
39
220
if !visible. is_visible {
40
221
continue ;
41
222
}
42
223
224
+ let entity_mask = maybe_entity_mask. copied ( ) . unwrap_or_default ( ) ;
225
+ if !camera_mask. intersects ( & entity_mask) {
226
+ continue ;
227
+ }
228
+
43
229
let order = if let Ok ( global_transform) = visible_transform_query. get ( entity) {
44
230
let position = global_transform. translation ;
45
231
// smaller distances are sorted to lower indices by using the distance from the camera
0 commit comments