| Crates.io | bevy_simple_screenshot |
| lib.rs | bevy_simple_screenshot |
| version | 0.1.2 |
| created_at | 2025-12-21 09:46:57.503679+00 |
| updated_at | 2025-12-21 10:11:47.154608+00 |
| description | A plug-and-play screenshot library for Bevy 0.17+ with ring-buffered capture and automatic saving |
| homepage | |
| repository | https://github.com/powergun/bevy_simple_screenshot |
| max_upload_size | |
| id | 1997776 |
| size | 299,467 |
A plug-and-play screenshot library for Bevy 0.17+ with ring-buffered capture and automatic saving.
Add the dependency:
[dependencies]
bevy_simple_screenshot = "0.1"
Add the plugin and capture screenshots from anywhere in your game code:
use bevy::prelude::*;
use bevy_simple_screenshot::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(ScreenshotBufferPlugin::new())
// Add your own game systems that use ScreenshotTrigger
.add_systems(Update, your_game_system)
.run();
}
// Example:
// Suppose you have a system that requires screenshot functionality.
// Here is the Update function of this system.
// You can integrate the screenshot functionality in other part of the system, too.
fn your_game_system(
trigger: ScreenshotTrigger,
// ... your other system parameters
) {
// Call screenshot!() whenever you want to capture
// For example, when a player dies:
screenshot!(&trigger, "player_died");
// Or with a category key for organization:
screenshot!(&trigger, "combat", "boss_defeated");
}
The ScreenshotTrigger system parameter can be added to any of your game systems. Call screenshot!() whenever you want to capture - it's non-blocking and won't affect your game's performance (see benchmarks).
Screenshots are saved to .screenshots/ by default.
Capture screenshots cropped to a specific entity (e.g., your game's hero during a special move). This is useful for:
use bevy::prelude::*;
use bevy_simple_screenshot::prelude::*;
// ─────────────────────────────────────────────────────────────
// Your existing game code (components, etc.)
// ─────────────────────────────────────────────────────────────
#[derive(Component)]
struct Hero;
#[derive(Component)]
struct SpecialMoveActive;
// ─────────────────────────────────────────────────────────────
// Add EntityScreenshotTrigger to your system parameters
// ─────────────────────────────────────────────────────────────
fn capture_hero_special_move(
trigger: EntityScreenshotTrigger, // <-- Use this instead of ScreenshotTrigger
hero_query: Query<Entity, (With<Hero>, Added<SpecialMoveActive>)>,
) {
for hero_entity in &hero_query {
// Capture with default settings (20px padding)
screenshot_entity!(&trigger, hero_entity, "hero", "special_move");
// Or with custom padding
let settings = EntityScreenshotSettings::default().with_padding(50);
screenshot_entity!(&trigger, hero_entity, "hero", "special_move", settings);
}
}
Sprite or Aabb)screenshot_entity! Variants// Entity only (default key "default", no description, 20px padding)
screenshot_entity!(&trigger, entity);
// With key
screenshot_entity!(&trigger, entity, "hero");
// With key and description
screenshot_entity!(&trigger, entity, "hero", "idle_animation");
// With key, description, and custom settings
let settings = EntityScreenshotSettings::default()
.with_padding(30)
.with_fallback_size(64, 64); // Used if entity has no Sprite/Aabb
screenshot_entity!(&trigger, entity, "hero", "idle_animation", settings);
Create screenshots.toml in your project root:
output_dir = ".screenshots"
buffer_capacity = 10
format = "png" # or "jpeg"
auto_save = true
[keys.combat]
buffer_capacity = 20
format = "jpeg"
jpeg_quality = "high" # max, high, medium, low
# Optional: burn-in text overlay on screenshots
# NOTE: font_path is REQUIRED when burn-in is enabled - see "Important Notes" below
[burn_in]
enabled = true
font_path = "assets/fonts/MyFont.ttf" # REQUIRED - must be a valid TTF from your project
show_frame = true # show frame number (default when enabled)
show_key = true # show screenshot key
show_description = true # show description text
position = "upper-right" # upper-left, upper-right, lower-left, lower-right
padding = 5 # pixels from edge
font_size = 18.0 # font size in pixels
Or configure programmatically:
ScreenshotBufferPlugin::with_config(
ScreenshotConfig::default()
.with_output_dir(".screenshots")
.with_buffer_capacity(5)
.with_format(ImageFormat::Jpeg)
.with_burn_in(
BurnInConfig::enabled()
.with_font("assets/fonts/MyFont.ttf") // required
.with_show_frame(true)
.with_show_key(true)
.with_position(BurnInPosition::UpperRight)
)
)
When burn-in text overlay is enabled, you must provide a valid TTF font file from your game project. The library does not bundle any fonts to keep dependencies minimal and give you full control over the appearance.
// This will PANIC if the font file doesn't exist or is invalid
BurnInConfig::enabled()
.with_font("assets/fonts/MyFont.ttf") // <-- Required!
If you enable burn-in without specifying a font path, or if the font file cannot be loaded, the application will panic with a clear error message. Make sure to:
The description parameter in screenshot!() and screenshot_entity!() is used in the output filename. To ensure valid filenames across all platforms, the description is automatically sanitized:
_), and hyphens (-) are preserved../) are neutralized// These descriptions will be sanitized:
screenshot!(&trigger, "combat", "boss defeated!"); // -> "boss_defeated"
screenshot!(&trigger, "debug", "frame 100 @ 60fps"); // -> "frame_100__60fps"
screenshot!(&trigger, "test", "../../etc/passwd"); // -> "etcpasswd"
This ensures screenshots are always saved with safe, predictable filenames regardless of the description content.
MIT