1use bevy_ecs::prelude::{Component, ReflectComponent};
2use bevy_reflect::{std_traits::ReflectDefault, Reflect};
3use smallvec::SmallVec;
4
5pub const DEFAULT_LAYERS: &RenderLayers = &RenderLayers::layer(0);
6
7pub type Layer = usize;
9
10#[derive(impl bevy_ecs::component::Component for RenderLayers where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::clone::Clone for RenderLayers {
#[inline]
fn clone(&self) -> RenderLayers {
RenderLayers(::core::clone::Clone::clone(&self.0))
}
}Clone, const _: () =
{
impl bevy_reflect::GetTypeRegistration for RenderLayers where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
registration.register_type_data::<ReflectComponent, Self>();
registration.register_type_data::<ReflectDefault, Self>();
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<SmallVec<[u64; INLINE_BLOCKS]> as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for RenderLayers where {
#[inline]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(||
{
bevy_reflect::TypeInfo::TupleStruct(bevy_reflect::tuple_struct::TupleStructInfo::new::<Self>(&[bevy_reflect::UnnamedField::new::<SmallVec<[u64; INLINE_BLOCKS]>>(0usize)]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for RenderLayers where {
fn type_path() -> &'static str {
"bevy_camera::visibility::render_layers::RenderLayers"
}
fn short_type_path() -> &'static str { "RenderLayers" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("RenderLayers")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_camera::visibility::render_layers".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_camera::visibility::render_layers")
}
}
impl bevy_reflect::Reflect for RenderLayers where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<RenderLayers
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::tuple_struct::TupleStruct for RenderLayers where {
fn field(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.0),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.0),
_ => ::core::option::Option::None,
}
}
#[inline]
fn field_len(&self) -> usize { 1usize }
#[inline]
fn iter_fields(&self)
-> bevy_reflect::tuple_struct::TupleStructFieldIter {
bevy_reflect::tuple_struct::TupleStructFieldIter::new(self)
}
fn to_dynamic_tuple_struct(&self)
-> bevy_reflect::tuple_struct::DynamicTupleStruct {
let mut dynamic:
bevy_reflect::tuple_struct::DynamicTupleStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed(bevy_reflect::PartialReflect::to_dynamic(&self.0));
dynamic
}
}
impl bevy_reflect::PartialReflect for RenderLayers where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::TupleStruct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (i, value) in
::core::iter::Iterator::enumerate(bevy_reflect::tuple_struct::TupleStruct::iter_fields(struct_value))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::tuple_struct::TupleStruct::field_mut(self, i)
{
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::TupleStruct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::TupleStruct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::TupleStruct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::TupleStruct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::TupleStruct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::tuple_struct::tuple_struct_partial_cmp)(self,
value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for RenderLayers where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::TupleStruct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<SmallVec<[u64; INLINE_BLOCKS]> as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::tuple_struct::TupleStruct::field(__ref_struct,
0)?))() {
__this.0 = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect, #[automatically_derived]
impl ::core::cmp::PartialEq for RenderLayers {
#[inline]
fn eq(&self, other: &RenderLayers) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for RenderLayers {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<SmallVec<[u64; INLINE_BLOCKS]>>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for RenderLayers {
#[inline]
fn partial_cmp(&self, other: &RenderLayers)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for RenderLayers {
#[inline]
fn cmp(&self, other: &RenderLayers) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
19#[reflect(Component, Default, PartialEq, Debug, Clone)]
20pub struct RenderLayers(SmallVec<[u64; INLINE_BLOCKS]>);
21
22const INLINE_BLOCKS: usize = 1;
24
25impl Default for &RenderLayers {
26 fn default() -> Self {
27 DEFAULT_LAYERS
28 }
29}
30
31impl core::fmt::Debug for RenderLayers {
32 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33 f.debug_tuple("RenderLayers")
34 .field(&self.iter().collect::<Vec<_>>())
35 .finish()
36 }
37}
38
39impl FromIterator<Layer> for RenderLayers {
40 fn from_iter<T: IntoIterator<Item = Layer>>(i: T) -> Self {
41 i.into_iter().fold(Self::none(), RenderLayers::with)
42 }
43}
44
45impl Default for RenderLayers {
46 fn default() -> Self {
50 const { Self::layer(0) }
51 }
52}
53
54impl RenderLayers {
55 pub const fn layer(n: Layer) -> Self {
61 let (buffer_index, bit) = Self::layer_info(n);
62 if !(buffer_index < INLINE_BLOCKS) {
{
::core::panicking::panic_fmt(format_args!("layer is out of bounds for const construction"));
}
};assert!(
63 buffer_index < INLINE_BLOCKS,
64 "layer is out of bounds for const construction"
65 );
66 let mut buffer = [0; INLINE_BLOCKS];
67 buffer[buffer_index] = bit;
68 RenderLayers(SmallVec::from_const(buffer))
69 }
70
71 pub const fn none() -> Self {
75 RenderLayers(SmallVec::from_const([0; INLINE_BLOCKS]))
76 }
77
78 pub fn from_layers(layers: &[Layer]) -> Self {
80 layers.iter().copied().collect()
81 }
82
83 #[must_use]
88 pub fn with(mut self, layer: Layer) -> Self {
89 let (buffer_index, bit) = Self::layer_info(layer);
90 self.extend_buffer(buffer_index + 1);
91 self.0[buffer_index] |= bit;
92 self
93 }
94
95 #[must_use]
97 pub fn without(mut self, layer: Layer) -> Self {
98 let (buffer_index, bit) = Self::layer_info(layer);
99 if buffer_index < self.0.len() {
100 self.0[buffer_index] &= !bit;
101 if buffer_index == self.0.len() - 1 {
104 self = self.shrink();
105 }
106 }
107 self
108 }
109
110 pub fn iter(&self) -> impl Iterator<Item = Layer> + '_ {
112 self.0.iter().copied().zip(0..).flat_map(Self::iter_layers)
113 }
114
115 pub fn intersects(&self, other: &RenderLayers) -> bool {
122 if self.0.as_ptr() == other.0.as_ptr() {
125 return true;
126 }
127
128 for (self_layer, other_layer) in self.0.iter().zip(other.0.iter()) {
129 if (*self_layer & *other_layer) != 0 {
130 return true;
131 }
132 }
133
134 false
135 }
136
137 pub fn bits(&self) -> &[u64] {
139 self.0.as_slice()
140 }
141
142 const fn layer_info(layer: usize) -> (usize, u64) {
143 let buffer_index = layer / 64;
144 let bit_index = layer % 64;
145 let bit = 1u64 << bit_index;
146
147 (buffer_index, bit)
148 }
149
150 fn extend_buffer(&mut self, other_len: usize) {
151 let new_size = core::cmp::max(self.0.len(), other_len);
152 self.0.reserve_exact(new_size - self.0.len());
153 self.0.resize(new_size, 0u64);
154 }
155
156 fn iter_layers(buffer_and_offset: (u64, usize)) -> impl Iterator<Item = Layer> + 'static {
157 let (mut buffer, mut layer) = buffer_and_offset;
158 layer *= 64;
159 core::iter::from_fn(move || {
160 if buffer == 0 {
161 return None;
162 }
163 let next = buffer.trailing_zeros() + 1;
164 buffer = buffer.checked_shr(next).unwrap_or(0);
165 layer += next as usize;
166 Some(layer - 1)
167 })
168 }
169
170 pub fn intersection(&self, other: &Self) -> Self {
174 self.combine_blocks(other, |a, b| a & b).shrink()
175 }
176
177 pub fn union(&self, other: &Self) -> Self {
181 self.combine_blocks(other, |a, b| a | b) }
183
184 pub fn symmetric_difference(&self, other: &Self) -> Self {
188 self.combine_blocks(other, |a, b| a ^ b).shrink()
189 }
190
191 fn shrink(mut self) -> Self {
193 let mut any_dropped = false;
194 while self.0.len() > INLINE_BLOCKS && self.0.last() == Some(&0) {
195 self.0.pop();
196 any_dropped = true;
197 }
198 if any_dropped && self.0.len() <= INLINE_BLOCKS {
199 self.0.shrink_to_fit();
200 }
201 self
202 }
203
204 fn combine_blocks(&self, other: &Self, mut f: impl FnMut(u64, u64) -> u64) -> Self {
211 let mut a = self.0.iter();
212 let mut b = other.0.iter();
213 let mask = core::iter::from_fn(|| {
214 let a = a.next().copied();
215 let b = b.next().copied();
216 if a.is_none() && b.is_none() {
217 return None;
218 }
219 Some(f(a.unwrap_or_default(), b.unwrap_or_default()))
220 });
221 Self(mask.collect())
222 }
223}
224
225impl core::ops::BitAnd for RenderLayers {
226 type Output = Self;
227 fn bitand(self, rhs: Self) -> Self::Output {
228 self.intersection(&rhs)
229 }
230}
231
232impl core::ops::BitOr for RenderLayers {
233 type Output = Self;
234 fn bitor(self, rhs: Self) -> Self::Output {
235 self.union(&rhs)
236 }
237}
238
239impl core::ops::BitXor for RenderLayers {
240 type Output = Self;
241 fn bitxor(self, rhs: Self) -> Self::Output {
242 self.symmetric_difference(&rhs)
243 }
244}
245
246#[cfg(test)]
247mod rendering_mask_tests {
248 use super::{Layer, RenderLayers};
249 use smallvec::SmallVec;
250
251 #[test]
252 fn rendering_mask_sanity() {
253 let layer_0 = RenderLayers::layer(0);
254 assert_eq!(layer_0.0.len(), 1, "layer 0 is one buffer");
255 assert_eq!(layer_0.0[0], 1, "layer 0 is mask 1");
256 let layer_1 = RenderLayers::layer(1);
257 assert_eq!(layer_1.0.len(), 1, "layer 1 is one buffer");
258 assert_eq!(layer_1.0[0], 2, "layer 1 is mask 2");
259 let layer_0_1 = RenderLayers::layer(0).with(1);
260 assert_eq!(layer_0_1.0.len(), 1, "layer 0 + 1 is one buffer");
261 assert_eq!(layer_0_1.0[0], 3, "layer 0 + 1 is mask 3");
262 let layer_0_1_without_0 = layer_0_1.without(0);
263 assert_eq!(
264 layer_0_1_without_0.0.len(),
265 1,
266 "layer 0 + 1 - 0 is one buffer"
267 );
268 assert_eq!(layer_0_1_without_0.0[0], 2, "layer 0 + 1 - 0 is mask 2");
269 let layer_0_2345 = RenderLayers::layer(0).with(2345);
270 assert_eq!(layer_0_2345.0.len(), 37, "layer 0 + 2345 is 37 buffers");
271 assert_eq!(layer_0_2345.0[0], 1, "layer 0 + 2345 is mask 1");
272 assert_eq!(
273 layer_0_2345.0[36], 2199023255552,
274 "layer 0 + 2345 is mask 2199023255552"
275 );
276 assert!(
277 layer_0_2345.intersects(&layer_0),
278 "layer 0 + 2345 intersects 0"
279 );
280 assert!(
281 RenderLayers::layer(1).intersects(&RenderLayers::layer(1)),
282 "layers match like layers"
283 );
284 assert!(
285 RenderLayers::layer(0).intersects(&RenderLayers(SmallVec::from_const([1]))),
286 "a layer of 0 means the mask is just 1 bit"
287 );
288
289 assert!(
290 RenderLayers::layer(0)
291 .with(3)
292 .intersects(&RenderLayers::layer(3)),
293 "a mask will match another mask containing any similar layers"
294 );
295
296 assert!(
297 RenderLayers::default().intersects(&RenderLayers::default()),
298 "default masks match each other"
299 );
300
301 assert!(
302 !RenderLayers::layer(0).intersects(&RenderLayers::layer(1)),
303 "masks with differing layers do not match"
304 );
305 assert!(
306 !RenderLayers::none().intersects(&RenderLayers::none()),
307 "empty masks don't match"
308 );
309 assert_eq!(
310 RenderLayers::from_layers(&[0, 2, 16, 30])
311 .iter()
312 .collect::<Vec<_>>(),
313 vec![0, 2, 16, 30],
314 "from_layers and get_layers should roundtrip"
315 );
316 assert_eq!(
317 format!("{:?}", RenderLayers::from_layers(&[0, 1, 2, 3])).as_str(),
318 "RenderLayers([0, 1, 2, 3])",
319 "Debug instance shows layers"
320 );
321 assert_eq!(
322 RenderLayers::from_layers(&[0, 1, 2]),
323 <RenderLayers as FromIterator<Layer>>::from_iter(vec![0, 1, 2]),
324 "from_layers and from_iter are equivalent"
325 );
326
327 let tricky_layers = vec![0, 5, 17, 55, 999, 1025, 1026];
328 let layers = RenderLayers::from_layers(&tricky_layers);
329 let out = layers.iter().collect::<Vec<_>>();
330 assert_eq!(tricky_layers, out, "tricky layers roundtrip");
331 }
332
333 const MANY: RenderLayers = RenderLayers(SmallVec::from_const([u64::MAX]));
334
335 #[test]
336 fn render_layer_ops() {
337 let a = RenderLayers::from_layers(&[2, 4, 6]);
338 let b = RenderLayers::from_layers(&[1, 2, 3, 4, 5]);
339
340 assert_eq!(
341 a.clone() | b.clone(),
342 RenderLayers::from_layers(&[1, 2, 3, 4, 5, 6])
343 );
344 assert_eq!(a.clone() & b.clone(), RenderLayers::from_layers(&[2, 4]));
345 assert_eq!(a ^ b, RenderLayers::from_layers(&[1, 3, 5, 6]));
346
347 assert_eq!(RenderLayers::none() & MANY, RenderLayers::none());
348 assert_eq!(RenderLayers::none() | MANY, MANY);
349 assert_eq!(RenderLayers::none() ^ MANY, MANY);
350 }
351
352 #[test]
353 fn render_layer_shrink() {
354 let layers = RenderLayers::from_layers(&[1, 77]);
356 assert!(layers.0.len() == 2);
357 let layers = layers.without(77);
359 assert!(layers.0.len() == 1);
360 }
361
362 #[test]
363 fn render_layer_iter_no_overflow() {
364 let layers = RenderLayers::from_layers(&[63]);
365 layers.iter().count();
366 }
367}