Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OneOf Query Type #376

Open
Moulberry opened this issue Sep 18, 2024 · 1 comment
Open

OneOf Query Type #376

Moulberry opened this issue Sep 18, 2024 · 1 comment

Comments

@Moulberry
Copy link

Moulberry commented Sep 18, 2024

Hello, hope you are doing well.

This issue is about the discussion of a potential new query type OneOf.
I am willing to create the pull request for this feature if it's desired, I'm creating an issue first to gauge whether or not this would be suitable for hecs.

Motivation

I can't find a built-in way to query one of a set of types, the closest is the Or query type but this has certain limitations as discussed below. The motivation for OneOf would be to implement different behaviour when the player interacts with some entity, i.e. clicking an Enemy/Item/Corpse/etc.

Example

The query type OneOf3<A, B, C> will match any entity that contains either A, B or C, but only up to the first match.

You can then use code similar on the result:

match item {
    One(a) => {},
    Two(b) => {},
    Three(c) => {},
}

edit: An alternative implementation would be to implement #[derive(Query)] for enum types as well, allowing users to define their own enum queries like:

#[derive(hecs::Query)]
pub enum AttackTarget {
    Enemy(Enemy),
    Item(Item),
}

I think this approach might be superior.

Alternatives that already exist (to my knowledge)

Layering Ors, like Or<A, Or<B, C>>
Problems:

  1. Lots of boilerplate to set up the query with the repeated or and brackets
  2. Not very easy to concisely match on the result
  3. The query engine will continue checking for B and C even if A is present, i.e. it doesn't stop when you've already matched

Using a lot of options, like (Option<A>, Option<B>, Option<C>)
Problems:

  1. Code using the query result will end up having a lot of if-else chains to check every option
  2. 3 Nones is a valid result, meaning you're going to end up iterating over every entity unless you constrain it with a more complex query eg. With<(Option<A>, Option<B>, Option<C>), Or<A, Or<B, C>>

Some other workaround, like inserting an Attack component when an entity is clicked
Problems:

  1. Doesn't work for every use-case
  2. Performance penalty due to changing archetype
  3. More architecturally complex than just performing the logic you want directly

I apologize in advance if there's built-in a way to do OneOf. Once again, I am willing to contribute this feature if it's within the scope of hecs. Thank you for your time

@VinTarZ
Copy link

VinTarZ commented Sep 26, 2024

Permanently add

enum ClickTarget {
Enemy,
Item,
Button,
}

Component and query for (Entity, ClickTarget), then match click_target and get component you want using entity_id?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants