/
schedule.rs
113 lines (98 loc) · 3.28 KB
/
schedule.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
use std::{
collections::HashMap,
fmt::{Debug, Formatter, Result as FmtResult},
};
use crate::{Resources, Stage, StageLabel, World};
#[derive(Default)]
pub struct Schedule {
stages: Vec<Box<dyn Stage>>,
index_table: HashMap<Box<dyn StageLabel>, usize>,
}
impl Schedule {
pub fn new() -> Self {
Default::default()
}
fn stage_index(&self, label: &impl StageLabel) -> Option<usize> {
self.index_table.get(label as &dyn StageLabel).cloned()
}
fn insert_stage(&mut self, stage_index: usize, stage: impl Stage) {
self.stages.insert(stage_index, Box::new(stage));
for index in self
.index_table
.values_mut()
.filter(|index| **index >= stage_index)
{
*index += 1;
}
}
fn remove_stage<S: Stage>(&mut self, stage_index: usize) -> S {
let stage = self.stages.remove(stage_index);
for index in self
.index_table
.values_mut()
.filter(|index| **index > stage_index)
{
*index -= 1;
}
*stage.downcast::<S>().map_err(|_| ()).unwrap()
}
fn insert_label(&mut self, stage_index: usize, label: impl StageLabel) {
assert!(!self.index_table.contains_key(&label as &dyn StageLabel));
self.index_table.insert(Box::new(label), stage_index);
}
fn remove_label(&mut self, label: &impl StageLabel) -> Option<usize> {
self.index_table.remove(label as &dyn StageLabel)
}
pub fn add(&mut self, label: impl StageLabel, stage: impl Stage) {
self.insert_label(self.stages.len(), label);
self.stages.push(Box::new(stage));
}
pub fn add_before(
&mut self,
target_label: &impl StageLabel,
label: impl StageLabel,
stage: impl Stage,
) {
let index = self.stage_index(target_label).unwrap();
self.insert_stage(index, stage);
self.insert_label(index, label);
}
pub fn add_after(
&mut self,
target_label: &impl StageLabel,
label: impl StageLabel,
stage: impl Stage,
) {
let index = self.stage_index(target_label).unwrap() + 1;
self.insert_stage(index, stage);
self.insert_label(index, label);
}
pub fn remove<S: Stage>(&mut self, label: &impl StageLabel) -> Option<S> {
self.remove_label(label)
.map(move |index| self.remove_stage(index))
}
pub fn stage_mut<S: Stage>(&mut self, label: &impl StageLabel) -> Option<&mut S> {
self.index_table
.get(label as &dyn StageLabel)
.cloned()
.and_then(move |index| self.stages[index].downcast_mut())
}
pub fn run(&mut self, world: &mut World, resources: &mut Resources) {
for stage in &mut self.stages {
stage.run(world, resources);
}
}
}
impl Debug for Schedule {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut index_table = self.index_table.iter().collect::<Vec<_>>();
index_table.sort_by(|(_, index), (_, other_index)| index.cmp(other_index));
f.debug_map()
.entries(
index_table
.drain(..)
.map(|(label, index)| (label, &self.stages[*index])),
)
.finish()
}
}