Skip to content

OneOf WorldQuery via a Xor filter, alternative to Enum filtering #9649

@ItsDoot

Description

@ItsDoot

What problem does this solve or what need does it fill?

A somewhat common question in the Bevy Discord involves being able to filter by a component's enum variant:

enum MyComponent {
    Foo,
    Bar,
}

fn my_system(query: Query<Entity, With<MyComponent::Foo>>) {
    // ...
}

This doesn't work because Rust doesn't represent enum variants as full types. A common alternative is to use marker components instead, but currently you lose out on the mutual exclusivity that standard enums provide.

I propose to add a new OneOf<(A, B, C, ...)> WorldQuery similar to AnyOf, but backed by a Xor filter rather than Or.

What solution would you like?

Similar to how AnyOf works:

// equivalent to `Query<(Option<&A>, Option<&B>, Option<&mut C>), Or<(With<A>, With<B>, With<C>)>>
fn my_system(query: Query<AnyOf<(&A, &B, &mut C)>>) {}

This new OneOf should work like:

// equivalent to `Query<(Option<&A>, Option<&B>, Option<&mut C>), Xor<(With<A>, With<B>, With<C>)>>
fn my_system(query: Query<OneOf<(&A, &B, &mut C)>>) {}

Could also look at having an enum return type per arity, like

enum OneOf2<A, B> {
    A(A),
    B(B),
}

enum OneOf3<A, B, C> {
    A(A),
    B(B),
    C(C),
}

// etc ...

This might be best paired with Archetype Invariants.

What alternative(s) have you considered?

Use enums and deal with its inherent issues manually.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-FeatureA new feature, making something new possibleD-ModestA "normal" level of difficulty; suitable for simple features or challenging fixesS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions