Skip to content

Commit ee94150

Browse files
committed
relations
1 parent 00d8d5d commit ee94150

34 files changed

+4169
-898
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ path = "examples/diagnostics/custom_diagnostic.rs"
258258
name = "ecs_guide"
259259
path = "examples/ecs/ecs_guide.rs"
260260

261+
[[example]]
262+
name = "relations_grouping"
263+
path = "examples/ecs/relations_grouping.rs"
264+
261265
[[example]]
262266
name = "change_detection"
263267
path = "examples/ecs/change_detection.rs"

crates/bevy_core/src/time/fixed_timestep.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::Time;
22
use bevy_ecs::{
33
archetype::{Archetype, ArchetypeComponentId},
4-
component::ComponentId,
4+
component::RelationKindId,
55
query::Access,
66
schedule::ShouldRun,
77
system::{IntoSystem, Local, Res, ResMut, System, SystemId},
@@ -160,7 +160,7 @@ impl System for FixedTimestep {
160160
self.internal_system.archetype_component_access()
161161
}
162162

163-
fn component_access(&self) -> &Access<ComponentId> {
163+
fn component_access(&self) -> &Access<RelationKindId> {
164164
self.internal_system.component_access()
165165
}
166166

crates/bevy_ecs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.5.0" }
2323
bevy_utils = { path = "../bevy_utils", version = "0.5.0" }
2424
bevy_ecs_macros = { path = "macros", version = "0.5.0" }
2525

26+
smallvec = { version = "1.4", features = ["serde"] }
2627
async-channel = "1.4"
2728
bitflags = "1.2"
2829
fixedbitset = "0.4"

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,17 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
258258
fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) {
259259
let (#(#query,)*) = &mut self.0;
260260
#(
261-
#query.new_archetype(archetype);
261+
for (relation_filter, cache) in #query.relation_filter_accesses.iter_mut() {
262+
QueryState::<#query, #filter>::new_archetype(
263+
&#query.fetch_state,
264+
&#query.filter_state,
265+
&mut #query.archetype_component_access,
266+
&*relation_filter,
267+
cache,
268+
archetype
269+
);
270+
}
271+
262272
system_meta
263273
.archetype_component_access
264274
.extend(&#query.archetype_component_access);
@@ -280,7 +290,7 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
280290
world: &'a World,
281291
change_tick: u32,
282292
) -> Self::Item {
283-
let (#(#query,)*) = &state.0;
293+
let (#(#query,)*) = &mut state.0;
284294
QuerySet((#(Query::new(world, #query, system_meta.last_change_tick, change_tick),)*))
285295
}
286296
}

crates/bevy_ecs/src/archetype.rs

Lines changed: 105 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use bevy_utils::HashMap;
2+
use bevy_utils::StableHashMap;
3+
14
use crate::{
25
bundle::BundleId,
3-
component::{ComponentId, StorageType},
6+
component::{RelationKindId, StorageType},
47
entity::{Entity, EntityLocation},
58
storage::{Column, SparseArray, SparseSet, SparseSetIndex, TableId},
69
};
710
use std::{
811
borrow::Cow,
9-
collections::HashMap,
1012
hash::Hash,
1113
ops::{Index, IndexMut},
1214
};
@@ -124,54 +126,73 @@ pub struct Archetype {
124126
entities: Vec<Entity>,
125127
edges: Edges,
126128
table_info: TableInfo,
127-
table_components: Cow<'static, [ComponentId]>,
128-
sparse_set_components: Cow<'static, [ComponentId]>,
129-
pub(crate) unique_components: SparseSet<ComponentId, Column>,
130-
pub(crate) components: SparseSet<ComponentId, ArchetypeComponentInfo>,
129+
table_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
130+
sparse_set_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
131+
pub(crate) unique_components: SparseSet<RelationKindId, Column>,
132+
pub(crate) components: SparseSet<RelationKindId, ArchetypeComponentInfo>,
133+
pub(crate) relations: SparseSet<RelationKindId, StableHashMap<Entity, ArchetypeComponentInfo>>,
131134
}
132135

133136
impl Archetype {
134137
pub fn new(
135138
id: ArchetypeId,
136139
table_id: TableId,
137-
table_components: Cow<'static, [ComponentId]>,
138-
sparse_set_components: Cow<'static, [ComponentId]>,
140+
table_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
141+
sparse_set_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
139142
table_archetype_components: Vec<ArchetypeComponentId>,
140143
sparse_set_archetype_components: Vec<ArchetypeComponentId>,
141144
) -> Self {
145+
// FIXME(Relationships) sort out this capacity weirdness
142146
let mut components =
143147
SparseSet::with_capacity(table_components.len() + sparse_set_components.len());
144-
for (component_id, archetype_component_id) in
148+
let mut relations = SparseSet::new();
149+
for ((kind_id, target), archetype_component_id) in
145150
table_components.iter().zip(table_archetype_components)
146151
{
147-
components.insert(
148-
*component_id,
149-
ArchetypeComponentInfo {
150-
storage_type: StorageType::Table,
151-
archetype_component_id,
152-
},
153-
);
152+
let arch_comp_info = ArchetypeComponentInfo {
153+
storage_type: StorageType::Table,
154+
archetype_component_id,
155+
};
156+
157+
match target {
158+
None => {
159+
components.insert(*kind_id, arch_comp_info);
160+
}
161+
Some(target) => {
162+
let set = relations.get_or_insert_with(*kind_id, StableHashMap::default);
163+
set.insert(*target, arch_comp_info);
164+
}
165+
};
154166
}
155167

156-
for (component_id, archetype_component_id) in sparse_set_components
168+
for ((kind_id, target), archetype_component_id) in sparse_set_components
157169
.iter()
158170
.zip(sparse_set_archetype_components)
159171
{
160-
components.insert(
161-
*component_id,
162-
ArchetypeComponentInfo {
163-
storage_type: StorageType::SparseSet,
164-
archetype_component_id,
165-
},
166-
);
172+
let arch_comp_info = ArchetypeComponentInfo {
173+
storage_type: StorageType::SparseSet,
174+
archetype_component_id,
175+
};
176+
177+
match target {
178+
None => {
179+
components.insert(*kind_id, arch_comp_info);
180+
}
181+
Some(target) => {
182+
let set = relations.get_or_insert_with(*kind_id, StableHashMap::default);
183+
set.insert(*target, arch_comp_info);
184+
}
185+
};
167186
}
187+
168188
Self {
169189
id,
170190
table_info: TableInfo {
171191
id: table_id,
172192
entity_rows: Default::default(),
173193
},
174194
components,
195+
relations,
175196
table_components,
176197
sparse_set_components,
177198
unique_components: SparseSet::new(),
@@ -201,28 +222,38 @@ impl Archetype {
201222
}
202223

203224
#[inline]
204-
pub fn table_components(&self) -> &[ComponentId] {
225+
pub fn table_components(&self) -> &[(RelationKindId, Option<Entity>)] {
205226
&self.table_components
206227
}
207228

208229
#[inline]
209-
pub fn sparse_set_components(&self) -> &[ComponentId] {
230+
pub fn sparse_set_components(&self) -> &[(RelationKindId, Option<Entity>)] {
210231
&self.sparse_set_components
211232
}
212233

213234
#[inline]
214-
pub fn unique_components(&self) -> &SparseSet<ComponentId, Column> {
235+
pub fn unique_components(&self) -> &SparseSet<RelationKindId, Column> {
215236
&self.unique_components
216237
}
217238

218239
#[inline]
219-
pub fn unique_components_mut(&mut self) -> &mut SparseSet<ComponentId, Column> {
240+
pub fn unique_components_mut(&mut self) -> &mut SparseSet<RelationKindId, Column> {
220241
&mut self.unique_components
221242
}
222243

244+
// FIXME(Relationships) this also yields relations which feels weird but also needed
223245
#[inline]
224-
pub fn components(&self) -> impl Iterator<Item = ComponentId> + '_ {
225-
self.components.indices()
246+
pub fn components(&self) -> impl Iterator<Item = (RelationKindId, Option<Entity>)> + '_ {
247+
self.components
248+
.indices()
249+
.map(|kind| (kind, None))
250+
.chain(self.relations.indices().flat_map(move |kind_id| {
251+
self.relations
252+
.get(kind_id)
253+
.unwrap()
254+
.keys()
255+
.map(move |target| (kind_id, Some(*target)))
256+
}))
226257
}
227258

228259
#[inline]
@@ -289,25 +320,51 @@ impl Archetype {
289320
}
290321

291322
#[inline]
292-
pub fn contains(&self, component_id: ComponentId) -> bool {
293-
self.components.contains(component_id)
323+
pub fn contains(&self, relation_kind: RelationKindId, relation_target: Option<Entity>) -> bool {
324+
match relation_target {
325+
None => self.components.contains(relation_kind),
326+
Some(target) => self
327+
.relations
328+
.get(relation_kind)
329+
.map(|set| set.get(&target))
330+
.flatten()
331+
.is_some(),
332+
}
294333
}
295334

335+
// FIXME(Relationships) technically the target is unnecessary here as all `KindId` have the same storage type
296336
#[inline]
297-
pub fn get_storage_type(&self, component_id: ComponentId) -> Option<StorageType> {
298-
self.components
299-
.get(component_id)
300-
.map(|info| info.storage_type)
337+
pub fn get_storage_type(
338+
&self,
339+
relation_kind: RelationKindId,
340+
relation_target: Option<Entity>,
341+
) -> Option<StorageType> {
342+
match relation_target {
343+
None => self.components.get(relation_kind),
344+
Some(target) => self
345+
.relations
346+
.get(relation_kind)
347+
.map(|set| set.get(&target))
348+
.flatten(),
349+
}
350+
.map(|info| info.storage_type)
301351
}
302352

303353
#[inline]
304354
pub fn get_archetype_component_id(
305355
&self,
306-
component_id: ComponentId,
356+
relation_kind: RelationKindId,
357+
relation_target: Option<Entity>,
307358
) -> Option<ArchetypeComponentId> {
308-
self.components
309-
.get(component_id)
310-
.map(|info| info.archetype_component_id)
359+
match relation_target {
360+
None => self.components.get(relation_kind),
361+
Some(target) => self
362+
.relations
363+
.get(relation_kind)
364+
.map(|set| set.get(&target))
365+
.flatten(),
366+
}
367+
.map(|info| info.archetype_component_id)
311368
}
312369
}
313370

@@ -329,8 +386,8 @@ impl ArchetypeGeneration {
329386

330387
#[derive(Hash, PartialEq, Eq)]
331388
pub struct ArchetypeIdentity {
332-
table_components: Cow<'static, [ComponentId]>,
333-
sparse_set_components: Cow<'static, [ComponentId]>,
389+
table_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
390+
sparse_set_components: Cow<'static, [(RelationKindId, Option<Entity>)]>,
334391
}
335392

336393
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -453,6 +510,10 @@ impl Archetypes {
453510
a: ArchetypeId,
454511
b: ArchetypeId,
455512
) -> (&mut Archetype, &mut Archetype) {
513+
if a.0 == b.0 {
514+
panic!("both indexes were the same");
515+
}
516+
456517
if a.index() > b.index() {
457518
let (b_slice, a_slice) = self.archetypes.split_at_mut(a.index());
458519
(&mut a_slice[0], &mut b_slice[b.index()])
@@ -475,8 +536,8 @@ impl Archetypes {
475536
pub(crate) fn get_id_or_insert(
476537
&mut self,
477538
table_id: TableId,
478-
table_components: Vec<ComponentId>,
479-
sparse_set_components: Vec<ComponentId>,
539+
table_components: Vec<(RelationKindId, Option<Entity>)>,
540+
sparse_set_components: Vec<(RelationKindId, Option<Entity>)>,
480541
) -> ArchetypeId {
481542
let table_components = Cow::from(table_components);
482543
let sparse_set_components = Cow::from(sparse_set_components);

0 commit comments

Comments
 (0)