forked from amethyst/specs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathordered_track.rs
115 lines (96 loc) · 4.21 KB
/
ordered_track.rs
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
extern crate hibitset;
extern crate shrev;
extern crate specs;
use std::collections::HashMap;
use specs::prelude::*;
struct TrackedComponent(u64);
impl Component for TrackedComponent {
type Storage = FlaggedStorage<Self>;
}
#[derive(Default)]
struct SysA {
reader_id: Option<ReaderId<ComponentEvent>>,
cache: HashMap<u32, (Entity, u64)>,
}
impl<'a> System<'a> for SysA {
type SystemData = (Entities<'a>, ReadStorage<'a, TrackedComponent>);
fn setup(&mut self, res: &mut Resources) {
Self::SystemData::setup(res);
self.reader_id = Some(WriteStorage::<TrackedComponent>::fetch(&res).register_reader());
}
fn run(&mut self, (entities, tracked): Self::SystemData) {
let events = tracked
.channel()
.read(self.reader_id.as_mut().expect("ReaderId not found"));
// These events are received in the same order they were operated on in the last frame.
// However, be careful. Just because you received a `Modified/Inserted` event does not mean that the
// entity at that index has a component. To get the current state of the entity, you should replay the
// events in order to see the final result of the component. Partial iteration over the events might lead
// to weird bugs and issues.
for event in events {
match event {
ComponentEvent::Modified(id) => {
let entity = entities.entity(*id);
if let Some(component) = tracked.get(entity) {
// This is safe because it can only occur after an `Inserted` event, not a
// `Removed` event.
*self.cache.get_mut(id).unwrap() = (entity, component.0);
println!("{:?} was changed to {:?}", entity, component.0);
} else {
println!(
"{:?} was changed, but was removed before the next update.",
entity
);
}
}
ComponentEvent::Inserted(id) => {
let entity = entities.entity(*id);
if let Some(component) = tracked.get(entity) {
self.cache.insert(*id, (entity, component.0));
println!("{:?} had {:?} inserted", entity, component.0);
} else {
println!("{:?} had a component inserted, but was removed before the next update.", entity);
}
}
ComponentEvent::Removed(id) => {
let entity = entities.entity(*id);
self.cache.remove(id);
println!("{:?} had its component removed", entity);
}
}
}
}
}
fn main() {
let mut world = World::new();
let mut dispatcher = DispatcherBuilder::new()
.with(SysA::default(), "sys_a", &[])
.build();
dispatcher.setup(&mut world.res);
let e1 = world.create_entity().with(TrackedComponent(1)).build();
let e2 = world.create_entity().with(TrackedComponent(2)).build();
let e3 = world.create_entity().with(TrackedComponent(3)).build();
let e4 = world.create_entity().with(TrackedComponent(4)).build();
dispatcher.dispatch(&mut world.res);
world.maintain();
{
let mut tracked = world.write_storage::<TrackedComponent>();
tracked.get_mut(e1).unwrap().0 = 0;
tracked.get_mut(e2).unwrap().0 = 50;
tracked.get_mut(e4).unwrap().0 *= 2;
tracked.remove(e1);
}
dispatcher.dispatch(&mut world.res);
world.maintain();
{
let mut tracked = world.write_storage::<TrackedComponent>();
// Note that any removal after a modification won't be seen in the next frame, instead you
// will find no component or if a new component was inserted right after it was inserted then
// then you will find the new inserted component rather than the modified one from earlier.
tracked.get_mut(e3).unwrap().0 = 20;
tracked.remove(e3);
tracked.insert(e3, TrackedComponent(10)).unwrap();
}
dispatcher.dispatch(&mut world.res);
world.maintain();
}