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

Add app.add_state(inital_state) convenience method #10731

Closed
honungsburk opened this issue Nov 25, 2023 · 4 comments · Fixed by #11043
Closed

Add app.add_state(inital_state) convenience method #10731

honungsburk opened this issue Nov 25, 2023 · 4 comments · Fixed by #11043
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible C-Usability A targeted quality-of-life change that makes Bevy easier to use

Comments

@honungsburk
Copy link
Contributor

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

I want to initialize a state to an arbitrary state, not just default.

Right now I am using app.add_state::<MyState>()

What solution would you like?

Add a convenience method app.add_state(MyState::MyArbitraryState) to App

What alternative(s) have you considered?

I read through the motivation for the new state system but it doesn't mention why only the default trait is used for initialization. This seems like a clear win to me so I would be surprised at any objections.

@honungsburk honungsburk added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Nov 25, 2023
@ItsDoot ItsDoot added A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use and removed S-Needs-Triage This issue needs to be labelled labels Nov 25, 2023
@honungsburk
Copy link
Contributor Author

I tried out this idea in my own game and it works great:

use bevy::ecs::schedule::common_conditions::run_once as run_once_condition;
use bevy::ecs::schedule::run_enter_schedule;
use bevy::prelude::*;

pub trait AppExtension {
    fn init_state<S: States>(&mut self, initial_state: S) -> &mut Self;
}

impl AppExtension for App {
    // Remove when [add_state is added](https://github.com/bevyengine/bevy/issues/10731)
    fn init_state<S: States>(&mut self, initial_state: S) -> &mut Self {
        self.insert_resource::<State<S>>(State::new(initial_state))
            .init_resource::<NextState<S>>()
            .add_systems(
                StateTransition,
                (
                    run_enter_schedule::<S>.run_if(run_once_condition()),
                    apply_state_transition::<S>,
                )
                    .chain(),
            );

        // The OnEnter, OnExit, and OnTransition schedules are lazily initialized
        // (i.e. when the first system is added to them), and World::try_run_schedule is used to fail
        // gracefully if they aren't present.
        self
    }
}

@honungsburk
Copy link
Contributor Author

If someone gives the greenlight I'll happily create PR 😄

@honungsburk honungsburk changed the title Add app.add_state(inital_state) connivance method Add app.add_state(inital_state) convenience method Nov 25, 2023
@roboteng
Copy link

I've done something a little different in my projects before. I'm not sure if its any better, but its another option.

pub struct BasePlugin(GameState);
impl Plugin for BasePlugin {
    fn build(&self, app: &mut App) {
        app.add_state::<GameState>();

        app.world
            .get_resource_mut::<NextState<GameState>>()
            .unwrap()
            .set(self.0);
   }
}

I just copied this from my project, but I don't think it'd be hard to change this to a method on App just like add_state

Is this any better/worse?

@doonv
Copy link
Contributor

doonv commented Nov 26, 2023

How about we split the add_state method into two methods: init_state<T: State>() and insert_state<T: State>(state: T). init_state would work like add_state, and insert_state will initialize the state to the state you pass in.

The names are inspired by the init_resource and insert_resource methods.

github-merge-queue bot pushed a commit that referenced this issue Dec 21, 2023
# Objective

Fix #10731.

## Solution

Rename `App::add_state<T>(&mut self)` to `init_state`, and add
`App::insert_state<T>(&mut self, state: T)`. I decided on these names
because they are more similar to `init_resource` and `insert_resource`.

I also removed the `States` trait's requirement for `Default`. Instead,
`init_state` requires `FromWorld`.

---

## Changelog

- Renamed `App::add_state` to `init_state`.
- Added `App::insert_state`.
- Removed the `States` trait's requirement for `Default`.

## Migration Guide

- Renamed `App::add_state` to `init_state`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible C-Usability A targeted quality-of-life change that makes Bevy easier to use
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants