pane_ui 0.1.0

A RON-driven, hot-reloadable wgpu UI library with spring animations and consistent scaling
Documentation
//! # `pane_ui`
//!
//! A RON-driven, hot-reloadable UI library for [wgpu](https://github.com/gfx-rs/wgpu).
//!
//! Define your entire UI in a `.ron` file. No layout code, no style code, no wiring code.
//! Edit the file while your app runs and the UI updates instantly — menus, styles, and
//! shaders alike. Your game loop stays untouched.
//!
//! ---
//!
//! ## Modes
//!
//! Choose the integration that fits your architecture:
//!
//! | Mode | Owns window? | GPU required? | Use when |
//! |------|:---:|:---:|---|
//! | [`run`] | ✅ | ✅ | Pane IS the app |
//! | [`overlay`] / [`PaneOverlay`] | ❌ | ✅ | Compositing onto your renderer |
//! | [`headless`] / [`PaneHeadless`] | ❌ | ❌ | Tests, servers, CI |
//!
//! ### Standalone
//!
//! Pane owns the window and event loop entirely.
//!
//! ```no_run
//! // Simplest — one line, no callbacks
//! pane::run("assets/menu.ron");
//!
//! // With callback — handle actions and call write/toast each frame
//! pane::run_with("assets/menu.ron", |ui, action| {
//!     if let pane::PaneAction::Custom(ref id) = action {
//!         if id == "save" { ui.push_toast("Saved!", 2.0, 0.0, -400.0, 300.0, 60.0); }
//!     }
//! });
//! ```
//!
//! ### Overlay
//!
//! Composites onto your existing wgpu renderer. You keep your device, queue, and loop.
//!
//! ```ignore
//! // Startup — pass Some(gilrs) to share your gamepad context, or None to auto-create one
//! let mut ui = pane::overlay("assets/hud.ron", &device, &queue, format, None);
//!
//! // In your event loop
//! ui.handle_event(&event, window_width, window_height);
//!
//! // In your render pass — call after your own draw commands
//! for action in ui.draw(&mut encoder, &view, pw, ph) {
//!     match action {
//!         pane::PaneAction::Custom(tag)         => println!("button: {tag}"),
//!         pane::PaneAction::Slider(id, val)     => println!("{id} = {val:.2}"),
//!         pane::PaneAction::Toggle(id, checked) => println!("{id} = {checked}"),
//!         pane::PaneAction::Quit                => std::process::exit(0),
//!         _                                     => {}
//!     }
//! }
//! ```
//!
//! ### Headless
//!
//! No GPU, no window. Useful for testing UI logic in CI or driving a server-side state machine.
//!
//! ```no_run
//! let mut menu = pane::headless("assets/menu.ron");
//! menu.press("play_button");
//! let actions = menu.update(1.0 / 60.0);
//! ```
//!
//! ---
//!
//! ## Coordinate System
//!
//! Pane uses a **centered, resolution-independent** coordinate system:
//!
//! - `(0.0, 0.0)` is always the center of the screen
//! - The screen height is always `1080` units regardless of actual resolution
//! - Width scales proportionally — widescreen just adds space on the sides
//! - Positive Y is downward
//!
//! A button at `x: -170.0, y: 0.0` is centered vertically on every screen.
//! You never write resolution-specific layout.
//!
//! ---
//!
//! ## Widgets
//!
//! 15 built-in widget types, all defined in RON:
//!
//! `Button` · `Toggle` · `Slider` · `TextBox` · `Dropdown` · `RadioGroup` ·
//! `ScrollList` · `ScrollPane` · `Bar` · `Popout` · `Label` · `Divider` ·
//! `Image` · `ProgressBar` · `Tabs`
//!
//! Plus `Actor` — a non-interactive animated element that follows the cursor
//! or moves to programmatic targets.
//!
//! ---
//!
//! ## Actions
//!
//! [`PaneOverlay::draw`] and [`PaneHeadless::update`] return a vector of [`PaneAction`]
//! each frame. Match on these to drive your application:
//!
//! ```no_run
//! # use pane::PaneAction;
//! # let actions: Vec<PaneAction> = vec![];
//! for action in actions {
//!     match action {
//!         PaneAction::Custom(tag)              => { /* button pressed */ }
//!         PaneAction::Slider(id, value)        => { /* slider moved */ }
//!         PaneAction::Toggle(id, checked)      => { /* toggle flipped */ }
//!         PaneAction::Dropdown(id, idx, label) => { /* selection changed */ }
//!         PaneAction::Radio(id, idx, label)    => { /* selection changed */ }
//!         PaneAction::TextChanged(id, text)    => { /* keystroke */ }
//!         PaneAction::TextSubmitted(id, text)  => { /* enter pressed */ }
//!         PaneAction::SwitchRoot(name)         => { /* root changed */ }
//!         PaneAction::Quit                     => { std::process::exit(0); }
//!     }
//! }
//! ```
//!
//! ---
//!
//! ## Runtime API
//!
//! Read or write any widget's value from code at any time. Useful for syncing UI
//! to app state on startup, or driving a progress bar mid-game.
//!
//! ```ignore
//! # use pane::WriteValue;
//! # let mut ui: pane::PaneOverlay = todo!();
//! // Read — returns the UiItem definition + current visual state
//! if let Some((pane::api::UiItem::Slider(s), _)) = ui.read("volume") {
//!     println!("volume = {}", s.value);
//! }
//!
//! // Write — silently sets value without firing PaneActions
//! ui.write("volume",  &WriteValue::Slider(0.8));
//! ui.write("mute",    &WriteValue::Toggle(true));
//! ui.write("name",    &WriteValue::Text("Player 1".into()));
//! ui.write("quality", &WriteValue::Selected(2));
//!
//! // Toast notification (also triggerable directly from RON via on_press: Toast(...))
//! ui.push_toast("Settings saved", 2.0, 0.0, -400.0, 300.0, 60.0);
//! ```
//!
//! ---
//!
//! ## Hot Reload
//!
//! Set `hot_reload: true` in your root `.ron` file. While your app runs:
//!
//! - Save a menu `.ron` → layout and behaviour update instantly
//! - Save a style `.ron` → visual design updates instantly
//! - Save a `.wgsl` shader → shader recompiles and updates instantly
//!
//! No restart. No recompile. Just save.
//!
//! Requires the `dev` feature for runtime style loading:
//!
//! ```toml
//! pane_ui = { version = "0.1", features = ["dev"] }
//! ```
//!
//! ---
//!
//! ## Controller Support
//!
//! All widgets support gamepad navigation with no extra configuration:
//!
//! - **D-pad / left stick** — moves focus to the nearest widget in that direction
//! - **South (A / Cross)** — confirms; activates focused widget
//! - **East (B / Circle)** — cancels; closes popout panels
//! - **Sliders** — left/right adjusts value continuously
//! - **Scroll lists & panes** — focus scrolls to keep the active item visible
//! - **Popouts** — confirm opens, up/down navigates inside, cancel closes
//!
//! Pass your existing `gilrs::Gilrs` to share it with your game:
//!
//! ```no_run
//! # let (device, queue, format) = todo!();
//! # let gilrs: gilrs::Gilrs = todo!();
//! // Share your game's gilrs context
//! let ui = pane::overlay("assets/hud.ron", &device, &queue, format, Some(gilrs));
//!
//! // Or let pane_ui manage its own
//! let ui = pane::overlay("assets/hud.ron", &device, &queue, format, None);
//! ```
//!
//! ---
//!
//! ## Custom Styles & Shaders
//!
//! Drop `.ron` style files in your style directory and `.wgsl` shaders in your shader
//! directory. Reference them by filename (without extension). Users and modders can
//! reskin your entire UI without touching your code.
//!
//! ```ron
//! (
//!     shader_dirs: ["shaders"],
//!     style_dirs:  ["styles"],
//!     roots: [
//!         (
//!             name: "main_menu",
//!             buttons: [
//!                 (
//!                     id: "my_btn",
//!                     style: "my_custom_style",  // loads styles/my_custom_style.ron
//!                     on_press: Custom("clicked"),
//!                     // ...
//!                 ),
//!             ],
//!         ),
//!     ],
//! )
//! ```
//!
//! 6 built-in styles are always available: `frosted_glass` · `retro` · `plain` ·
//! `glass_pill` · `emboss` · `sharp_outline`
//!
//! ---
//!
//! ## Debugging
//!
//! Enable debug logging to print every internal message to stdout:
//!
//! ```no_run
//! # let mut ui: pane::PaneOverlay = todo!();
//! // Overlay or headless
//! ui.set_debug(true);
//! ```
//!
//! ```text
//! // Standalone — set the environment variable before running
//! PANE_DEBUG=1 cargo run
//! ```

// ── Public modules ────────────────────────────────────────────────────────────

pub mod api;
pub mod build;
pub mod draw;
pub mod input;
pub mod loader;

// ── Internal modules ──────────────────────────────────────────────────────────

pub(crate) mod anim;
pub(crate) mod builder;
pub(crate) mod items;
pub(crate) mod keyboard;
pub(crate) mod logic;
pub(crate) mod order;
pub(crate) mod query;
pub(crate) mod shader_reg;
pub(crate) mod styles;
pub(crate) mod styles_reg;
pub(crate) mod textures;
pub(crate) mod threader;
pub(crate) mod widgets;

// ── Re-exports ────────────────────────────────────────────────────────────────

/// Re-exported for convenience — pass a `gilrs::Gilrs` to [`overlay`] to share
/// your existing gamepad context with `pane_ui`.
pub use gilrs;

pub use api::{
    PaneAction, PaneHeadless, PaneOverlay, StandaloneHandle, WriteValue, headless, overlay, run,
    run_with,
};