Filters
Sometimes, a dynamic on-the-fly filter is needed to process only a subset of Entities; this enables us to quickly adjust our ECS logic to do different subsets of work without requiring a growing amount of queries to be defined.
To do so, we simply clone our lightweight Stream<> view and change some fields.
Creating a Stream Filter
Each Stream<> has two filter fields, Subset and Exclude, which are used to filter the Entities that are processed by the Stream.
Can I interest you in a Grape-Colored Example
There's an appetizer on this topic! Check out Thanos for an, ahem, "practical" example of using filters.
You can specify them using the with syntax to create a new Stream with the filters applied. This gives you a new view that applies the filter for all its operations. It doesn't mutate the original Stream, nor the underlying Query.
var stream = world.Stream<Position, Velocity>();
var filteredStream = stream with
{
Subset = [ Component.PlainComponent<Alive>() ], // collection initializer
Exclude = [ Link.With(TheOneRing) ] // (the collections are immutable sets)
};Subset Clause
This works much like an additional Has<> clause.
includes onlyEntities that have the given component or relation. MultipleHasstatements can be compared to a logicalA AND B AND C.
Exclude Clause
This works much like an additional Not<> clause.
excludesany Entities that have the given component. MultipleNotstatements can be compared to a logicalNOT (A OR B OR C), aka.(NOT A) AND (NOT B) AND (NOT C).
Combining Filters
Subset and Exclude are ImmutableSets, so they can be combined to build or merge some filters together when specifying a new Stream using the with keyword.
var stream = world.Stream<Position, Velocity>();
var filteredStream = stream with
{
Subset = otherFilter.Subset
.Add(Component.PlainComponent<Alive>())
.Remove(Component.PlainComponent<Dead>()),
Exclude = otherFilter.Subset.Union([Component.AnyRelation<Owes>()]),
};Future Features
The Component utility class to create the necessary filter expressions is likely to have its API reviewed and tightened, to make the syntax more readable and easier to use. It might get unified into a Mask-like system as used internally to power QueryBuilders.