More Image Generator stuff (#59)

YOLO
This commit is contained in:
Danny McGee
2024-02-28 15:52:01 -05:00
committed by GitHub
parent 04ecc78059
commit f31cf35da1
18 changed files with 462 additions and 119 deletions
+15
View File
@@ -1,5 +1,7 @@
use bevy::prelude::*;
use crate::scene::{SceneElement, SceneSpawnerSystem, SceneState};
pub struct ChangeTrackingPlugin;
impl Plugin for ChangeTrackingPlugin {
@@ -8,6 +10,10 @@ impl Plugin for ChangeTrackingPlugin {
// Add more of these systems for each component that we want to track
app.add_systems(Update, send_change_events::<Transform>);
app.add_systems(
OnEnter(SceneState::Active),
track_scene_elements.after(SceneSpawnerSystem),
);
#[cfg(feature = "wasm")]
app.add_systems(
@@ -29,6 +35,15 @@ fn send_change_events<T: Component>(
}
}
fn track_scene_elements(
mut cmd: Commands,
q_scene_elements: Query<Entity, (With<Transform>, With<SceneElement>, Without<ChangeTracker>)>,
) {
for element in q_scene_elements.iter() {
cmd.entity(element).insert(ChangeTracker);
}
}
#[derive(Event, Deref)]
pub struct EntityChangedEvent(pub Entity);
+11 -5
View File
@@ -177,11 +177,17 @@ fn translate_dcc_camera_events(
else if (keyboard.just_released(KeyCode::AltLeft) && !keyboard.pressed(KeyCode::AltRight))
|| (keyboard.just_released(KeyCode::AltRight) && !keyboard.pressed(KeyCode::AltLeft))
{
input.send(InputAction(
Lifecycle::Stop,
CameraMotion::Orbit(Vec2::ZERO).into(),
));
input.send(InputAction(Lifecycle::Stop, CameraMotion::Zoom(0.).into()));
// Stop Camera Orbit
if mouse_buttons.pressed(MouseButton::Left) {
input.send(InputAction(
Lifecycle::Stop,
CameraMotion::Orbit(Vec2::ZERO).into(),
));
}
// Stop Camera Zoom
else if mouse_buttons.pressed(MouseButton::Right) {
input.send(InputAction(Lifecycle::Stop, CameraMotion::Zoom(0.).into()));
}
}
// Camera Rotation
else if mouse_buttons.pressed(MouseButton::Right) {
+1 -1
View File
@@ -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,
}
+1
View File
@@ -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};
+1 -1
View File
@@ -158,7 +158,7 @@ pub fn start(init: InitParams, mode: StudioMode, window_config: Option<Window>)
..default()
}),
CommonPlugins,
#[cfg(all(feature = "wasm", feature = "wasm_screenshot"))]
#[cfg(feature = "wasm")]
wasm::ScreenshotPlugin,
));
+3 -17
View File
@@ -23,7 +23,6 @@ use wasm_bindgen::prelude::wasm_bindgen;
use wgpu::{TextureDescriptor, TextureUsages};
use crate::{
anim::SkeletalJoint,
camera_controller::{CameraController, CameraControllerBundle},
change_tracking::{ChangeTracker, ChangeTrackingPlugin},
debug::DebugPoint,
@@ -63,13 +62,9 @@ impl Plugin for ScenePlugin {
.add_systems(
OnEnter(SceneState::Active),
(
(
tag_scene_elements,
frame_scene_in_view,
start_capture.run_if(is_headless),
),
apply_deferred,
track_scene_elements,
tag_scene_elements,
frame_scene_in_view,
start_capture.run_if(is_headless),
)
.chain()
.in_set(SceneSpawnerSystem),
@@ -524,15 +519,6 @@ fn start_capture(mut captures: Query<&mut ScreenCapture>) {
}
}
fn track_scene_elements(
mut commands: Commands,
scene_elements: Query<Entity, (With<Transform>, With<SkeletalJoint>)>,
) {
for element in scene_elements.iter() {
commands.entity(element).insert(ChangeTracker);
}
}
#[cfg(feature = "wasm")]
mod wasm {
use bevy::{prelude::*, window::PrimaryWindow};
-2
View File
@@ -5,12 +5,10 @@ use wasm_bindgen::prelude::wasm_bindgen;
mod conv;
mod init;
#[cfg(feature = "wasm_screenshot")]
mod screenshot;
mod util;
pub use conv::*;
#[cfg(feature = "wasm_screenshot")]
pub use screenshot::ScreenshotPlugin;
pub(crate) use util::*;
+59 -9
View File
@@ -10,9 +10,11 @@
//! to the frontend by converting the `Vec<u8>` to a [`js_sys::Uint8Array`]
use bevy::{prelude::*, render::view::screenshot::ScreenshotManager, window::PrimaryWindow};
use image::{codecs::png::PngEncoder, ColorType, ImageEncoder};
use image::{codecs::jpeg::JpegEncoder, 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()) {
@@ -112,8 +148,8 @@ fn take_screenshots(
};
let src_buffer = &img.as_raw()[..buffer_len];
let mut png_bytes = vec![];
if let Err(err) = PngEncoder::new(&mut png_bytes).write_image(
let mut jpg_bytes = vec![];
if let Err(err) = JpegEncoder::new_with_quality(&mut jpg_bytes, 70).write_image(
src_buffer,
img.width(),
img.height(),
@@ -124,7 +160,7 @@ fn take_screenshots(
}
SCREENSHOT.write_message(ScreenshotNative {
data: png_bytes,
data: jpg_bytes,
width: img.width() as usize,
height: img.height() as usize,
});
@@ -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(())
}
+1 -1
View File
@@ -17,7 +17,7 @@ impl Plugin for WorldGridPlugin {
}
#[derive(Component)]
struct WorldGridPlane;
pub struct WorldGridPlane;
#[derive(Asset, AsBindGroup, TypePath, Clone)]
struct ProceduralGridMaterial {}