Skip to main content

repame_ui/
lib.rs

1//! Shared game UI kit for the Repame template line: one action queue, one run
2//! flow, focus-navigable controls, one palette and one touch overlay.
3//!
4//! The kit exists because a measurement across the template-derived games found
5//! the same four things in every `ui/` module: eleven files define the same
6//! `mix`/`lighten`, eight to ten define the same `rect`/`chunky`/`label`
7//! shapes, thirteen files across nine games — four of them outside the template
8//! line — hand-roll the same `Sink`/`UiActions`/`drain_actions` action queue,
9//! and eight ship the same virtual stick. Nothing in those games can be
10//! navigated with a keyboard or a gamepad, because the overlay root asks for
11//! focus for itself and the buttons are boxes with a click handler.
12//!
13//! ## What the kit owns
14//!
15//! * [`queue`]: [`ActionQueue`]/[`Sink`] to push from a click closure and drain
16//!   from the sim, plus [`Intents`], the ordered edge view of a drained batch
17//!   that replaces a per-action boolean struct.
18//! * [`flow`]: [`Flow`], [`Transition`] and [`Suspension`] as
19//!   `repame_sim::state` state sets with enter/exit/transition schedules, plus
20//!   [`FlowState`], the playing / modal / transitional / suspended predicates
21//!   every game's `Phase` and `RunState` re-derive.
22//! * [`nav`]: focus traversal over the kit's own controls, built on repose's
23//!   `spatial_focus_next` and `FocusRequester`, with an entry point, focus
24//!   groups, boundary wrap and analog-stick repeat. This is the part the
25//!   template games are missing entirely.
26//! * [`palette`] and [`kit`]: palette tokens and the button/chip/panel/label
27//!   voices every game redraws, with the colour blending in one place.
28//! * [`touch`]: the virtual stick and tap buttons as kit controls, driving the
29//!   same queue and the same `apply_stick` curve as the pads.
30//!
31//! ## Adoption
32//!
33//! Nothing here has to be an ECS resource, and the crate deliberately carries no
34//! `bevy_ecs` dependency. A game keeps the wrapper resource it already declares
35//! and puts the kit's handle inside it:
36//!
37//! ```ignore
38//! #[derive(Resource, Clone, Default)]
39//! pub struct UiActions(pub repame_ui::Sink<UiAction>);
40//!
41//! #[derive(Resource, Default)]
42//! pub struct UiIntents(pub repame_ui::Intents<UiAction>);
43//! ```
44//!
45//! The frame then drains once, and hands the same sink to the kit:
46//!
47//! ```ignore
48//! let mut ui = self.sim.world.resource_mut::<UiActions>();
49//! let mut intents = self.sim.world.resource_mut::<UiIntents>();
50//! repame_ui::absorb(&ui.0, &mut intents.0);
51//!
52//! let kit = repame_ui::Kit::new(scale, repame_ui::Tokens::default(), ui.0.clone());
53//! kit.begin_frame();
54//! sim.add_chained_systems(update.run_if(repame_ui::flow::run_live));
55//! ```
56//!
57//! What stays in the game: its action enum, its panel list, its art colours and
58//! its font registration. What the kit removes: the copies of the queue, the
59//! flow predicates, the palette blending, the shapes, the stick, and the reason
60//! the menus could not be navigated.
61
62pub mod flow;
63pub mod kit;
64pub mod layout;
65pub mod nav;
66pub mod palette;
67pub mod queue;
68pub mod touch;
69
70pub use flow::{Flow, FlowState, InputOwner, Suspension, Transition, panel_owns_input, run_live};
71pub use kit::{Button, Kit, overlay_root};
72pub use layout::{
73    DESIGN, Scale, ScaleError, anchor_edges, anchor_rect, design_units, disc, ring,
74};
75pub use nav::{
76    GroupId, NavDir, NavDriver, NavEntry, NavMap, NavStep, StickNav, Wrap, chain_of, dpad_dirs,
77    pad_confirm,
78};
79pub use palette::{
80    FONT, ICON_BUTTON, ICON_GLYPH, MATERIAL_SYMBOLS, Tokens, chip, chunky, darken, hand_cut,
81    lighten, mix, state_colors,
82};
83pub use queue::{ActionQueue, Intents, Sink, UiAction, absorb};
84pub use touch::{STICK_RADIUS, TouchError, TouchPad};