mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
Exclude editor visuals from screen captures
This commit is contained in:
@@ -22,7 +22,6 @@ import "./app.element.scss"
|
||||
@customElement("app-root")
|
||||
export class AppElement extends LitElement {
|
||||
@state() imageCaptureUrl?: string;
|
||||
@state() realtimeCapture = true;
|
||||
|
||||
@state() hierarchyWidth = 256;
|
||||
@state() resizing = false;
|
||||
@@ -52,12 +51,9 @@ export class AppElement extends LitElement {
|
||||
}
|
||||
|
||||
@on("entity-changes")
|
||||
@debounce(1000 / 24)
|
||||
onStudioChanges(): void {
|
||||
if (this.realtimeCapture) {
|
||||
this.requestScreenshot_realtime();
|
||||
} else {
|
||||
this.requestScreenshot_delayed();
|
||||
}
|
||||
studio.requestScreenshot();
|
||||
}
|
||||
|
||||
@on("viewport-resized")
|
||||
@@ -67,16 +63,6 @@ export class AppElement extends LitElement {
|
||||
studio.requestScreenshot();
|
||||
}
|
||||
|
||||
@debounce(1000 / 24, { maxWait: 1000 / 5 })
|
||||
requestScreenshot_realtime() {
|
||||
studio.requestScreenshot();
|
||||
}
|
||||
|
||||
@debounce(1000 / 24)
|
||||
requestScreenshot_delayed() {
|
||||
studio.requestScreenshot();
|
||||
}
|
||||
|
||||
@on("screenshot-ready")
|
||||
onScreenshotReady({ detail: screenshot }: ScreenshotReadyEvent) {
|
||||
const prevUrl = this.imageCaptureUrl;
|
||||
@@ -101,11 +87,6 @@ export class AppElement extends LitElement {
|
||||
this.hierarchyWidth = Math.max(Math.min(updated, 512), 128);
|
||||
}
|
||||
|
||||
toggleRealtimeCapture(event: InputEvent): void {
|
||||
const { checked } = event.target as HTMLInputElement;
|
||||
this.realtimeCapture = checked;
|
||||
}
|
||||
|
||||
refreshSeed(): void {
|
||||
this.seed = randomSeed();
|
||||
}
|
||||
@@ -184,6 +165,11 @@ export class AppElement extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${/*
|
||||
FIXME: Real-time capture is not really feasible until we can come up
|
||||
with a more elegant way to exclude the world grid, gizmos, etc.
|
||||
from the captured image
|
||||
|
||||
<div class="config v-start h-end">
|
||||
<label class="config-checkbox">
|
||||
<input
|
||||
@@ -194,6 +180,8 @@ export class AppElement extends LitElement {
|
||||
Realtime Capture
|
||||
</label>
|
||||
</div>
|
||||
*/
|
||||
nothing}
|
||||
|
||||
${this.loading ? html`
|
||||
<!-- TODO: Animated spinner or something -- talk to our designers -->
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::interaction::TransformSpace;
|
||||
use super::material::GizmoMaterial;
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
pub(super) struct TransformGizmo {
|
||||
pub struct TransformGizmo {
|
||||
pub(super) target: Entity,
|
||||
pub(super) transform_space: TransformSpace,
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use self::{
|
||||
rotation::{spawn_rotation_gizmo, update_ss_ring_rotation},
|
||||
translation::spawn_translation_gizmo,
|
||||
};
|
||||
pub use common::TransformGizmo;
|
||||
|
||||
use super::{Selection, TransformMode, TransformType};
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ use bevy::{prelude::*, render::view::screenshot::ScreenshotManager, window::Prim
|
||||
use image::{codecs::png::PngEncoder, ColorType, ImageEncoder};
|
||||
use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
|
||||
|
||||
use crate::{interaction::gizmos::TransformGizmo, world_grid::WorldGridPlane};
|
||||
|
||||
use super::{AsJsValue, StaticBuffer, WasmMessageBuffer};
|
||||
|
||||
static SCREENSHOT_REQUEST: WasmMessageBuffer<()> = WasmMessageBuffer::new();
|
||||
@@ -22,16 +24,25 @@ pub struct ScreenshotPlugin;
|
||||
|
||||
impl Plugin for ScreenshotPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_event::<ScreenshotRequestedEvent>();
|
||||
app.add_systems(
|
||||
Update,
|
||||
(
|
||||
take_screenshots.map(bevy::utils::error),
|
||||
(
|
||||
prepare_screenshot,
|
||||
apply_deferred,
|
||||
take_screenshots.map(bevy::utils::error),
|
||||
)
|
||||
.chain(),
|
||||
send_screenshots.map(bevy::utils::error),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Event)]
|
||||
pub struct ScreenshotRequestedEvent;
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Clone)]
|
||||
pub struct Screenshot {
|
||||
@@ -74,21 +85,46 @@ impl AsJsValue for Screenshot {
|
||||
|
||||
#[wasm_bindgen(js_name = requestScreenshot)]
|
||||
pub fn request_screenshot() {
|
||||
info!("[wasm::screenshot] Screenshot request received");
|
||||
SCREENSHOT_REQUEST.write_message(());
|
||||
}
|
||||
|
||||
fn prepare_screenshot(
|
||||
mut q_editor_visuals: Query<&mut Visibility, Or<(With<WorldGridPlane>, With<TransformGizmo>)>>,
|
||||
mut ew: EventWriter<ScreenshotRequestedEvent>,
|
||||
) {
|
||||
if SCREENSHOT_REQUEST.take_message().is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
info!(
|
||||
"[wasm::screenshot] Hiding {} editor visuals",
|
||||
q_editor_visuals.iter().count()
|
||||
);
|
||||
|
||||
for mut visibility in q_editor_visuals.iter_mut() {
|
||||
*visibility = Visibility::Hidden;
|
||||
}
|
||||
|
||||
ew.send(ScreenshotRequestedEvent);
|
||||
}
|
||||
|
||||
fn take_screenshots(
|
||||
mut r_screenshot_mgr: ResMut<ScreenshotManager>,
|
||||
q_window: Query<Entity, With<PrimaryWindow>>,
|
||||
mut er: EventReader<ScreenshotRequestedEvent>,
|
||||
) -> Result<(), String> {
|
||||
if SCREENSHOT_REQUEST.take_message().is_none() {
|
||||
if er.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Ok(window_ent) = q_window.get_single() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
er.clear();
|
||||
|
||||
info!("[wasm::screenshot] Queueing screenshot request");
|
||||
|
||||
r_screenshot_mgr
|
||||
.take_screenshot(window_ent, |img| {
|
||||
let img = match img.try_into_dynamic().map(|img| img.to_rgb8()) {
|
||||
@@ -146,7 +182,10 @@ declare global {
|
||||
}
|
||||
"#;
|
||||
|
||||
fn send_screenshots(q_window: Query<&Window, With<PrimaryWindow>>) -> Result<(), String> {
|
||||
fn send_screenshots(
|
||||
q_window: Query<&Window, With<PrimaryWindow>>,
|
||||
mut q_editor_visuals: Query<&mut Visibility, Or<(With<WorldGridPlane>, With<TransformGizmo>)>>,
|
||||
) -> Result<(), String> {
|
||||
let Some(screenshot) = SCREENSHOT.take_message() else {
|
||||
return Ok(());
|
||||
};
|
||||
@@ -157,5 +196,16 @@ fn send_screenshots(q_window: Query<&Window, With<PrimaryWindow>>) -> Result<(),
|
||||
|
||||
let screenshot = Screenshot::from(screenshot);
|
||||
|
||||
super::dispatch_to_js(window, "screenshot-ready", &screenshot)
|
||||
super::dispatch_to_js(window, "screenshot-ready", &screenshot)?;
|
||||
|
||||
info!(
|
||||
"[wasm::screenshot] Revealing {} previously hidden editor visuals",
|
||||
q_editor_visuals.iter().count()
|
||||
);
|
||||
|
||||
for mut visibility in q_editor_visuals.iter_mut() {
|
||||
*visibility = Visibility::Inherited;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ impl Plugin for WorldGridPlugin {
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct WorldGridPlane;
|
||||
pub struct WorldGridPlane;
|
||||
|
||||
#[derive(Asset, AsBindGroup, TypePath, Clone)]
|
||||
struct ProceduralGridMaterial {}
|
||||
|
||||
Reference in New Issue
Block a user