From c1f92cc2d610fe8c23cb402780ab4ec3a2ef9dbd Mon Sep 17 00:00:00 2001 From: Danny McGee Date: Fri, 29 Sep 2023 20:36:23 -0400 Subject: [PATCH] Spawn Bevy canvas at full viewport size --- studio-frontend/src/app/app.element.scss | 416 ----------------------- studio-frontend/src/app/app.element.ts | 8 +- studio-frontend/src/styles.scss | 11 +- studio/src/lib.rs | 19 +- studio/src/main.rs | 2 +- studio/src/viewport.rs | 37 ++ 6 files changed, 64 insertions(+), 429 deletions(-) create mode 100644 studio/src/viewport.rs diff --git a/studio-frontend/src/app/app.element.scss b/studio-frontend/src/app/app.element.scss index e033890..e69de29 100644 --- a/studio-frontend/src/app/app.element.scss +++ b/studio-frontend/src/app/app.element.scss @@ -1,416 +0,0 @@ -/* - * Remove template code below - */ - html { - -webkit-text-size-adjust: 100%; - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, - 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, - 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', - 'Noto Color Emoji'; - line-height: 1.5; - tab-size: 4; - scroll-behavior: smooth; - } - body { - font-family: inherit; - line-height: inherit; - margin: 0; - } - h1, - h2, - p, - pre { - margin: 0; - } - *, - ::before, - ::after { - box-sizing: border-box; - border-width: 0; - border-style: solid; - border-color: currentColor; - } - h1, - h2 { - font-size: inherit; - font-weight: inherit; - } - a { - color: inherit; - text-decoration: inherit; - } - pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - 'Liberation Mono', 'Courier New', monospace; - } - svg { - display: block; - vertical-align: middle; - } - - svg { - shape-rendering: auto; - text-rendering: optimizeLegibility; - } - pre { - background-color: rgba(55, 65, 81, 1); - border-radius: 0.25rem; - color: rgba(229, 231, 235, 1); - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - 'Liberation Mono', 'Courier New', monospace; - overflow: scroll; - padding: 0.5rem 0.75rem; - } - - .shadow { - box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1), - 0 4px 6px -2px rgba(0, 0, 0, 0.05); - } - .rounded { - border-radius: 1.5rem; - } - - .wrapper { - width: 100%; - } - .container { - margin-left: auto; - margin-right: auto; - max-width: 768px; - padding-bottom: 3rem; - padding-left: 1rem; - padding-right: 1rem; - color: rgba(55, 65, 81, 1); - width: 100%; - } - #welcome { - margin-top: 2.5rem; - } - #welcome h1 { - font-size: 3rem; - font-weight: 500; - letter-spacing: -0.025em; - line-height: 1; - } - #welcome span { - display: block; - font-size: 1.875rem; - font-weight: 300; - line-height: 2.25rem; - margin-bottom: 0.5rem; - } - #hero { - align-items: center; - background-color: hsla(214, 62%, 21%, 1); - border: none; - box-sizing: border-box; - color: rgba(55, 65, 81, 1); - display: grid; - grid-template-columns: 1fr; - margin-top: 3.5rem; - } - #hero .text-container { - color: rgba(255, 255, 255, 1); - padding: 3rem 2rem; - } - #hero .text-container h2 { - font-size: 1.5rem; - line-height: 2rem; - position: relative; - } - #hero .text-container h2 svg { - color: hsla(162, 47%, 50%, 1); - height: 2rem; - left: -0.25rem; - position: absolute; - top: 0; - width: 2rem; - } - #hero .text-container h2 span { - margin-left: 2.5rem; - } - #hero .text-container a { - background-color: rgba(255, 255, 255, 1); - border-radius: 0.75rem; - color: rgba(55, 65, 81, 1); - display: inline-block; - margin-top: 1.5rem; - padding: 1rem 2rem; - text-decoration: inherit; - } - #hero .logo-container { - display: none; - justify-content: center; - padding-left: 2rem; - padding-right: 2rem; - } - #hero .logo-container svg { - color: rgba(255, 255, 255, 1); - width: 66.666667%; - } - - #middle-content { - align-items: flex-start; - display: grid; - gap: 4rem; - grid-template-columns: 1fr; - margin-top: 3.5rem; - } - - #learning-materials { - padding: 2.5rem 2rem; - } - #learning-materials h2 { - font-weight: 500; - font-size: 1.25rem; - letter-spacing: -0.025em; - line-height: 1.75rem; - padding-left: 1rem; - padding-right: 1rem; - } - .list-item-link { - align-items: center; - border-radius: 0.75rem; - display: flex; - margin-top: 1rem; - padding: 1rem; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - width: 100%; - } - .list-item-link svg:first-child { - margin-right: 1rem; - height: 1.5rem; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - width: 1.5rem; - } - .list-item-link > span { - flex-grow: 1; - font-weight: 400; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - } - .list-item-link > span > span { - color: rgba(107, 114, 128, 1); - display: block; - flex-grow: 1; - font-size: 0.75rem; - font-weight: 300; - line-height: 1rem; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - } - .list-item-link svg:last-child { - height: 1rem; - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - width: 1rem; - } - .list-item-link:hover { - color: rgba(255, 255, 255, 1); - background-color: hsla(162, 47%, 50%, 1); - } - .list-item-link:hover > span { - } - .list-item-link:hover > span > span { - color: rgba(243, 244, 246, 1); - } - .list-item-link:hover svg:last-child { - transform: translateX(0.25rem); - } - - #other-links { - } - .button-pill { - padding: 1.5rem 2rem; - transition-duration: 300ms; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - align-items: center; - display: flex; - } - .button-pill svg { - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - flex-shrink: 0; - width: 3rem; - } - .button-pill > span { - letter-spacing: -0.025em; - font-weight: 400; - font-size: 1.125rem; - line-height: 1.75rem; - padding-left: 1rem; - padding-right: 1rem; - } - .button-pill span span { - display: block; - font-size: 0.875rem; - font-weight: 300; - line-height: 1.25rem; - } - .button-pill:hover svg, - .button-pill:hover { - color: rgba(255, 255, 255, 1) !important; - } - #nx-console:hover { - background-color: rgba(0, 122, 204, 1); - } - #nx-console svg { - color: rgba(0, 122, 204, 1); - } - - #nx-repo:hover { - background-color: rgba(24, 23, 23, 1); - } - #nx-repo svg { - color: rgba(24, 23, 23, 1); - } - - #nx-cloud { - margin-bottom: 2rem; - margin-top: 2rem; - padding: 2.5rem 2rem; - } - #nx-cloud > div { - align-items: center; - display: flex; - } - #nx-cloud > div svg { - border-radius: 0.375rem; - flex-shrink: 0; - width: 3rem; - } - #nx-cloud > div h2 { - font-size: 1.125rem; - font-weight: 400; - letter-spacing: -0.025em; - line-height: 1.75rem; - padding-left: 1rem; - padding-right: 1rem; - } - #nx-cloud > div h2 span { - display: block; - font-size: 0.875rem; - font-weight: 300; - line-height: 1.25rem; - } - #nx-cloud p { - font-size: 1rem; - line-height: 1.5rem; - margin-top: 1rem; - } - #nx-cloud pre { - margin-top: 1rem; - } - #nx-cloud a { - color: rgba(107, 114, 128, 1); - display: block; - font-size: 0.875rem; - line-height: 1.25rem; - margin-top: 1.5rem; - text-align: right; - } - #nx-cloud a:hover { - text-decoration: underline; - } - - #commands { - padding: 2.5rem 2rem; - - margin-top: 3.5rem; - } - #commands h2 { - font-size: 1.25rem; - font-weight: 400; - letter-spacing: -0.025em; - line-height: 1.75rem; - padding-left: 1rem; - padding-right: 1rem; - } - #commands p { - font-size: 1rem; - font-weight: 300; - line-height: 1.5rem; - margin-top: 1rem; - padding-left: 1rem; - padding-right: 1rem; - } - details { - align-items: center; - display: flex; - margin-top: 1rem; - padding-left: 1rem; - padding-right: 1rem; - width: 100%; - } - details pre > span { - color: rgba(181, 181, 181, 1); - } - summary { - border-radius: 0.5rem; - display: flex; - font-weight: 400; - padding: 0.5rem; - cursor: pointer; - transition-property: background-color, border-color, color, fill, stroke, - opacity, box-shadow, transform, filter, backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - } - summary:hover { - background-color: rgba(243, 244, 246, 1); - } - summary svg { - height: 1.5rem; - margin-right: 1rem; - width: 1.5rem; - } - - #love { - color: rgba(107, 114, 128, 1); - font-size: 0.875rem; - line-height: 1.25rem; - margin-top: 3.5rem; - opacity: 0.6; - text-align: center; - } - #love svg { - color: rgba(252, 165, 165, 1); - width: 1.25rem; - height: 1.25rem; - display: inline; - margin-top: -0.25rem; - } - - @media screen and (min-width: 768px) { - #hero { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - #hero .logo-container { - display: flex; - } - #middle-content { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - } diff --git a/studio-frontend/src/app/app.element.ts b/studio-frontend/src/app/app.element.ts index 1329853..5d14227 100644 --- a/studio-frontend/src/app/app.element.ts +++ b/studio-frontend/src/app/app.element.ts @@ -1,4 +1,5 @@ import * as studio from "@storyteller/studio"; +import { ViewportSize } from "@storyteller/studio"; import "./app.element.scss"; @@ -9,11 +10,8 @@ export class AppElement extends HTMLElement { // TODO: This siezes up the whole browser for several seconds, presumably // while the WASM binary is loading. Is there any way to do this // asynchronously? - // TODO: Since we're using `#[wasm_bindgen]` attributes instead of the - // CLI, we can craft our own JS API to interact with Bevy! \o/ As a start, - // we should exploit this to pass an explicit canvas size to Bevy and keep - // it up to date with the browser viewport size. - studio.init(); + const { width, height } = document.body.getBoundingClientRect(); + studio.init(new ViewportSize(width, height)); } } customElements.define("app-root", AppElement); diff --git a/studio-frontend/src/styles.scss b/studio-frontend/src/styles.scss index 90d4ee0..3782467 100644 --- a/studio-frontend/src/styles.scss +++ b/studio-frontend/src/styles.scss @@ -1 +1,10 @@ -/* You can add global styles to this file, and also import other style files */ +*, *::before, *::after { + box-sizing: border-box; +} + +html, body { + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; +} diff --git a/studio/src/lib.rs b/studio/src/lib.rs index 033b7da..c67f828 100644 --- a/studio/src/lib.rs +++ b/studio/src/lib.rs @@ -1,24 +1,31 @@ #![allow(clippy::type_complexity)] use bevy::prelude::*; +use orbit_cam::{OrbitCam, OrbitCamPlugin}; +use test_scene::TestScenePlugin; +use ui::UiLayerPlugin; +use viewport::ViewportSize; use wasm_bindgen::prelude::*; mod orbit_cam; mod test_scene; mod ui; - -use orbit_cam::{OrbitCam, OrbitCamPlugin}; -use test_scene::TestScenePlugin; -use ui::UiLayerPlugin; +mod viewport; #[wasm_bindgen] -pub fn init() { +pub fn init(viewport_size: ViewportSize) { #[cfg(target_arch = "wasm32")] console_error_panic_hook::set_once(); App::new() .add_plugins(( - DefaultPlugins, + DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + resolution: viewport_size.into(), + ..default() + }), + ..default() + }), OrbitCamPlugin, TestScenePlugin, UiLayerPlugin, diff --git a/studio/src/main.rs b/studio/src/main.rs index 97f51bc..7e35631 100644 --- a/studio/src/main.rs +++ b/studio/src/main.rs @@ -1,3 +1,3 @@ fn main() { - studio::init(); + studio::init(Default::default()); } diff --git a/studio/src/viewport.rs b/studio/src/viewport.rs new file mode 100644 index 0000000..99072c0 --- /dev/null +++ b/studio/src/viewport.rs @@ -0,0 +1,37 @@ +use bevy::window::WindowResolution; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub struct ViewportSize { + pub width: f32, + pub height: f32, +} + +#[wasm_bindgen] +impl ViewportSize { + #[wasm_bindgen(constructor)] + pub fn new(width: f32, height: f32) -> Self { + Self { width, height } + } +} + +impl Default for ViewportSize { + fn default() -> Self { + WindowResolution::default().into() + } +} + +impl From for WindowResolution { + fn from(value: ViewportSize) -> Self { + Self::new(value.width, value.height) + } +} + +impl From for ViewportSize { + fn from(value: WindowResolution) -> Self { + Self { + width: value.width(), + height: value.height(), + } + } +}