cu_bevymon
cu_bevymon is a Copper monitor frontend that renders the shared TUI monitor UI inside Bevy using a soft_ratatui backend uploaded into a Bevy texture.
By default, the Bevy windowed monitor uses bundled JetBrains Mono Nerd Font Mono TTF files so the Bevy rendering is much closer to the console monitor than the stock mono_8x13 backend.
It provides:
CuBevyMon: aCuMonitorimplementation backed by the shared monitor modelCuBevyMonPlugin: a Bevy plugin that draws the monitor into a Bevy textureCuBevyMonFontOptions: font sizing for the bundled windowed TUI rendererCuBevyMonTextureandCuBevyMonPanel: the Bevy-backed monitor render surfaceCuBevyMonSurfaceNode,CuBevyMonFocus, andCuBevyMonFocusBorder: helpers for click-to-focus split layoutsspawn_split_layout(...): the shared left/right split shell used by the current examplesCuBevyMonViewportSurface: a camera helper for syncing a 3D viewport to a Bevy UI panel
Design intent:
- reuse the same Ratatui rendering as
cu_consolemon - reuse the same shared
LOGpane, including Copper live logs and optionalstderrcapture - integrate into existing Bevy sims like
cu_rp_balancebotandcu_flight_controller - keep the rendering/backend split clean enough for later browser / wasm work
Recommended app structure:
- keep Copper config backend-agnostic by pointing it at an app-local monitor alias
- pick the actual monitor implementation in Rust with
cfg(feature = "...") - let the Bevy host app decide layout and focus ownership
The existing flight-controller pattern is the recommended one:
// copperconfig.ron
(
id: "monitor",
type: "tasks::monitor::AppMonitor",
)
// src/tasks/monitor.rs
pub type AppMonitor = CuBevyMon;
pub type AppMonitor = CuConsoleMon;
pub type AppMonitor = CuLogMon;
That keeps RON stable while the build target decides whether the app gets a Bevy panel, a terminal TUI, or a lighter real-target monitor.
Standard split-view pattern:
- Keep your sim scene camera app-owned.
- Recommended: render that camera to an offscreen
RenderTarget::Image. - Add
CuBevyMonPlugin::new(model)to the Bevy app. - Create a dedicated
Camera2dfor the split-shell UI. - Call
spawn_split_layout(...)with the scene camera entity and the monitor texture handle. - Add app-specific overlays like loading cards, help panels, or OSD widgets as children of the returned
sim_panel. - Gate sim-control systems on
Res<CuBevyMonFocus>whilecu_bevymonroutes monitor events tocu_tuimon.
Shared shell sketch:
let layout = spawn_split_layout;
commands.entity.with_children;
The cu_bevymon_demo, cu_rp_balancebot, and cu_flight_controller examples all use that shared split shell now. The main app-specific choice is how the left-side scene camera is produced.
Render strategy guidance:
- Use the offscreen
RenderTarget::Image+ViewportNodepath when the sim already has its own UI overlays, picking, or camera behavior. This is the standardized path in the current examples. CuBevyMonViewportSurfacestill exists for simpler panel-clipped window cameras, but it is now the lower-level escape hatch, not the primary documented pattern.
Input model:
- window focus stays with Bevy
- logical panel focus is tracked by
CuBevyMonFocus cu_bevymontranslates Bevy events into backend-neutralcu_tuimon::MonitorUiEvent- monitor bindings live in
cu_tuimon, not in the Bevy adapter
Font behavior:
- the default bundled font set is JetBrains Mono Nerd Font Mono Light / SemiBold / LightItalic
- the default bundled font size is 24 px
- panel resize changes how many rows and columns fit; it does not change the glyph size
- use
CuBevyMonPlugin::with_font_size(...)orCuBevyMonPlugin::with_font_options(...)to tune the Bevy-side font size - use
CuBevyMonPlugin::with_font_options(...)for full control - the bundled font bytes live under
assets/fonts/ - this improves glyph coverage for the powerline tabs, symbols, arrows, and box drawing used by
cu_tuimon - OpenType feature selection like Kitty's
+zeroflag is not currently exposed through this backend