-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Make state private and only accessible through getter for State resource #8009
Conversation
The field in there should really be private too 🤔 Should we make that change here, or in a new PR? |
I'll just make the change here because yeah, otherwise its a bit error prone for setting the next state. |
It looks like your PR is a breaking change, but you didn't provide a migration guide. Could you add some context on what users should update when this change get released in a new version of Bevy? |
Idk if this is a win. It forces the "double star deref" for the State resource: // before
fn system_1(state: Res<State<AppState>>) {
if state.0 == AppState::InGame {
info!("do thing");
}
}
// after
fn system(state: Res<State<AppState>>) {
if **state == AppState::InGame {
info!("do thing");
}
} |
I think it's important to make the field private, but I would be fine with a getter instead. |
Yeah I think a getter is preferable to double star |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
constructor is unfortunate, but I think at least there's docs there. I don't think we can remove it safely: it's way too hard to build compatible alternative state impls without it.
/// | ||
/// // Now that we are in `GameState::Pause`, `pause_system` will run | ||
/// app.run(&mut world); | ||
/// assert_eq!(world.resource::<Counter>().0, 0); | ||
/// ``` | ||
pub fn in_state<S: States>(state: S) -> impl FnMut(Res<State<S>>) -> bool + Clone { | ||
move |current_state: Res<State<S>>| current_state.0 == state | ||
move |current_state: Res<State<S>>| *current_state.get() == state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thought / proposal:
- Only implement
.get()
for states that implement copy/clone. Return by value. Then 9/10 times comparisons can becurrent_state.get() == state
- Also implement Deref::deref(), which returns the reference. Use double star (or manual deref() calls) in these cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
States
has a Clone
bound already, so I think it should just return by value 100% of the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I think implicitly cloning for getting the state would be great, I'd be more comfortable with impling on just Copy + Clone ones though.
If we want to simplify this a bit we could just impl PartialEq/Eq on State<S>
itself and it could just be
current_state == state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the impl on State quite a bit actually: that really feels like the idiomatic approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup way better!
Objective
State requires a kind of awkward
state.0
to get the current state and exposes the field directly to manipulation.Solution
Make it accessible through a getter method as well as privatize the field to make sure false assumptions about setting the state aren't made.
Migration Guide
State::get
instead of accessing the tuple field directly.