Coder Social home page Coder Social logo

Optimal event handling about hecs HOT 9 OPEN

ralith avatar ralith commented on June 30, 2024
Optimal event handling

from hecs.

Comments (9)

AngelOfSol avatar AngelOfSol commented on June 30, 2024

I wonder if an API like the following makes sense:

impl World {
  fn handle_events<Event, F: FnMut(Q::Item), Q: Query, I: Iterator<Item=(Entity, Event)>>(&mut self, iterator: I, f: F);
  fn handle_events2<Event, F1: FnMut(Q1::Item), Q1: Query, F2: FnMut(Q2::Item), Q2: Query,I: Iterator<Item=(Entity, Event)>>(&mut self, iterator: I, f: F1, f2: F2);
 ...
}

You could probably do something with a Trait parameterized on tuples of queries?

trait EventHandler<Q, F, E> {
  fn handle_events(&mut self, iter: impl Iterator<Item=(Entity, E)>, f: F);
}

impl<Q: Query, U: Query, E> EventHandler<(Q, U), (FnMut(Event, Q::Item), FnMut(Event, U::Item)), E> for World {
  fn handle_events(&mut self, iter: impl Iterator<Item=(Entity, Event)>, f: F) { 
    // do stuff here...
  }
}

Really rough spitball here, but I think my point is there? (Not sure what Fn trait to use).

I'm just trying to come at it from the user side and figure out what would be nice to use.

from hecs.

AngelOfSol avatar AngelOfSol commented on June 30, 2024

Another idea I had that doesn't really necessarily optimize the problem on the backend, but might look ok for the user was something like this:

impl World {
  fn try_on_entity<T, Q: Query, F: FnOnce(Q) -> T>(&mut self, entity: Entity: f: F) -> Option<T> { ... }
}

from hecs.

Ralith avatar Ralith commented on June 30, 2024

I wonder if an API like the following makes sense:

I think that could work, but the ergonomics of passing a bunch of queries in type parameters and then matching them up with a giant tuple of functions seem unpleasant enough to not be worth it.

Another idea

How does that differ from the existing World::query_one?

from hecs.

AngelOfSol avatar AngelOfSol commented on June 30, 2024

I think that could work, but the ergonomics of passing a bunch of queries in type parameters and then matching them up with a giant tuple of functions seem unpleasant enough to not be worth it.

I was hoping typeck could figure out the types for everything to make it so the client didn't have to figure it out themselves, or at least only have to annotate the function type parameters.

How does that differ from the existing World::query_one?

Same as above in regards to typeck. It's main use would be to reduce boilerplate by providing an Option::map like interface on the entity. At least that's what I was trying to get at.

from hecs.

Ralith avatar Ralith commented on June 30, 2024

Type inference can't work backwards from an associated type.

from hecs.

AngelOfSol avatar AngelOfSol commented on June 30, 2024

That makes sense. I was hoping there was some way to decrease boilerplate a little bit. Either way I'm interested to see where this goes from the user-side, so I'll be watching.

from hecs.

Ralith avatar Ralith commented on June 30, 2024

#154 is a closely related problem, where instead of cacheing a list of queries satisfied by an archetype, we want to cache a list of archetypes that satisfy a query.

from hecs.

adamreichold avatar adamreichold commented on June 30, 2024

I wonder if this use case isn't actually solved well by using the View types? I think the initial example could be rewritten as

let mut query_a = world.query::<A>();
let mut view_a = query_a.view();

let mut query_b = world.query::<B>();
let mut view_b = query_b.view();

for (entity, event) in events.drain(..) {
    if let Some(components) = view_a.get_mut(entity) {
        handle_a(event, components);
    }
    if let Some(components) = view_b.get_mut(entity) {
        handle_b(event, components);
    }
    // ...
}

which should be efficient?

from hecs.

Ralith avatar Ralith commented on June 30, 2024

The idea here was to find a way to replace all the if let Some branching with indirection that could determine, based on the entity's archetype, exactly which of a collection of handlers should run without any dynamic filtering. I think the approach you've sketched would be a good enough substitute, since it all the nontrivial work out of the loop, but it's not generally applicable because it adds the constraint that A and B must be able to overlap without violating aliasing rules.

from hecs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.