Debugging window/viewport scaling issues

This commit is contained in:
Danny McGee
2024-04-04 15:47:16 -04:00
parent 691ff92d17
commit 1efa6a95a1
4 changed files with 79 additions and 42 deletions
+2 -1
View File
@@ -64,7 +64,7 @@ export class StudioElement extends LitElement {
#onResize(): void {
const { width, height } = this.getBoundingClientRect();
studio.resize(new ViewportSize(width, height));
studio.resize(new ViewportSize(width, height), window.devicePixelRatio);
this.dispatchEvent(new CustomEvent("viewport-resized", {
detail: { width, height },
@@ -83,6 +83,7 @@ export class StudioElement extends LitElement {
canvasSelector: `#${this._canvasProvider?.canvasId}`,
canvasAlt: "Storyteller Studio",
viewportSize: new ViewportSize(width, height),
scaleFactor: window.devicePixelRatio,
};
try {
+21 -2
View File
@@ -10,9 +10,13 @@ use bevy::{
math::vec2,
pbr::ShadowFilteringMethod,
prelude::*,
render::{camera::RenderTarget, primitives::Aabb},
render::{
camera::{RenderTarget, Viewport},
primitives::Aabb,
},
scene::InstanceId,
utils::HashSet,
window::PrimaryWindow,
};
#[cfg(feature = "wasm")]
use serde_repr::{Deserialize_repr, Serialize_repr};
@@ -310,11 +314,19 @@ pub struct SceneData {
#[derive(Component)]
pub struct SceneRoot;
fn initialize(mut cmd: Commands) {
fn initialize(mut cmd: Commands, q_window: Query<&Window, With<PrimaryWindow>>) {
// Camera, graphics settings
let focus = Vec3::ZERO;
let camera_xform = Transform::from_xyz(-2.5, 4.5, 5.0).looking_at(focus, Vec3::Y);
let window = q_window.single();
info!(
"Window: ({:.2} x {:.2}) [{:.2}]",
window.width(),
window.height(),
window.scale_factor(),
);
cmd.spawn((
Name::new("Main Camera"),
MainCamera,
@@ -325,6 +337,13 @@ fn initialize(mut cmd: Commands) {
tonemapping: Tonemapping::BlenderFilmic,
camera: Camera {
hdr: true,
viewport: Some(Viewport {
physical_size: UVec2::new(
(window.width() * window.scale_factor()) as u32,
(window.height() * window.scale_factor()) as u32,
),
..default()
}),
..default()
},
..default()
+22 -28
View File
@@ -1,6 +1,5 @@
use core::fmt;
use bevy::window::WindowResolution;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
@@ -21,21 +20,9 @@ impl ViewportSize {
impl Default for ViewportSize {
fn default() -> Self {
WindowResolution::default().into()
}
}
impl From<ViewportSize> for WindowResolution {
fn from(value: ViewportSize) -> Self {
Self::new(value.width, value.height)
}
}
impl From<WindowResolution> for ViewportSize {
fn from(value: WindowResolution) -> Self {
Self {
width: value.width(),
height: value.height(),
width: 1280.,
height: 720.,
}
}
}
@@ -58,11 +45,11 @@ pub mod wasm {
use super::ViewportSize;
static RESIZE_BUF: WasmMessageBuffer<ViewportSize> = WasmMessageBuffer::new();
static RESIZE_BUF: WasmMessageBuffer<(ViewportSize, f32)> = WasmMessageBuffer::new();
#[wasm_bindgen]
pub fn resize(viewport_size: ViewportSize) {
RESIZE_BUF.write_message(viewport_size);
pub fn resize(viewport_size: ViewportSize, scale_factor: f32) {
RESIZE_BUF.write_message((viewport_size, scale_factor));
}
pub struct ViewportPlugin;
@@ -77,30 +64,37 @@ pub mod wasm {
}
#[derive(Event, Clone, Copy)]
struct ViewportResizeEvent(ViewportSize);
struct ViewportResizeEvent {
pub size: ViewportSize,
pub scale_factor: f32,
}
fn sync_window_to_viewport(
mut events: EventReader<ViewportResizeEvent>,
mut window: Query<&mut Window>,
mut q_camera: Query<&mut Camera, With<MainCamera>>,
) {
if let Some(event) = events.read().last() {
let ViewportSize { width, height } = event.0;
window.single_mut().resolution.set(width, height);
if let Some(ViewportResizeEvent { size, scale_factor }) = events.read().last() {
let ViewportSize { width, height } = size;
window.single_mut().resolution.set(*width, *height);
q_camera.single_mut().viewport = Some(Viewport {
physical_size: UVec2::new(width as u32, height as u32),
physical_size: UVec2::new(
(width * scale_factor) as u32,
(height * scale_factor) as u32,
),
..Default::default()
});
info!("Viewport size: ({:.2}, {:.2})", width, height);
info!("Viewport size: ({width:.2}, {height:.2}) [{scale_factor:.2}]");
}
}
fn dispatch_resize_events(mut events: EventWriter<ViewportResizeEvent>) {
if let Some(resize) = RESIZE_BUF.take_message() {
events.send(ViewportResizeEvent(resize));
if let Some((size, scale_factor)) = RESIZE_BUF.take_message() {
events.send(ViewportResizeEvent { size, scale_factor });
info!(
"Dispatch Viewport size: ({:.2}, {:.2})",
resize.width, resize.height
"Dispatch Viewport size: ({:.2}, {:.2}) [{scale_factor:.2}]",
size.width, size.height,
);
}
}
+34 -11
View File
@@ -1,4 +1,4 @@
use bevy::prelude::*;
use bevy::{prelude::*, window::WindowResolution};
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
@@ -13,6 +13,7 @@ export interface InitOptions {
canvasSelector: string;
canvasAlt: string;
viewportSize: ViewportSize;
scaleFactor: number;
}
export function initFromLibrary(objectId: string, options: InitOptions): void;
@@ -22,26 +23,28 @@ export function initFromSceneImport(scenePath: string, options: InitOptions): vo
export function initFromStorytellerScene(scenePath: string, options: InitOptions): void;
"#;
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct WasmInitOptions {
#[serde(rename = "skyboxId")]
skybox_id: Option<String>,
mode: StudioMode,
#[serde(rename = "canvasSelector")]
canvas_selector: String,
#[serde(rename = "canvasAlt")]
canvas_alt: String,
#[serde(rename = "viewportSize")]
viewport_size: ViewportSize,
scale_factor: f32,
}
#[wasm_bindgen(skip_typescript, js_name = initFromLibrary)]
pub fn init_from_library(object_id: String, options: JsValue) -> Result<(), JsValue> {
let options = serde_wasm_bindgen::from_value::<WasmInitOptions>(options)?;
info!("wasm::init_from_library: {object_id} {options:#?}");
let skybox_id = options
.skybox_id
.expect("`skyboxId` is required for `initFromLibrary`");
let ViewportSize { width, height } = options.viewport_size;
crate::start(
InitParams::FromAsset {
asset: InitAsset::LibraryObject(object_id),
@@ -49,7 +52,8 @@ pub fn init_from_library(object_id: String, options: JsValue) -> Result<(), JsVa
},
options.mode,
Some(Window {
resolution: options.viewport_size.into(),
resolution: WindowResolution::new(width, height)
.with_scale_factor_override(options.scale_factor),
title: options.canvas_alt,
canvas: Some(options.canvas_selector),
..default()
@@ -63,10 +67,14 @@ pub fn init_from_library(object_id: String, options: JsValue) -> Result<(), JsVa
#[wasm_bindgen(skip_typescript, js_name = initFromBvh)]
pub fn init_from_bvh(anim_path: String, options: JsValue) -> Result<(), JsValue> {
let options = serde_wasm_bindgen::from_value::<WasmInitOptions>(options)?;
info!("wasm::init_from_bvh: {anim_path} {options:#?}");
let skybox_id = options
.skybox_id
.expect("`skyboxId` is required for `initFromBvh`");
let ViewportSize { width, height } = options.viewport_size;
crate::start(
InitParams::FromAsset {
asset: InitAsset::BvhAnim(anim_path),
@@ -74,7 +82,8 @@ pub fn init_from_bvh(anim_path: String, options: JsValue) -> Result<(), JsValue>
},
options.mode,
Some(Window {
resolution: options.viewport_size.into(),
resolution: WindowResolution::new(width, height)
.with_scale_factor_override(options.scale_factor),
title: options.canvas_alt,
canvas: Some(options.canvas_selector),
..default()
@@ -88,10 +97,14 @@ pub fn init_from_bvh(anim_path: String, options: JsValue) -> Result<(), JsValue>
#[wasm_bindgen(skip_typescript, js_name = initFromMixamo)]
pub fn init_from_mixamo(anim_path: String, options: JsValue) -> Result<(), JsValue> {
let options = serde_wasm_bindgen::from_value::<WasmInitOptions>(options)?;
info!("wasm::init_from_mixamo: {anim_path} {options:#?}");
let skybox_id = options
.skybox_id
.expect("`skyboxId` is required for `initFromMixamo`");
let ViewportSize { width, height } = options.viewport_size;
crate::start(
InitParams::FromAsset {
asset: InitAsset::MixamoAnim(anim_path),
@@ -99,7 +112,8 @@ pub fn init_from_mixamo(anim_path: String, options: JsValue) -> Result<(), JsVal
},
options.mode,
Some(Window {
resolution: options.viewport_size.into(),
resolution: WindowResolution::new(width, height)
.with_scale_factor_override(options.scale_factor),
title: options.canvas_alt,
canvas: Some(options.canvas_selector),
..default()
@@ -113,10 +127,14 @@ pub fn init_from_mixamo(anim_path: String, options: JsValue) -> Result<(), JsVal
#[wasm_bindgen(skip_typescript, js_name = initFromSceneImport)]
pub fn init_from_scene_import(scene_path: String, options: JsValue) -> Result<(), JsValue> {
let options = serde_wasm_bindgen::from_value::<WasmInitOptions>(options)?;
info!("wasm::init_from_scene_import: {scene_path} {options:#?}");
let skybox_id = options
.skybox_id
.expect("`skyboxId` is required for `initFromSceneImport`");
let ViewportSize { width, height } = options.viewport_size;
crate::start(
InitParams::FromAsset {
asset: InitAsset::ImportedScene(scene_path),
@@ -124,7 +142,8 @@ pub fn init_from_scene_import(scene_path: String, options: JsValue) -> Result<()
},
options.mode,
Some(Window {
resolution: options.viewport_size.into(),
resolution: WindowResolution::new(width, height)
.with_scale_factor_override(options.scale_factor),
title: options.canvas_alt,
canvas: Some(options.canvas_selector),
..default()
@@ -138,12 +157,16 @@ pub fn init_from_scene_import(scene_path: String, options: JsValue) -> Result<()
#[wasm_bindgen(skip_typescript, js_name = initFromStorytellerScene)]
pub fn init_from_storyteller_scene(scene_path: String, options: JsValue) -> Result<(), JsValue> {
let options = serde_wasm_bindgen::from_value::<WasmInitOptions>(options)?;
info!("wasm::init_from_storyteller_scene: {scene_path} {options:#?}");
let ViewportSize { width, height } = options.viewport_size;
crate::start(
InitParams::FromScene(scene_path),
options.mode,
Some(Window {
resolution: options.viewport_size.into(),
resolution: WindowResolution::new(width, height)
.with_scale_factor_override(options.scale_factor),
title: options.canvas_alt,
canvas: Some(options.canvas_selector),
..default()