forked from jakobhellermann/bevy_ecs_dynamic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
methods.rs
137 lines (116 loc) · 3.81 KB
/
methods.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use bevy_ecs::{
component::ComponentId,
prelude::{Component, World},
reflect::AppTypeRegistry,
};
use bevy_reflect::ReflectFromPtr;
use crate::DynamicQuery;
use super::{AndFilter, AndFilters, Fetch, FetchData, OrFilters};
pub struct OrBuilder<'w> {
world: &'w mut World,
filters: AndFilters,
}
pub struct DynamicQueryBuilder<'w> {
world: &'w mut World,
fetches: Vec<Fetch>,
filters: OrFilters,
}
// TODO(err): do not panic on missing registration, instead return error.
fn with_info<C: Component>(world: &mut World) -> FetchData {
let id = world.init_component::<C>();
let type_id = std::any::TypeId::of::<C>();
let registry = world.resource::<AppTypeRegistry>().read();
let from_ptr = registry
.get_type_data::<ReflectFromPtr>(type_id)
.unwrap()
.clone();
FetchData { id, from_ptr }
}
impl<'w> DynamicQueryBuilder<'w> {
pub fn new(world: &'w mut World) -> Self {
Self {
world,
fetches: Vec::new(),
filters: OrFilters(Vec::new()),
}
}
pub fn or(
&mut self,
f: impl for<'a, 'z> FnOnce(&'a mut OrBuilder<'z>) -> &'a mut OrBuilder<'z>,
) -> &mut Self {
let mut conjunction = OrBuilder { world: self.world, filters: AndFilters(Vec::new()) };
f(&mut conjunction);
self.filters.0.push(conjunction.filters);
self
}
pub fn component<T: Component>(&mut self) -> &mut Self {
let data = with_info::<T>(self.world);
self.ref_by_id(data)
}
pub fn component_mut<T: Component>(&mut self) -> &mut Self {
let data = with_info::<T>(self.world);
self.mut_by_id(data)
}
pub fn ref_by_id(&mut self, info: FetchData) -> &mut Self {
self.fetches.push(Fetch::Read(info));
self
}
pub fn mut_by_id(&mut self, info: FetchData) -> &mut Self {
self.fetches.push(Fetch::Mut(info));
self
}
pub fn optional<T: Component>(&mut self) -> &mut Self {
let data = with_info::<T>(self.world);
self.optional_ref_by_id(data)
}
pub fn optional_mut<T: Component>(&mut self) -> &mut Self {
let data = with_info::<T>(self.world);
self.optional_mut_by_id(data)
}
pub fn optional_ref_by_id(&mut self, info: FetchData) -> &mut Self {
self.fetches.push(Fetch::OptionRead(info));
self
}
pub fn optional_mut_by_id(&mut self, info: FetchData) -> &mut Self {
self.fetches.push(Fetch::OptionMut(info));
self
}
pub fn build(&mut self) -> Option<DynamicQuery> {
use std::mem::take;
DynamicQuery::new(take(&mut self.fetches), take(&mut self.filters))
}
}
impl<'w> OrBuilder<'w> {
pub fn with<T: Component>(&mut self) -> &mut Self {
let data = self.world.init_component::<T>();
self.with_by_id(data)
}
pub fn without<T: Component>(&mut self) -> &mut Self {
let data = self.world.init_component::<T>();
self.without_by_id(data)
}
pub fn added<T: Component>(&mut self) -> &mut Self {
let data = self.world.init_component::<T>();
self.added_by_id(data)
}
pub fn changed<T: Component>(&mut self) -> &mut Self {
let data = self.world.init_component::<T>();
self.changed_by_id(data)
}
pub fn with_by_id(&mut self, id: ComponentId) -> &mut Self {
self.filters.0.push(AndFilter::With(id));
self
}
pub fn without_by_id(&mut self, id: ComponentId) -> &mut Self {
self.filters.0.push(AndFilter::Without(id));
self
}
pub fn added_by_id(&mut self, id: ComponentId) -> &mut Self {
self.filters.0.push(AndFilter::Added(id));
self
}
pub fn changed_by_id(&mut self, id: ComponentId) -> &mut Self {
self.filters.0.push(AndFilter::Changed(id));
self
}
}