Overview
saddle-pane is a debug/tweaking panel library for Bevy built entirely on Bevy's native UI system. It provides two APIs: a recommended Derive API and a lower-level Builder API.
Core Data Flow
Resource (game state)
↕ bidirectional sync (binding.rs)
PaneStore (central value store)
↕ sync systems (sync.rs)
Control Components (per-row ECS entities)
↕ interaction/display systems (controls/*.rs)
Bevy UI Nodes (visual elements)Resource (game state)
↕ bidirectional sync (binding.rs)
PaneStore (central value store)
↕ sync systems (sync.rs)
Control Components (per-row ECS entities)
↕ interaction/display systems (controls/*.rs)
Bevy UI Nodes (visual elements)Key Components
PanePlugin (plugin.rs)
Registers all core systems in three ordered system sets:
PaneSystems::Interaction— widget events → control components (PostUpdate)PaneSystems::Sync— control components → PaneStore + events (PostUpdate)PaneSystems::Display— control components → UI updates (PostUpdate)
PaneStore (store.rs)
Central value store keyed by (pane_title, field_label). Stores PaneValue enum variants (Float, Bool, String, Color, Int, Custom). Tracks initial values for reset and a dirty set for external updates.
Derive Binding (binding.rs)
The PaneDerive trait (generated by the proc macro) provides typed read_field()/write_field() methods. RegisterPaneExt::register_pane::<T>() spawns the UI and adds bidirectional sync systems with feedback-loop prevention via DeriveSyncFlag.
Control Registry (registry.rs)
Plugin controls register via PaneControlRegistry. Each plugin provides:
id— control type identifier (e.g.,"interval","vector2")spawnfn — builds UI hierarchybuildfn — registers systemsdefault_valuefn — initial value factory
Built-in Controls (controls/)
| Control | File | Trigger |
|---|---|---|
| Slider | slider.rs | #[pane(slider)] or builder .slider() |
| Toggle | toggle.rs | bool field or .toggle() |
| Number | number.rs | numeric field or .number() |
| Text | text.rs | String field or .text() |
| Select | select.rs | #[pane(select)] or .select() |
| Color | color.rs + color_picker.rs | #[pane(color)] or .color() |
| Monitor | monitor.rs | #[pane(monitor)] |
| Button | button.rs | .button() |
| Separator | separator.rs | .separator() |
Theme System (theme.rs)
PaneTheme resource with dark/light presets. PaneThemeOverride component for per-pane overrides. CSS variables defined in style/tokens.css.
Crate Structure
saddle-pane/ Main library (PanePlugin, derive, builder, controls)
├── crates/derive/ Proc macro (#[derive(Pane)])
├── crates/interval/ Range slider plugin
├── crates/vector2/ 2D joystick plugin
├── crates/button-grid/ Button grid plugin
├── crates/radio-grid/ Radio/checkbox grid plugin
├── crates/bezier/ Bezier curve editor plugin
└── crates/file/ File browser pluginsaddle-pane/ Main library (PanePlugin, derive, builder, controls)
├── crates/derive/ Proc macro (#[derive(Pane)])
├── crates/interval/ Range slider plugin
├── crates/vector2/ 2D joystick plugin
├── crates/button-grid/ Button grid plugin
├── crates/radio-grid/ Radio/checkbox grid plugin
├── crates/bezier/ Bezier curve editor plugin
└── crates/file/ File browser pluginStyling
All styling is CSS-based via bevy_flair. Stylesheets are embedded at compile time using embedded_asset!. Design tokens in style/tokens.css define colors, spacing, and typography.