diff --git a/Cargo.lock b/Cargo.lock index 6b0a14d..5c1b8f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1420,6 +1420,20 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "bevy_web_asset" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7e9b05e9baf4a0ed31e33fc056c0d179d2b6c07a9d63b7e425a847286456b3" +dependencies = [ + "bevy", + "isahc", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "bevy_window" version = "0.12.1" @@ -1659,6 +1673,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "castaway" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" + [[package]] name = "cc" version = "1.0.83" @@ -1978,6 +1998,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "curl" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.70+curl-8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0333d8849afe78a4c8102a429a446bfdd055832af071945520e835ae2d841e" +dependencies = [ + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "windows-sys 0.48.0", +] + [[package]] name = "d3d12" version = "0.7.0" @@ -2162,6 +2213,15 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "epaint" version = "0.23.0" @@ -2640,6 +2700,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "idna" version = "0.4.0" @@ -2725,6 +2796,33 @@ dependencies = [ "mach2", ] +[[package]] +name = "isahc" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +dependencies = [ + "async-channel", + "castaway", + "crossbeam-utils", + "curl", + "curl-sys", + "encoding_rs", + "event-listener", + "futures-lite", + "http", + "log", + "mime", + "once_cell", + "polling", + "slab", + "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", +] + [[package]] name = "itertools" version = "0.11.0" @@ -2912,6 +3010,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libnghttp2-sys" +version = "0.1.9+1.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57e858af2798e167e709b9d969325b6d8e9d50232fcbc494d7d54f976854a64" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libudev-sys" version = "0.1.4" @@ -2922,6 +3030,18 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libz-sys" +version = "1.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "295c17e837573c8c821dbaeb3cceb3d745ad082f7572191409e69cbc1b3fd050" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "lock_api" version = "0.4.10" @@ -3014,6 +3134,12 @@ dependencies = [ "paste", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3428,6 +3554,24 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "orbclient" version = "0.3.46" @@ -3530,6 +3674,26 @@ dependencies = [ "indexmap 2.0.0", ] +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3566,6 +3730,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "pp-rs" version = "0.2.1" @@ -3839,6 +4019,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3945,6 +4134,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "sluice" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" +dependencies = [ + "async-channel", + "futures-core", + "futures-io", +] + [[package]] name = "smallvec" version = "1.11.1" @@ -3963,6 +4163,16 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "space_bevy_xpbd_plugin" version = "0.3.1" @@ -4105,6 +4315,7 @@ dependencies = [ "bevy_mod_picking", "bevy_mod_raycast", "bevy_rapier3d", + "bevy_web_asset", "bitflags 2.4.0", "console_error_panic_hook", "js-sys", @@ -4308,6 +4519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4334,6 +4546,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.3" @@ -4462,6 +4684,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -4849,6 +5077,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4879,6 +5116,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -4891,6 +5143,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -4903,6 +5161,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -4915,6 +5179,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4927,6 +5197,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4939,6 +5215,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4951,6 +5233,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4963,6 +5251,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winit" version = "0.28.7" diff --git a/studio-frontend/src/app/app.element.ts b/studio-frontend/src/app/app.element.ts index a3ef43d..9f1e3fc 100644 --- a/studio-frontend/src/app/app.element.ts +++ b/studio-frontend/src/app/app.element.ts @@ -20,6 +20,7 @@ import { Ref, createRef, ref } from "lit-html/directives/ref.js"; import "@storyteller/studio-web/canvas-provider"; import "@storyteller/studio-web/viewer"; +import "@storyteller/studio-web/bvh-viewer"; import "./button.element"; import "./help.element"; import "./icon.element"; @@ -44,6 +45,7 @@ export class AppElement extends LitElement { @state() sceneObjects: SceneObject[] = []; @state() selection?: string | null; + @state() bvhPath?: string; @state() mode?: StudioMode; #sceneObjects: studio.SceneObject[] = []; @@ -62,6 +64,9 @@ export class AppElement extends LitElement { const params = new URLSearchParams(document.location.search); + if (params.has("bvh")) + this.bvhPath = params.get("bvh")!; + this.mode = match (params.get("mode"), { "studio": () => StudioMode.Editor, "viewer": () => StudioMode.Viewer, @@ -184,16 +189,20 @@ export class AppElement extends LitElement { class="app-root" ${ref(this.#canvasProvider as any)} > - ${ - // TODO: See notes in studio-web/src/lib/viewer.element.ts - nothing - } - + ${this.bvhPath ? html` + + ` : html` + + `} @@ -215,17 +224,17 @@ export class AppElement extends LitElement { .space=${this.transformSpace} @space-change=${this.onTransformSpaceChange} > - ` : nothing} -
- ${this.sceneObjects.map(obj => html` - - `)} -
+
+ ${this.sceneObjects.map(obj => html` + + `)} +
+ ` : nothing} ${this.showHelp ? html` diff --git a/studio-web/src/index.ts b/studio-web/src/index.ts index d51e81e..7b96f52 100644 --- a/studio-web/src/index.ts +++ b/studio-web/src/index.ts @@ -1,2 +1,3 @@ +export * from "./lib/bvh-viewer.element"; export * from "./lib/canvas-provider.element"; export * from "./lib/viewer.element"; diff --git a/studio-web/src/lib/bvh-viewer.element.ts b/studio-web/src/lib/bvh-viewer.element.ts new file mode 100644 index 0000000..d81f0d3 --- /dev/null +++ b/studio-web/src/lib/bvh-viewer.element.ts @@ -0,0 +1,34 @@ +import * as studio from "@storyteller/studio"; +import { ViewportSize } from "@storyteller/studio"; +import { customElement, property } from "lit/decorators.js"; + +import { StudioBaseElement } from "./studio-base.element"; +import { PropertyValues } from "lit"; + +@customElement("sts-bvh-viewer") +export class BvhViewerElement extends StudioBaseElement { + @property() bvhPath?: string; + @property() skyboxId?: string; + + onStart(viewportSize: ViewportSize): void { + if (!this.bvhPath) return; + if (!this.skyboxId) return; + + studio.startBvhViewer( + this.bvhPath, + this.skyboxId, + `#${this._canvasProvider!.canvasId}`, + "Storyteller Studio", + viewportSize, + ); + } + + onChanges(changes: PropertyValues): void { + if (changes.has("bvhPath") && !!this.bvhPath) { + // TODO + } + + if (changes.has("skyboxId") && !!this.skyboxId) + studio.setSkybox(this.skyboxId); + } +} diff --git a/studio-web/src/lib/viewer.element.scss b/studio-web/src/lib/studio-base.element.scss similarity index 100% rename from studio-web/src/lib/viewer.element.scss rename to studio-web/src/lib/studio-base.element.scss diff --git a/studio-web/src/lib/studio-base.element.ts b/studio-web/src/lib/studio-base.element.ts new file mode 100644 index 0000000..65db8cd --- /dev/null +++ b/studio-web/src/lib/studio-base.element.ts @@ -0,0 +1,72 @@ +import { inject } from "@storyteller/framework"; +import * as studio from "@storyteller/studio"; +import { ViewportSize } from "@storyteller/studio"; +import { LitElement, PropertyValues, html, unsafeCSS } from "lit"; + +import { CANVAS_PROVIDER, type CanvasProvider } from "./canvas-provider.element"; + +import styles from "./studio-base.element.scss?inline"; + +export abstract class StudioBaseElement extends LitElement { + static override styles = unsafeCSS(styles); + + @inject(CANVAS_PROVIDER) + _canvasProvider?: CanvasProvider; + + #canvas?: HTMLCanvasElement; + #resizeObserver?: ResizeObserver; + + abstract onStart(viewportSize: ViewportSize): void; + abstract onChanges?(changes: PropertyValues): void; + + override connectedCallback(): void { + super.connectedCallback(); + + this.#resizeObserver = new ResizeObserver(this.#onResize.bind(this)); + this.#resizeObserver.observe(this); + + if (!this._canvasProvider) + throw new Error(`No provider found for token: ${CANVAS_PROVIDER}`); + + if ((this.#canvas = this._canvasProvider.takeCanvas())) + this.appendChild(this.#canvas); + } + + override disconnectedCallback(): void { + if (this.#canvas) + this._canvasProvider?.returnCanvas(this.removeChild(this.#canvas)); + + this.#resizeObserver?.disconnect(); + + super.disconnectedCallback(); + } + + protected override updated(changes: PropertyValues): void { + if (!studio.isInitialized()) { + this.#start(); + } else { + this.onChanges?.(changes); + } + } + + #onResize(): void { + const { width, height } = this.getBoundingClientRect(); + studio.resize(new ViewportSize(width, height)); + } + + #start(): void { + if (!this.#canvas) return; + + const { width, height } = this.getBoundingClientRect(); + try { + this.onStart(new ViewportSize(width, height)); + } catch (err) { + if (!(err as Error).message?.startsWith("Using exceptions for control flow")) + throw err; + } + } + + protected override render = () => html` + + `; +} diff --git a/studio-web/src/lib/viewer.element.ts b/studio-web/src/lib/viewer.element.ts index 7ee3aea..ec72727 100644 --- a/studio-web/src/lib/viewer.element.ts +++ b/studio-web/src/lib/viewer.element.ts @@ -1,99 +1,37 @@ import * as studio from "@storyteller/studio"; import { StudioMode, ViewportSize } from "@storyteller/studio"; -import { inject } from "@storyteller/framework"; -import { LitElement, PropertyValues, html, unsafeCSS } from "lit"; +import { PropertyValues } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { CANVAS_PROVIDER, type CanvasProvider } from "./canvas-provider.element"; - -import styles from "./viewer.element.scss?inline"; +import { StudioBaseElement } from "./studio-base.element"; @customElement("sts-viewer") -export class ViewerElement extends LitElement { - static override styles = unsafeCSS(styles); - - // TODO: `` and `` should be separate element - // types with different inputs. `` should take a BVH - // animation and load a simple mannequin asset playing the given - // animation in a loop, while `` should take a scene - // asset handle and load it with full editing capabilities. - // - // Both elements should share most of the core functionality here, - // which could easily be extracted to a base class for inheritance by - // making `#startViewer` an abstract method. +export class ViewerElement extends StudioBaseElement { @property() objectId?: string; @property() skyboxId?: string; @property({ type: Number }) mode?: StudioMode; - @inject(CANVAS_PROVIDER) - _canvasProvider?: CanvasProvider; - - #canvas?: HTMLCanvasElement; - #resizeObserver?: ResizeObserver; - - override connectedCallback(): void { - super.connectedCallback(); - - this.#resizeObserver = new ResizeObserver(this.#onResize.bind(this)); - this.#resizeObserver.observe(this); - - if (!this._canvasProvider) - throw new Error(`No provider found for token: ${CANVAS_PROVIDER}`); - - if ((this.#canvas = this._canvasProvider.takeCanvas())) - this.appendChild(this.#canvas); - } - - override disconnectedCallback(): void { - if (this.#canvas) - this._canvasProvider?.returnCanvas(this.removeChild(this.#canvas)); - - this.#resizeObserver?.disconnect(); - - super.disconnectedCallback(); - } - - protected override updated(changes: PropertyValues): void { - if (!studio.isInitialized()) { - this.#startViewer(); - } else { - if (changes.has("objectId") && !!this.objectId) - studio.loadObject(this.objectId); - - if (changes.has("skyboxId") && !!this.skyboxId) - studio.setSkybox(this.skyboxId); - } - } - - protected override render = () => html` - - `; - - #onResize(): void { - const { width, height } = this.getBoundingClientRect(); - studio.resize(new ViewportSize(width, height)); - } - - #startViewer(): void { - if (!this.#canvas) return; + onStart(viewportSize: ViewportSize): void { if (!this.objectId) return; if (!this.skyboxId) return; if (this.mode == null) return; - const { width, height } = this.getBoundingClientRect(); - try { - studio.start( - this.objectId, - this.skyboxId, - `#${this._canvasProvider!.canvasId}`, - "Storyteller Studio", - new ViewportSize(width, height), - this.mode, - ); - } catch (err) { - if (!(err as Error).message?.startsWith("Using exceptions for control flow")) - throw err; - } + studio.start( + this.objectId, + this.skyboxId, + `#${this._canvasProvider!.canvasId}`, + "Storyteller Studio", + viewportSize, + this.mode, + ); + } + + onChanges(changes: PropertyValues): void { + if (changes.has("objectId") && !!this.objectId) + studio.loadObject(this.objectId); + + if (changes.has("skyboxId") && !!this.skyboxId) + studio.setSkybox(this.skyboxId); } } diff --git a/studio/Cargo.toml b/studio/Cargo.toml index d767a44..e01809d 100644 --- a/studio/Cargo.toml +++ b/studio/Cargo.toml @@ -35,6 +35,7 @@ web-sys = { version = "0.3.65", optional = true, features = [ "Window", ] } space_editor = {git = "https://github.com/rewin123/space_editor", rev = "e150ecaf0647de6532d2967928982abf2558bfbc"} +bevy_web_asset = "0.7.0" [features] wasm = [ diff --git a/studio/src/lib.rs b/studio/src/lib.rs index f77d0eb..313179d 100644 --- a/studio/src/lib.rs +++ b/studio/src/lib.rs @@ -2,8 +2,9 @@ use bevy::{app::PluginGroupBuilder, prelude::*}; use bevy_mod_picking::DefaultPickingPlugins; - +use bevy_web_asset::WebAssetPlugin; use space_editor::prelude::space_undo::UndoPlugin; + #[cfg(feature = "wasm")] use wasm_bindgen::prelude::*; @@ -29,7 +30,7 @@ use crate::{ inspector::InspectorPlugin, interaction::InteractionPlugin, math::InterpolationPlugin, - scene::{LoadSceneEvent, ScenePlugin}, + scene::{LoadSceneEvent, ScenePlugin, TestBvh}, skybox::{SkyboxId, SkyboxPlugin}, ui::UiLayerPlugin, world_grid::WorldGridPlugin, @@ -84,6 +85,35 @@ impl PluginGroup for EditorPlugins { } } +#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = startBvhViewer))] +pub fn start_bvh_viewer( + bvh_path: &str, + skybox_id: &str, + canvas_selector: &str, + canvas_alt: &str, + viewport_size: ViewportSize, +) { + let mut app = start_internal( + "Mannequin.gltf", + skybox_id, + canvas_selector, + canvas_alt, + viewport_size, + StudioMode::Viewer, + ); + + let bvh_path = bvh_path.to_string(); + + app.add_systems( + Startup, + move |mut cmd: Commands, r_assets: Res| { + cmd.insert_resource(TestBvh(r_assets.load(bvh_path.clone()))); + }, + ); + + app.run(); +} + #[cfg_attr(feature = "wasm", wasm_bindgen(js_name = startViewer))] /// Start the application as a read-only viewer for a single library object. /// @@ -175,6 +205,7 @@ pub fn start_internal( app.add_plugins(( #[cfg(feature = "wasm")] viewport::wasm::ViewportPlugin, + WebAssetPlugin, DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { resolution: viewport_size.into(), diff --git a/studio/src/scene.rs b/studio/src/scene.rs index ce2d314..a5aa086 100644 --- a/studio/src/scene.rs +++ b/studio/src/scene.rs @@ -40,7 +40,7 @@ impl Plugin for ScenePlugin { .add_systems( Update, ( - spawn_test_bvh, // TODO + spawn_test_bvh.run_if(resource_exists::()), // TODO init_scene_loading, tick_scene_loading.run_if(in_state(SceneState::Loading)), tick_scene_spawning.run_if(in_state(SceneState::Spawning)), @@ -117,7 +117,7 @@ pub struct SkeletalJoint(pub Color); pub struct SceneRoot; #[derive(Resource, Deref, DerefMut)] -struct TestBvh(Handle); // TODO +pub struct TestBvh(pub Handle); // TODO #[derive(Component, Clone, Copy, Debug, Deref, DerefMut)] pub struct BindPoseLocal(pub Transform); @@ -158,9 +158,6 @@ fn initialize(mut cmd: Commands, r_assets: Res) { }, Fxaa::default(), )); - - // TODO - cmd.insert_resource(TestBvh(r_assets.load("mocap/shuffle.bvh"))); } // TODO diff --git a/tsconfig.base.json b/tsconfig.base.json index f6337bf..ab92679 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -20,6 +20,7 @@ "@storyteller/studio-web": ["studio-web/src/index.ts"], "@storyteller/studio-web/canvas-provider": ["studio-web/src/lib/canvas-provider.element.ts"], "@storyteller/studio-web/viewer": ["studio-web/src/lib/viewer.element.ts"], + "@storyteller/studio-web/bvh-viewer": ["studio-web/src/lib/bvh-viewer.element.ts"], "@storyteller/utility": ["utility/src/index.ts"] } },