3

I'm following a rust tutorial that uses the Specs ECS, and I'm trying to implement it using the legion ECS instead. I love legion and everything went smoothly until I faced a problem.

I'm not sure how to formulate my question. What I am trying to do is create a system that iterates on every entity that has e.g. ComponentA and ComponentB, but that also checks if the entity has ComponentC and do something special if it is the case.

I can do it like so using Specs (example code):

// Uses Specs
pub struct SystemA {}

impl<'a> System<'a> for SystemA {
    type SystemData = ( Entities<'a>,
                        WriteStorage<'a, ComponentA>, 
                        ReadStorage<'a, ComponentB>,
                        ReadStorage<'a, ComponentC>);

    fn run(&mut self, data : Self::SystemData) {
        let (entities, mut compA, compB, compC) = data;

        // Finding all entities with ComponentA and ComponentB
        for (ent, compA, compB) in (&entities, &mut compA, &compB).join() {
            // Do stuff with compA and compB

            // Check if Entity also has ComponentC
            let c : Option<&ComponentC> = compC.get(ent);

            if let Some(c) = c {
                // Do something special with entity if it also has ComponentC
            }
        }
    }
}

I have a hard time translating this to using legion (currently using the latest 0.4.0 version). I don't know how to get the other components that the current entity has. Here is the code I have:

#[system(for_each)]
pub fn systemA(entity: &Entity, compA: &mut compA, compB: &mut ComponentB) {
    // Do stuff with compA and compB

    // How do I check if entity has compC here?

}

The entity in the system above only contains its ID. How do I access the list of components this entity has without the World? Or is there a way to access the World in a system in legion? Or any other way to achieve the same as the Specs version?

Thanks!

dvidbruhm
  • 33
  • 3

1 Answers1

2

you can use Option<...> to optional component.

#[system(for_each)]
pub fn systemA(entity: &Entity, compA: &mut compA, compB: &mut ComponentB, compC: Option<&ComponentC>) {
    ...
    if let Some(compC) = compC {
        // this entity has compC
        ...
jongguk.jo
  • 96
  • 3
  • Do you know if there is a way to query for another type of component in a system? For example, in the same example system find other entities that have ComponentD (but not any of the ComponentA, B, or C) since we don't have access to the world in the system? – dvidbruhm Mar 10 '21 at 21:46
  • 1
    I don't know if this is possible using #[system(for_each)]. But, you can use SubWorld in #[system] #[system] #[read_component(A)] #[read_component(B)] #[write_component(C)] fn iter_ab(sworld: &mut SubWorld) { // access entity A, Optional B let mut query = <(Entity, &A, Option<&B>)>::query(); for (e, a, b) in query.iter(sworld) { } // access entity C let mut query_other = <(Entity, &mut C)>::query(); for (e, c) in query_other.iter_mut(sworld) { } } – jongguk.jo Mar 11 '21 at 03:08