Description
Overview
Add screenshot export functionality to BERT, allowing users to capture and save system diagrams. This feature enables users to export their visual models for documentation, presentations, and sharing. Perfect first issue for learning BERT's Bevy + Leptos + Tauri architecture.
User Value
- Export visual diagrams for documentation and presentations
- Share models with collaborators
- Save snapshots of work in progress
Scope
- Target: Desktop builds only (Tauri/Bevy). Web/wasm screenshot support will be a follow-up issue.
- Screenshot capture should be gated behind
#[cfg(not(target_arch = "wasm32"))].
- Minimum viable implementation uses Bevy's screenshot API and saves to the current working directory with a timestamped filename.
Important Caveat (Past Implementation)
- The older
bert-old implementation frequently exported blank images. The root cause was not confirmed; suspected causes include capturing before the frame finished rendering or targeting the wrong render surface.
- Contributors are encouraged to investigate alternative causes (e.g., stage timing/scheduling, incorrect window or camera target, MSAA/alpha/DPI issues) and propose the most reliable fix.
- To avoid blank screenshots, ensure capture happens after rendering has completed for the current frame. Use Bevy’s
Screenshot API correctly and, if necessary, defer capture to the next frame using events or a small state machine.
Prior Attempt (Reference Only)
A previous screenshot attempt exists in our older codebase. It was unreliable (often blank). Use it only to study patterns and API usage; do not assume correctness and do not copy directly.
Key Technical Patterns to Adapt
1. Bevy Screenshot Capture
// Pattern from previous implementation - adapt for current architecture
use bevy::{
prelude::*,
render::view::screenshot::{Screenshot, ScreenshotFinished},
window::PrimaryWindow,
};
pub fn take_screenshot(
main_window: Query<Entity, With<PrimaryWindow>>,
mut commands: Commands,
) {
// Called when UI button is clicked
let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S");
let path = PathBuf::from(format!("bert_screenshot_{}.png", timestamp));
commands.insert_resource(ScreenshotFile(path));
let screenshot_entity = commands.spawn(Screenshot::window(main_window.single())).id();
info!("Taking screenshot, saving to entity {:?}", screenshot_entity);
}
}
2. File Save Pattern
// Handle screenshot completion and file saving
pub fn save_screenshot_to_disk(
mut screenshot_events: EventReader<ScreenshotFinished>,
mut commands: Commands,
screenshot_file: Option<Res<ScreenshotFile>>,
) {
if let Some(screenshot_file) = screenshot_file {
for event in screenshot_events.read() {
if let Some(image_data) = &event.image_data {
let path = &screenshot_file.0;
match std::fs::write(path, image_data) {
Ok(_) => info!("Screenshot saved to {}", path.display()),
Err(e) => error!("Failed to save screenshot: {}", e),
}
commands.remove_resource::<ScreenshotFile>();
}
}
}
}
3. File Naming Convention
// Timestamp-based naming for unique files
let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S");
let filename = format!("bert_screenshot_{}.png", timestamp);
Implementation Tasks
Core Functionality (Bevy)
User Interface (Leptos)
Dependencies
Architecture Overview
BERT uses three main frameworks:
- Bevy: Game engine handling rendering and systems (add screenshot logic here)
- Leptos: Web framework for UI components (add screenshot button here)
- Tauri: Desktop app wrapper (handles file dialogs)
Key Files
- Systems:
/src/bevy_app/systems/ - Add screenshot.rs here
- UI Components:
/src/leptos_app/components/ - Add controls here
- System Registration:
/src/bevy_app/mod.rs - Register new systems
- Notifications:
/src/bevy_app/systems/toast_handler.rs - Available for future feedback
Acceptance Criteria
Must Have
Nice to Have
Getting Started
1. Explore Current Architecture
# Look at existing systems for patterns
ls src/bevy_app/systems/
cat src/bevy_app/systems/mod.rs
# Check existing UI components
ls src/leptos_app/components/
cat src/leptos_app/components/controls_menu.rs
2. Study Reference Implementation
- Review the linked files for overall approach
- Note the patterns but adapt for current architecture
- Pay attention to system registration and event handling
3. Start Small
- Begin with desktop-only keyboard shortcut + file save (timestamped PNG)
- Gate the implementation with
#[cfg(not(target_arch = "wasm32"))]
- Add UI controls (button and Save As dialog) in a follow-up PR
Technical Notes
Key Differences from Reference
- Current version has evolved significantly since reference implementation
- Use current Leptos component patterns, not old ones
- Integrate with existing toast system rather than creating new notifications (
SaveSuccessEvent)
- Register systems in
src/bevy_app/mod.rs (.add_systems(Update, ...)) and export from src/bevy_app/systems/mod.rs
Testing
- Test keyboard shortcuts on different platforms (Mac/Windows/Linux)
- Verify file naming doesn't conflict with existing files
- Test error cases (permission issues, disk full, etc.)
- Confirm screenshots capture the full system diagram correctly on desktop
- Validate non-blank capture: create a model with distinct colors and labels, then compare a few known pixel samples or visually confirm contents. If blank, defer the capture by one frame (PostUpdate) or after
TransformPropagate and retry.
Questions?
Feel free to ask questions in this issue or reach out in our Discord! This is designed to be a learning-friendly first contribution.
Additional Context for Implementation
Current File Structure Reference
src/bevy_app/systems/
├── mod.rs # System registration patterns here
├── setup.rs # App initialization patterns
├── camera.rs # Camera/view handling
├── toast_handler.rs # Notification system (use this!)
└── ui/ # UI-related systems
├── mod.rs
├── color.rs
├── drag.rs
└── zoom.rs
Leptos Component Integration
src/leptos_app/components/
├── mod.rs
├── controls_menu.rs # Likely place for screenshot button
├── button.rs # Button component patterns
└── toast.rs # Toast notification patterns
Description
Overview
Add screenshot export functionality to BERT, allowing users to capture and save system diagrams. This feature enables users to export their visual models for documentation, presentations, and sharing. Perfect first issue for learning BERT's Bevy + Leptos + Tauri architecture.
User Value
Scope
#[cfg(not(target_arch = "wasm32"))].Important Caveat (Past Implementation)
bert-oldimplementation frequently exported blank images. The root cause was not confirmed; suspected causes include capturing before the frame finished rendering or targeting the wrong render surface.ScreenshotAPI correctly and, if necessary, defer capture to the next frame using events or a small state machine.Prior Attempt (Reference Only)
A previous screenshot attempt exists in our older codebase. It was unreliable (often blank). Use it only to study patterns and API usage; do not assume correctness and do not copy directly.
Key Technical Patterns to Adapt
1. Bevy Screenshot Capture
2. File Save Pattern
3. File Naming Convention
Implementation Tasks
Core Functionality (Bevy)
src/bevy_app/systems/screenshot.rswith atake_screenshotandsave_screenshot_to_disksystem (desktop only via#[cfg(not(target_arch = "wasm32"))]).ScreenshotFileresource for path handling and cleanup after save.ScreenshotFinishedevents for saving to disk.src/bevy_app/systems/mod.rs.src/bevy_app/mod.rsunderUpdate(co-locate near other input-driven systems).SaveSuccessEventwith a brief message on success to drive the existing toast UI.take_screenshotto schedule a capture on the next frame (e.g., via a separateRequestScreenshotevent and a follow-up system running inPostUpdate).User Interface (Leptos)
src/leptos_app/mod.rs) and/or insrc/leptos_app/components/controls_menu.rs.ScreenshotRequest).Toastcomponent.Dependencies
chronotoCargo.tomlfor timestamped filenames (desktop only path).Architecture Overview
BERT uses three main frameworks:
Key Files
/src/bevy_app/systems/- Add screenshot.rs here/src/leptos_app/components/- Add controls here/src/bevy_app/mod.rs- Register new systems/src/bevy_app/systems/toast_handler.rs- Available for future feedbackAcceptance Criteria
Must Have
SaveSuccessEvent→Toastfor success/failure feedbackNice to Have
Getting Started
1. Explore Current Architecture
2. Study Reference Implementation
3. Start Small
#[cfg(not(target_arch = "wasm32"))]Technical Notes
Key Differences from Reference
SaveSuccessEvent)src/bevy_app/mod.rs(.add_systems(Update, ...)) and export fromsrc/bevy_app/systems/mod.rsTesting
TransformPropagateand retry.Questions?
Feel free to ask questions in this issue or reach out in our Discord! This is designed to be a learning-friendly first contribution.
Additional Context for Implementation
Current File Structure Reference
Leptos Component Integration