edict
edict copied to clipboard
[Discussion] New filter API
I have two complains about the current edict API:
- There is no way to get entities if one or another component is modified. The current
query::<(Modified<&A>, Modified<&B>)>()
means that both components are modified; - The tracked query without
Modified
likequery::<(&A, &B)>.tracked(&mut tracks)
is meaningless; - Mutation of
tracks
by query is not intuitive. I have to clonetracks
to pass it to multiple queries.
I propose this changes:
- Remove
Modified
query; - Remove methods like
World::for_each_tracked
andQueryRef::tracked_iter
; - Move
skip_chunk
andskip_item
fromQuery
toFilter
; - Add
Modified<T>
which owns it's tracks andModifiedSince<T>
which refers the tracks from outside. - Add
Or
andAnd
filters; - Add constructors
with::<T>()
,without::<T>()
,modified_since::<T>(tracks)
andmodified::<T>()
; - Add
.or(filter)
and.and(filter)
methods toFilter
trait; - Add methods like
World::for_each_filtered
andQueryRef::filter
or eventWorld::query_filtered
like bevy_ecs does.
Query with this changes will look like:
// the stateful filter is created outside the loop
let mut my_filter = with::<Foo>().or(with::<Bar>()).and(modified::<Baz>());
loop {
for _, (bar, baz) in world.query_filtered<(&Bar, &Baz)>(&mut my_filter) {
// do something
}
}
and with passing the tracks manually:
let mut tracks = world.tracks_now()
loop {
world.for_each_filtered::<(&Bar, &Baz)>(
&mut with::<Foo>()
.or(with::<Bar>())
.and(modified_since::<Baz>(tracks)),
|_, (bar. baz)| { ... } );
tracks = world.tracks_now(); // tracks is updated explicitly
}
Solves #10
We also can implement operators, so creating a filter would look like this:
let mut my_filter = !with::<Foo>() && (modified::<Bar>() || modified::<Baz>());
In this case one would need an instance of Tracks
for each modified
filter (implicit or explicit).
Which may or may not be a bad thing. But to keep this in mind while we deciding on the API
The problem with putting modification filtering into, well, filters, is that it would require to lock the version arrays immutably, which would prevent locking them mutably for mutable component query.
And if filter won't lock version arrays immutably, parallel query would be able to lock them mutably and cause a minor case of nasal demons.
Theoretically we can lock components for complex query at once and then distribute it to sub-queries and filters and allow trackers to look at versions of mutably borrowed component. But this can make code too complex and possibly slow.