#Pass state to Plugin

1 messages · Page 1 of 1 (latest)

frigid garden
#

Is it possible to make it so that I could pass a state to a Plugin constructor so that particular systems are added to particular states and stages?
I basically want to decouple the Plugin to make it more modular, say if someone wanted to use it like this without having access to the code?

Example (the type of a generic state is where i cant get it to work) :

impl MyPlugin {
  fn build_with_states(&self, app: &mut App, load_state: State, run_state: State) {
    app.
      .add_systems(OnEnter(load_state), my_load_system)
      .add_systems(Update, my_run_system.run_if(in_state(run_state));
  }
}
meager rivet
#

@frigid garden something like this: (didn't test it)

pub struct MyPlugin<S: States> {
  load_state: S,
  run_state: S,
}
impl<S: States> Plugin for MyPlugin<S> {
  fn build(&self, app: &mut App) {
    app.
      .add_systems(OnEnter(self.load_state), my_load_system)
      .add_systems(Update, my_run_system.run_if(in_state(self.run_state));
  }
}
```?
frigid garden
meager rivet
#

There's no associated type in my example, did you add some?

frigid garden
#

I changed State to States as that is a trait name. Im now thinking this was wrong

meager rivet
#

I meant to write States yeah, edited

#

If you have states like this:

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
enum GameState {
 #[default]
  Loading,
  Run,
  Other,
}```
You would use the plugin like this:
```rust
app.add_plugins(MyPlugin<GameState> {load_state: GameState::Loading, run_state: GameState::Run} )
#

That doesn't work?

frigid garden
#

Unfortunately not :/ The impl<S: States> returns compiler error "assoicated type bounds is unstable/are not allowed here"

#

Wait... For some reason I had impl MyPlugin<S: States>

#

moved it to impl

#

And it works! @meager rivet thank you very much, problem solved and taught me about type parameters!

meager rivet
#

@frigid garden To be completely honest I'm not sure why you need to put it on the impl x)
Happy to help, glad it works 💜

#

Also, another maybe more elegant solution would be to define another trait on GameState, something like

trait LoadRunStates: States {
  fn load() -> Self;
  fn run() -> Self;
}

impl LoadRunStates for GameState {
  fn load_state() -> Self {
    GameState::Load
  }
  fn run_state() -> Self {
    GameState::Run
  }
}

#[derive(Default)]
pub struct MyPlugin<S: LoadRunStates>(PhantomData<S>);

impl<S: LoadRunStates> Plugin for MyPlugin<S> {
  fn build(&self, app: &mut App) {
    app.
      .add_systems(OnEnter(self.load_state()), my_load_system)
      .add_systems(Update, my_run_system.run_if(in_state(self.run_state()));
  }
}```
Then call it like this:
```rust
app.add_plugins(MyPlugin::<GameState>::default())

@frigid garden

#

but maybe overkill depending of your usage