mewo_ecs/galaxy/
entity.rs1use super::{
2 ComponentAccessesOptional, ComponentGroupId, Entity, Galaxy, GenericComponent, QueryAccessType,
3 StorageModifyTransform, StorageTransform,
4};
5use crate::data::TVal;
6use std::marker::PhantomData;
7
8pub trait EntityModifyOnly {}
9pub struct EntityModifyOnlyImpl;
10impl EntityModifyOnly for EntityModifyOnlyImpl {}
11
12pub struct EntityGetter<'gal, T> {
13 galaxy: &'gal Galaxy,
14 trans: Option<StorageTransform>,
15 phantom: PhantomData<T>,
16}
17
18impl<'gal, T> EntityGetter<'gal, T> {
19 pub fn get_entity(&self) -> Entity {
20 match self.trans.as_ref().unwrap() {
21 StorageTransform::Insert(e, _) | StorageTransform::Modify(e, _) => *e,
22 _ => unreachable!(),
23 }
24 }
25
26 pub fn insert<C: GenericComponent + 'static>(&mut self, c: C) -> &mut Self {
27 self.component_maybe_insert::<C>();
28 match self.trans.as_mut().unwrap() {
29 StorageTransform::Insert(_, modify) | StorageTransform::Modify(_, modify) => {
30 modify.insert(C::mewo_component_id(), unsafe {
31 TVal::new(
32 C::mewo_component_size(),
33 &c as *const C as *const u8,
34 C::mewo_component_drop(),
35 )
36 });
37 }
38 _ => unreachable!(),
39 }
40 std::mem::forget(c);
41 self
42 }
43
44 pub fn remove<C: GenericComponent + 'static>(&mut self) -> &mut Self {
45 self.component_maybe_insert::<C>();
46 match self.trans.as_mut().unwrap() {
47 StorageTransform::Insert(_, modify) | StorageTransform::Modify(_, modify) => {
48 modify.remove(C::mewo_component_id());
49 }
50 _ => unreachable!(),
51 }
52 self
53 }
54
55 fn component_maybe_insert<C: GenericComponent + 'static>(&self) {
56 let id = C::mewo_component_id();
57 if self.galaxy.ctyp.read().get_type(id).is_err() {
58 let mut ctyp = self.galaxy.ctyp.write();
59 ctyp.insert_type(id, C::mewo_component_type_entry())
60 .unwrap();
61 }
62 }
63}
64
65impl<'gal, T> EntityGetter<'gal, T>
66where
67 T: EntityModifyOnly,
68{
69 pub fn get<CA: ComponentAccessesOptional>(
70 &mut self,
71 ) -> Option<EntityComponentGetter<'gal, CA>> {
72 Some(EntityComponentGetter::new(
73 self.galaxy,
74 *match self.trans.as_ref().unwrap() {
75 StorageTransform::Modify(e, _) => e,
76 _ => return None?,
77 },
78 ))
79 }
80}
81
82impl<'gal, T> Drop for EntityGetter<'gal, T> {
83 fn drop(&mut self) {
84 self.galaxy
85 .get_storage_transforms()
86 .push(self.trans.take().unwrap());
87 }
88}
89
90pub struct EntityComponentGetter<'gal, CA: ComponentAccessesOptional> {
91 galaxy: &'gal Galaxy,
92 group_id: ComponentGroupId,
93 entity_idx: usize,
94 datas: Vec<Option<*const u8>>,
95 phantom: PhantomData<CA>,
96}
97
98impl<'gal, CA> EntityComponentGetter<'gal, CA>
99where
100 CA: ComponentAccessesOptional,
101{
102 pub fn new(galaxy: &'gal Galaxy, entity: Entity) -> Self {
103 CA::component_maybe_insert(&galaxy.ctyp);
104 let sp = galaxy.sp.read();
105 let cgp = galaxy.cgp.read();
106 let gid = sp.get_entity_group(entity).unwrap();
107 let group = cgp.get_group(gid).unwrap();
108 let query = CA::infos();
109 let mut datas: Vec<Option<*const u8>> = query.iter().map(|_| None).collect();
110 for &cty in group.get_components() {
111 for (idx, &(qcty, qlock)) in query.iter().enumerate() {
112 if qcty == cty {
113 match qlock {
114 QueryAccessType::Read | QueryAccessType::OptionRead => {
115 sp.get_read_lock(gid, cty).unwrap();
116 *datas.get_mut(idx).unwrap() = sp.get_read(gid, cty);
117 }
118 QueryAccessType::Write | QueryAccessType::OptionWrite => {
119 sp.get_write_lock(gid, cty).unwrap();
120 *datas.get_mut(idx).unwrap() = sp.get_read(gid, cty);
121 }
122 };
123 }
124 }
125 }
126 EntityComponentGetter {
127 galaxy,
128 entity_idx: sp.get_entity_idx(gid, entity).unwrap(),
129 group_id: gid,
130 datas: datas.into_iter().collect(),
131 phantom: PhantomData,
132 }
133 }
134
135 pub fn get(&self) -> CA {
136 CA::datas(&self.datas, self.entity_idx)
137 }
138}
139
140impl<'gal, CA> Drop for EntityComponentGetter<'gal, CA>
141where
142 CA: ComponentAccessesOptional,
143{
144 fn drop(&mut self) {
145 let sp = self.galaxy.sp.read();
146 let cgp = self.galaxy.cgp.read();
147 let group = cgp.get_group(self.group_id).unwrap();
148 let query = CA::infos();
149
150 for &cty in group.get_components() {
152 for &(qcty, qlock) in query.iter() {
153 if qcty == cty {
154 match qlock {
155 QueryAccessType::Read | QueryAccessType::OptionRead => {
157 sp.get_read_unlock(self.group_id, cty).unwrap()
158 }
159 QueryAccessType::Write | QueryAccessType::OptionWrite => {
160 sp.get_write_unlock(self.group_id, cty).unwrap()
161 }
162 };
163 }
164 }
165 }
166 }
167}
168
169impl Galaxy {
170 pub fn insert_entity(&self) -> EntityGetter<()> {
171 let e = self.ep.write().insert();
172 EntityGetter {
173 galaxy: self,
174 trans: Some(StorageTransform::Insert(e, StorageModifyTransform::new())),
175 phantom: PhantomData,
176 }
177 }
178
179 pub fn get_entity(&self, entity: Entity) -> Option<EntityGetter<EntityModifyOnlyImpl>> {
180 self.ep.read().has_entity(entity).then_some(EntityGetter {
181 galaxy: self,
182 trans: Some(StorageTransform::Modify(
183 entity,
184 StorageModifyTransform::new(),
185 )),
186 phantom: PhantomData,
187 })
188 }
189
190 pub fn remove_entity(&self, e: Entity) {
191 self.get_storage_transforms()
192 .push(StorageTransform::Remove(e));
193 }
194
195 pub fn get_entities(&self) -> Vec<Entity> {
196 self.ep.read().get_entities()
197 }
198}