mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
Single-object viewer POC (#14)
This commit implements a Sketchfab-style single-object viewer as a minimal proof-of-concept. ### `@storyteller/studio-web` This is a new package to house web components for interfacing with the `@storyteller/studio` WASM library. It currently includes a single component, `<sts-viewer />`, which is exported from `@storyteller/studio-web/viewer`. ### `react-frontend` This is a new application intended as a proof-of-concept and testbed for React interop with `@storyteller/studio-web`. Web components are currently a little bit fiddly to use in a React application. `react-frontend/src/app/studio-viewer.tsx` demonstrates how a React-idiomatic component can be written as a thin wrapper around a web component, and `react-frontend/src/app/app.tsx` demonstrates that wrapper component in use.
This commit is contained in:
@@ -131,3 +131,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #222;
|
||||
color: #FFF;
|
||||
font: {
|
||||
family: "Fira Sans", sans-serif;
|
||||
weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,15 @@ import {
|
||||
type EntityMultiSpawnEvent,
|
||||
type EntitySelectEvent,
|
||||
type EntitySpawnEvent,
|
||||
type SceneStateEvent,
|
||||
TransformSpace,
|
||||
TransformType,
|
||||
ViewportSize,
|
||||
SceneState,
|
||||
} from "@storyteller/studio";
|
||||
import { match } from "@storyteller/utility";
|
||||
import { LitElement, html, unsafeCSS } from "lit";
|
||||
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
|
||||
import "./button.element";
|
||||
import "./help.element";
|
||||
@@ -30,6 +31,7 @@ export class AppElement extends LitElement {
|
||||
static override styles = unsafeCSS(styles);
|
||||
|
||||
@state() showHelp = false;
|
||||
@state() loading = true;
|
||||
|
||||
@state() transformSpace = TransformSpace.Local;
|
||||
@state() transformType = TransformType.Translate;
|
||||
@@ -80,6 +82,16 @@ export class AppElement extends LitElement {
|
||||
}));
|
||||
}
|
||||
|
||||
@on("window:scene-state")
|
||||
onSceneStateChange({ detail: state }: SceneStateEvent): void {
|
||||
console.log("scene state change:", SceneState[state]);
|
||||
|
||||
this.loading = match (state, {
|
||||
[SceneState.Active]: () => false,
|
||||
_: () => true,
|
||||
});
|
||||
}
|
||||
|
||||
@on("window:entity-select")
|
||||
onEntitySelectionChange({ detail: entity }: EntitySelectEvent): void {
|
||||
const sceneObject = this.#entityMap.get(entity!);
|
||||
@@ -178,7 +190,13 @@ export class AppElement extends LitElement {
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
try {
|
||||
studio.init(new ViewportSize(width, height));
|
||||
studio.startViewer(
|
||||
"couch",
|
||||
"test_scene",
|
||||
"#studio_canvas",
|
||||
"Storyteller Studio",
|
||||
new ViewportSize(width, height),
|
||||
);
|
||||
} catch (err) {
|
||||
if (!(err as Error).message?.startsWith("Using exceptions for control flow"))
|
||||
throw err;
|
||||
@@ -259,7 +277,14 @@ export class AppElement extends LitElement {
|
||||
|
||||
${this.showHelp ? html`
|
||||
<sts-help class="help"></sts-help>
|
||||
` : null}
|
||||
` : nothing}
|
||||
|
||||
${this.loading ? html`
|
||||
<!-- TODO: Animated spinner or something -- talk to our designers -->
|
||||
<div class="loading">
|
||||
<h1>Loading</h1>
|
||||
</div>
|
||||
` : nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user