1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use specs::{Component, Entity, World, WorldExt};
use std::{
any::{self, Any, TypeId},
fmt::{self, Debug, Formatter},
};
#[derive(Copy, Clone)]
pub struct ComponentVtable {
type_id: TypeId,
name: &'static str,
register: fn(world: &mut World),
get_cloned: fn(world: &World, entity: Entity) -> Option<Box<dyn Any>>,
set: fn(world: &mut World, entity: Entity, value: &dyn Any),
debug: fn(item: &dyn Any, f: &mut Formatter<'_>) -> fmt::Result,
}
impl ComponentVtable {
pub fn for_type<T>() -> Self
where
T: Component + Clone + Debug,
<T as Component>::Storage: Default,
{
ComponentVtable {
type_id: TypeId::of::<T>(),
name: any::type_name::<T>(),
register: |world| {
world.register::<T>();
},
get_cloned: |world, entity| {
world
.read_storage::<T>()
.get(entity)
.cloned()
.map(|item| Box::new(item) as Box<dyn Any>)
},
set: |world, entity, value| {
let value: &T = match value.downcast_ref() {
Some(boxed) => &*boxed,
None => panic!("Expected a {}", any::type_name::<T>()),
};
world
.write_storage::<T>()
.insert(entity, value.clone())
.unwrap();
},
debug: |item, f| match item.downcast_ref::<T>() {
Some(item) => Debug::fmt(item, f),
None => panic!("Expected a {}", any::type_name::<T>()),
},
}
}
pub fn applies_to<T: 'static>(&self) -> bool {
self.type_id == TypeId::of::<T>()
}
pub fn name(&self) -> &'static str { self.name }
pub fn debug(&self, item: &dyn Any, f: &mut Formatter<'_>) -> fmt::Result {
(self.debug)(item, f)
}
pub(crate) fn register(&self, world: &mut World) { (self.register)(world); }
pub(crate) fn get_cloned(
&self,
world: &World,
entity: Entity,
) -> Option<Box<dyn Any>> {
(self.get_cloned)(world, entity)
}
pub(crate) fn set(
&self,
world: &mut World,
entity: Entity,
value: &dyn Any,
) {
(self.set)(world, entity, value);
}
}
inventory::collect!(ComponentVtable);