Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_material/src/key.rs
9341 views
1
use bevy_platform::{hash::FixedHasher, sync::Arc};
2
use core::{
3
any::{Any, TypeId},
4
hash::{BuildHasher, Hash, Hasher},
5
};
6
7
/// A type-erased mesh pipeline key, which stores the bits of the key as a `u64`.
8
#[derive(Clone, Copy)]
9
pub struct ErasedMeshPipelineKey {
10
bits: u64,
11
type_id: TypeId,
12
}
13
14
impl ErasedMeshPipelineKey {
15
#[inline]
16
pub fn new<T: 'static>(key: T) -> Self
17
where
18
u64: From<T>,
19
{
20
Self {
21
bits: key.into(),
22
type_id: TypeId::of::<T>(),
23
}
24
}
25
26
#[inline]
27
pub fn downcast<T: 'static + From<u64>>(&self) -> T {
28
assert_eq!(
29
self.type_id,
30
TypeId::of::<T>(),
31
"ErasedMeshPipelineKey::downcast called with wrong type"
32
);
33
self.bits.into()
34
}
35
}
36
37
impl PartialEq for ErasedMeshPipelineKey {
38
#[inline]
39
fn eq(&self, other: &Self) -> bool {
40
self.type_id == other.type_id && self.bits == other.bits
41
}
42
}
43
44
impl Eq for ErasedMeshPipelineKey {}
45
46
impl Hash for ErasedMeshPipelineKey {
47
#[inline]
48
fn hash<H: Hasher>(&self, state: &mut H) {
49
self.type_id.hash(state);
50
self.bits.hash(state);
51
}
52
}
53
54
impl Default for ErasedMeshPipelineKey {
55
fn default() -> Self {
56
Self {
57
bits: 0,
58
type_id: TypeId::of::<()>(),
59
}
60
}
61
}
62
63
impl core::fmt::Debug for ErasedMeshPipelineKey {
64
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65
f.debug_struct("ErasedMeshPipelineKey")
66
.field("type_id", &self.type_id)
67
.field("bits", &format_args!("{:#018x}", self.bits))
68
.finish()
69
}
70
}
71
72
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
73
pub struct ErasedMaterialPipelineKey {
74
pub mesh_key: ErasedMeshPipelineKey,
75
pub material_key: ErasedMaterialKey,
76
pub type_id: TypeId,
77
}
78
79
#[derive(Debug)]
80
pub struct ErasedMaterialKey {
81
type_id: TypeId,
82
hash: u64,
83
value: Box<dyn Any + Send + Sync>,
84
vtable: Arc<ErasedMaterialKeyVTable>,
85
}
86
87
#[derive(Debug)]
88
pub struct ErasedMaterialKeyVTable {
89
clone_fn: fn(&dyn Any) -> Box<dyn Any + Send + Sync>,
90
partial_eq_fn: fn(&dyn Any, &dyn Any) -> bool,
91
}
92
93
impl ErasedMaterialKey {
94
pub fn new<T>(material_key: T) -> Self
95
where
96
T: Clone + Hash + PartialEq + Send + Sync + 'static,
97
{
98
let type_id = TypeId::of::<T>();
99
let hash = FixedHasher::hash_one(&FixedHasher, &material_key);
100
101
fn clone<T: Clone + Send + Sync + 'static>(any: &dyn Any) -> Box<dyn Any + Send + Sync> {
102
Box::new(any.downcast_ref::<T>().unwrap().clone())
103
}
104
fn partial_eq<T: PartialEq + 'static>(a: &dyn Any, b: &dyn Any) -> bool {
105
a.downcast_ref::<T>().unwrap() == b.downcast_ref::<T>().unwrap()
106
}
107
108
Self {
109
type_id,
110
hash,
111
value: Box::new(material_key),
112
vtable: Arc::new(ErasedMaterialKeyVTable {
113
clone_fn: clone::<T>,
114
partial_eq_fn: partial_eq::<T>,
115
}),
116
}
117
}
118
119
pub fn to_key<T: Clone + 'static>(&self) -> T {
120
debug_assert_eq!(self.type_id, TypeId::of::<T>());
121
self.value.downcast_ref::<T>().unwrap().clone()
122
}
123
}
124
125
impl PartialEq for ErasedMaterialKey {
126
fn eq(&self, other: &Self) -> bool {
127
self.type_id == other.type_id
128
&& (self.vtable.partial_eq_fn)(self.value.as_ref(), other.value.as_ref())
129
}
130
}
131
132
impl Eq for ErasedMaterialKey {}
133
134
impl Clone for ErasedMaterialKey {
135
fn clone(&self) -> Self {
136
Self {
137
type_id: self.type_id,
138
hash: self.hash,
139
value: (self.vtable.clone_fn)(self.value.as_ref()),
140
vtable: self.vtable.clone(),
141
}
142
}
143
}
144
145
impl Hash for ErasedMaterialKey {
146
fn hash<H: Hasher>(&self, state: &mut H) {
147
self.type_id.hash(state);
148
self.hash.hash(state);
149
}
150
}
151
152
impl Default for ErasedMaterialKey {
153
fn default() -> Self {
154
Self::new(())
155
}
156
}
157
158