bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Add PreviousState Resource accessible in OnEnter

Open Br3nnabee opened this issue 2 months ago • 1 comments

Objective

  • Adds a PreviousState resource to track the last active state, making it accessible during state transitions (e.g., in OnEnter schedules).
  • Fixes #21882.

Solution

  • Added a new PreviousState<S: States> resource.
  • Updated internal_apply_state_transition to manage the lifecycle of PreviousState:
    • Standard Transition: Updates PreviousState to the exited state.
    • Creation: If a state is initialized (transition from None), any existing PreviousState is removed.
    • Removal: If a state is removed, PreviousState is updated to preserve the last known state.
  • Registered PreviousState in AppExtStates for reflection and general access.
  • Ensured PreviousState is available for OnEnter systems by using ApplyDeferred ordering in setup_state_transitions_in_world.

Testing

  • Added a temporary local unit test previous_state_is_tracked_correctly which verifies that PreviousState is created, updated, and persisted correctly across multiple state transitions.
  • The implementation covered scenarios including standard transitions, state initialization (where no previous state exists), and state removal.
  • Don't think I handled all edge cases, would appreciate a second look.

Showcase

You can now access the state you just transitioned from directly in your systems!

fn handle_state_refresh<S: FreelyMutableState>(
    prev_state: Option<Res<PreviousState<S>>>, 
    mut next_state: ResMut<NextState<S>>
) {
    if let Some(prev) = prev_state {
        println!("We just came from {:?}", prev.0);
        // Example: revert to previous state
        next_state.set(prev.0.clone());
    }
}

app.add_systems(OnEnter(GameState::Refresh), handle_state_refresh::<GameState>);

This is my first contribution, would highly appreciate some feedback!

Br3nnabee avatar Dec 01 '25 09:12 Br3nnabee

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

github-actions[bot] avatar Dec 01 '25 09:12 github-actions[bot]

Alright, so I've removed the ApplyDeferred section now. There's a merge conflict due to #21792, but as far as I see it's a quick fix. Should I be the one to handle that, or would you prefer to?

Br3nnabee avatar Dec 15 '25 20:12 Br3nnabee

Yes please; handling merge conflicts is done by authors around here :)

alice-i-cecile avatar Dec 16 '25 05:12 alice-i-cecile