diff --git a/image-generator-demo/src/app/app.element.ts b/image-generator-demo/src/app/app.element.ts
index 606c239..33f1b9a 100644
--- a/image-generator-demo/src/app/app.element.ts
+++ b/image-generator-demo/src/app/app.element.ts
@@ -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 {
+ ${/*
+ 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
+
+ */
+ nothing}
${this.loading ? html`
diff --git a/studio/src/interaction/gizmos/common.rs b/studio/src/interaction/gizmos/common.rs
index b507901..6c5e46f 100644
--- a/studio/src/interaction/gizmos/common.rs
+++ b/studio/src/interaction/gizmos/common.rs
@@ -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,
}
diff --git a/studio/src/interaction/gizmos/mod.rs b/studio/src/interaction/gizmos/mod.rs
index 1a4c0fc..5ed674d 100644
--- a/studio/src/interaction/gizmos/mod.rs
+++ b/studio/src/interaction/gizmos/mod.rs
@@ -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};
diff --git a/studio/src/wasm/screenshot.rs b/studio/src/wasm/screenshot.rs
index b4141c4..78e99d8 100644
--- a/studio/src/wasm/screenshot.rs
+++ b/studio/src/wasm/screenshot.rs
@@ -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::();
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, With)>>,
+ mut ew: EventWriter,
+) {
+ 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,
q_window: Query>,
+ mut er: EventReader,
) -> 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>) -> Result<(), String> {
+fn send_screenshots(
+ q_window: Query<&Window, With>,
+ mut q_editor_visuals: Query<&mut Visibility, Or<(With, With)>>,
+) -> Result<(), String> {
let Some(screenshot) = SCREENSHOT.take_message() else {
return Ok(());
};
@@ -157,5 +196,16 @@ fn send_screenshots(q_window: Query<&Window, With>) -> 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(())
}
diff --git a/studio/src/world_grid.rs b/studio/src/world_grid.rs
index 8146db4..2c3256e 100644
--- a/studio/src/world_grid.rs
+++ b/studio/src/world_grid.rs
@@ -17,7 +17,7 @@ impl Plugin for WorldGridPlugin {
}
#[derive(Component)]
-struct WorldGridPlane;
+pub struct WorldGridPlane;
#[derive(Asset, AsBindGroup, TypePath, Clone)]
struct ProceduralGridMaterial {}