goud_engine/ecs/schedule/
system_set.rs1use std::collections::HashSet;
4use std::fmt;
5
6use crate::ecs::system::SystemId;
7
8use super::system_label::{SystemLabel, SystemLabelId};
9use super::system_ordering::SystemOrdering;
10
11#[derive(Debug, Clone)]
16pub struct SystemSet {
17 name: String,
19 systems: Vec<SystemId>,
21 system_set: HashSet<SystemId>,
23}
24
25impl SystemSet {
26 #[inline]
28 pub fn new(name: impl Into<String>) -> Self {
29 Self {
30 name: name.into(),
31 systems: Vec::new(),
32 system_set: HashSet::new(),
33 }
34 }
35
36 #[inline]
38 pub fn with_capacity(name: impl Into<String>, capacity: usize) -> Self {
39 Self {
40 name: name.into(),
41 systems: Vec::with_capacity(capacity),
42 system_set: HashSet::with_capacity(capacity),
43 }
44 }
45
46 #[inline]
48 pub fn name(&self) -> &str {
49 &self.name
50 }
51
52 pub fn add(&mut self, system: SystemId) -> bool {
56 if self.system_set.insert(system) {
57 self.systems.push(system);
58 true
59 } else {
60 false
61 }
62 }
63
64 pub fn remove(&mut self, system: SystemId) -> bool {
68 if self.system_set.remove(&system) {
69 self.systems.retain(|&id| id != system);
70 true
71 } else {
72 false
73 }
74 }
75
76 #[inline]
78 pub fn contains(&self, system: SystemId) -> bool {
79 self.system_set.contains(&system)
80 }
81
82 #[inline]
84 pub fn len(&self) -> usize {
85 self.systems.len()
86 }
87
88 #[inline]
90 pub fn is_empty(&self) -> bool {
91 self.systems.is_empty()
92 }
93
94 #[inline]
96 pub fn iter(&self) -> impl Iterator<Item = SystemId> + '_ {
97 self.systems.iter().copied()
98 }
99
100 pub fn clear(&mut self) {
102 self.systems.clear();
103 self.system_set.clear();
104 }
105}
106
107impl Default for SystemSet {
108 fn default() -> Self {
109 Self::new("DefaultSet")
110 }
111}
112
113#[derive(Debug, Clone)]
122pub struct SystemSetConfig {
123 pub before_labels: Vec<SystemLabelId>,
125 pub after_labels: Vec<SystemLabelId>,
127 pub enabled: bool,
129}
130
131impl Default for SystemSetConfig {
132 fn default() -> Self {
133 Self::new()
134 }
135}
136
137impl SystemSetConfig {
138 pub fn new() -> Self {
140 Self {
141 before_labels: Vec::new(),
142 after_labels: Vec::new(),
143 enabled: true,
144 }
145 }
146
147 pub fn before<L: SystemLabel + Clone>(mut self, label: L) -> Self {
149 self.before_labels.push(SystemLabelId::of(label));
150 self
151 }
152
153 pub fn after<L: SystemLabel + Clone>(mut self, label: L) -> Self {
155 self.after_labels.push(SystemLabelId::of(label));
156 self
157 }
158
159 pub fn enabled(mut self, enabled: bool) -> Self {
161 self.enabled = enabled;
162 self
163 }
164}
165
166#[derive(Debug, Clone)]
176pub struct ChainedSystems {
177 name: String,
179 systems: Vec<SystemId>,
181}
182
183impl ChainedSystems {
184 #[inline]
186 pub fn new(name: impl Into<String>) -> Self {
187 Self {
188 name: name.into(),
189 systems: Vec::new(),
190 }
191 }
192
193 #[inline]
195 pub fn with_capacity(name: impl Into<String>, capacity: usize) -> Self {
196 Self {
197 name: name.into(),
198 systems: Vec::with_capacity(capacity),
199 }
200 }
201
202 #[inline]
204 pub fn name(&self) -> &str {
205 &self.name
206 }
207
208 pub fn add(&mut self, system: SystemId) {
210 self.systems.push(system);
211 }
212
213 pub fn add_after(&mut self, system: SystemId, after: SystemId) {
217 if let Some(pos) = self.systems.iter().position(|&id| id == after) {
218 self.systems.insert(pos + 1, system);
219 } else {
220 self.systems.push(system);
221 }
222 }
223
224 #[inline]
226 pub fn len(&self) -> usize {
227 self.systems.len()
228 }
229
230 #[inline]
232 pub fn is_empty(&self) -> bool {
233 self.systems.is_empty()
234 }
235
236 #[inline]
238 pub fn iter(&self) -> impl Iterator<Item = SystemId> + '_ {
239 self.systems.iter().copied()
240 }
241
242 pub fn to_orderings(&self) -> Vec<SystemOrdering> {
246 self.systems
247 .windows(2)
248 .map(|pair| SystemOrdering::before(pair[0], pair[1]))
249 .collect()
250 }
251
252 pub fn clear(&mut self) {
254 self.systems.clear();
255 }
256}
257
258impl Default for ChainedSystems {
259 fn default() -> Self {
260 Self::new("Chain")
261 }
262}
263
264pub fn chain<I>(systems: I) -> Vec<SystemOrdering>
268where
269 I: IntoIterator<Item = SystemId>,
270{
271 let systems: Vec<_> = systems.into_iter().collect();
272 systems
273 .windows(2)
274 .map(|pair| SystemOrdering::before(pair[0], pair[1]))
275 .collect()
276}
277
278#[derive(Debug, Clone)]
287pub enum LabeledOrderingConstraint {
288 BeforeLabel(SystemLabelId),
290 AfterLabel(SystemLabelId),
292 BeforeSystem(SystemId),
294 AfterSystem(SystemId),
296}
297
298impl LabeledOrderingConstraint {
299 pub fn before_label<L: SystemLabel + Clone>(label: L) -> Self {
301 LabeledOrderingConstraint::BeforeLabel(SystemLabelId::of(label))
302 }
303
304 pub fn after_label<L: SystemLabel + Clone>(label: L) -> Self {
306 LabeledOrderingConstraint::AfterLabel(SystemLabelId::of(label))
307 }
308
309 #[inline]
311 pub fn before_system(id: SystemId) -> Self {
312 LabeledOrderingConstraint::BeforeSystem(id)
313 }
314
315 #[inline]
317 pub fn after_system(id: SystemId) -> Self {
318 LabeledOrderingConstraint::AfterSystem(id)
319 }
320
321 #[inline]
323 pub fn is_label_based(&self) -> bool {
324 matches!(
325 self,
326 LabeledOrderingConstraint::BeforeLabel(_) | LabeledOrderingConstraint::AfterLabel(_)
327 )
328 }
329
330 #[inline]
332 pub fn is_system_based(&self) -> bool {
333 matches!(
334 self,
335 LabeledOrderingConstraint::BeforeSystem(_) | LabeledOrderingConstraint::AfterSystem(_)
336 )
337 }
338}
339
340impl fmt::Display for LabeledOrderingConstraint {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 match self {
343 LabeledOrderingConstraint::BeforeLabel(label) => {
344 write!(f, "before label '{}'", label.name())
345 }
346 LabeledOrderingConstraint::AfterLabel(label) => {
347 write!(f, "after label '{}'", label.name())
348 }
349 LabeledOrderingConstraint::BeforeSystem(id) => {
350 write!(f, "before system {}", id.raw())
351 }
352 LabeledOrderingConstraint::AfterSystem(id) => {
353 write!(f, "after system {}", id.raw())
354 }
355 }
356 }
357}
358
359#[cfg(test)]
360#[path = "tests/system_set_tests.rs"]
361mod tests;