Skip to content

Stepper Widget #25706

Description

@viridia

I'm considering adding a Stepper widget to bevy_ui_widgets. This is a widget mainly used in console games, but it can also be useful in examples if we do a feathers version. (For example, we could use it to control which gltf scene is displayed).

The stepper is simply a button with two arrows, increment and decrement. It's like a slider, but without the draggable thumb.

The stepper widget is unopinionated about how the value is displayed: it could be a number, or it could be a word. An example of the latter would be a game difficulty stepper, which displays easy / normal / veteran / hardcore / insanity. (I can even envision an animated version in which the old word slides out and the new word slides in.)

While the stepper does respond to mouse clicks, it's main purpose is to be driven by the keyboard, or if available, a gamepad. For example, the D-Pad inputs could be used to increment or decrement the stepper.

Open Question

Currently the Slider widget only supports f32. FeathersNumberInput takes a much more complex route, and supports i32, i64, f32, and f64 through the use of enum variants. That's fine for feathers, which isn't intended to be a lightweight solution.

The stepper needs to support at least i32 and f32; The "game difficulty" use case is an example of the former, and "dead zone adjust" is an example of the latter.

One solution would be to migrate the feathers NumberInputValue into bevy_ui_widgets. One concern I have about this is small platforms like GBA which might not have i64 support, in which case we'd be generating extra code that never gets used, bloating the binary size. NumberInputValue does a lot of its internal calculations in f64 (like .offset_by and .scale_by, and while this is fine for an editor, a console game in which there's a fixed memory budget may want something slimmer.

It would also mean that Stepper was inconsistent with Slider (unless we update Slider too).

A variant of this would be to replace NumberInputValue's enum implementation with a trait-based generic, so that apps could choose which number types they wanted to support.

Another approach would be to make Stepper generic; this would also require making its plugin and all of its observers generic too. Going too far down this road leads to a combinatorial explosion of observers. Like, do we really want Stepper<i64> to be part of DefaultPlugins?

This, too, is inconsistent with the way the other widgets behave.

A third option is to go with a "pure MVC" approach, and not have the stepper manage the value at all - that is, it only generates increment / decrement events and leaves the mutation and clamping of the value up to the app/model. However, this also has problems: first, it means that the app would also be responsible for updating the a11y information, which violates our "a11y is the path of least resistance" principle. Second, this also is inconsistent with how the other widgets work.

A final alternative is to have explicitly two different steppers: StepperI32 and StepperF32.

@alice-i-cecile @kfc35 @ickshonpe

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-UIGraphical user interfaces, styles, layouts, and widgetsC-FeatureA new feature, making something new possibleD-ComplexQuite challenging from either a design or technical perspective. Ask for help!S-Needs-DesignThis issue requires design work to think about how it would best be accomplished

    Type

    No type

    Projects

    • Status
      Needs SME Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions