mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
UI styling, main workspace layout (#119)
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
import { bind, inject, observe } from "@storyteller/framework";
|
||||
import * as studio from "@storyteller/studio";
|
||||
import { BlockingCommand, TransformSpace, TransformType } from "@storyteller/studio";
|
||||
import {
|
||||
SCENE_DATA_PROVIDER,
|
||||
STUDIO_PARAMS,
|
||||
type SceneDataProvider,
|
||||
type StudioParams,
|
||||
} from "@storyteller/studio-web";
|
||||
import { ButtonElement } from "@storyteller/studio-ui/button";
|
||||
import { LitElement, PropertyValues, TemplateResult, html, nothing } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { createRef, ref } from "lit/directives/ref.js";
|
||||
import {
|
||||
ANIM_TIMELINE_CONTROLLER,
|
||||
type AnimTimelineController,
|
||||
} from "./anim-timeline-controller.element";
|
||||
|
||||
import "@storyteller/studio-web/entity-inspector";
|
||||
import "@storyteller/studio-web/studio";
|
||||
import "@storyteller/studio-ui/button";
|
||||
import "@storyteller/studio-ui/forms/radio";
|
||||
import "@storyteller/studio-ui/forms/select";
|
||||
import "@storyteller/studio-ui/toolbar";
|
||||
import "./anim-timeline-controls.element";
|
||||
|
||||
import "./studio-viewport.element.scss";
|
||||
|
||||
@customElement("sts-studio-viewport")
|
||||
export class StudioViewportElement extends LitElement {
|
||||
@inject(STUDIO_PARAMS)
|
||||
_params!: StudioParams;
|
||||
|
||||
@observe(["selectedEntity", "selectedObject"])
|
||||
@inject(SCENE_DATA_PROVIDER)
|
||||
_sceneData!: SceneDataProvider;
|
||||
|
||||
@observe(["tracks"])
|
||||
@inject(ANIM_TIMELINE_CONTROLLER)
|
||||
_timeline!: AnimTimelineController;
|
||||
|
||||
@state() _transformSpace = TransformSpace.Local;
|
||||
@state() _transformType = TransformType.Translate;
|
||||
|
||||
get #selectedEntityInTracklist() {
|
||||
return (
|
||||
this._sceneData.selectedEntity != null
|
||||
&& this._sceneData.selectedEntity in this._timeline.tracks
|
||||
);
|
||||
}
|
||||
|
||||
#fileTriggerRef = createRef<ButtonElement>();
|
||||
#mediaLibraryTriggerRef = createRef<ButtonElement>();
|
||||
|
||||
get #selectedObject() {
|
||||
return this._sceneData.selectedObject;
|
||||
}
|
||||
|
||||
protected override createRenderRoot = () => this;
|
||||
|
||||
protected override update(changes: PropertyValues<this>): void {
|
||||
if (changes.has("_transformSpace"))
|
||||
studio.setTransformSpace(this._transformSpace);
|
||||
|
||||
if (changes.has("_transformType"))
|
||||
studio.setTransformType(this._transformType);
|
||||
|
||||
super.update(changes);
|
||||
}
|
||||
|
||||
protected override render(): TemplateResult {
|
||||
return html`
|
||||
<sts-studio
|
||||
class="studio"
|
||||
.objectId=${this._params.objectId}
|
||||
.bvhPath=${this._params.bvh}
|
||||
.mixamoPath=${this._params.mixamo}
|
||||
.sceneImport=${this._params.sceneImport}
|
||||
.storytellerScene=${this._params.scene}
|
||||
.skyboxId=${this._params.skybox ?? "test_scene"}
|
||||
.mode=${this._params.mode}
|
||||
>
|
||||
<div class="main-menu abs h-start v-start offset">
|
||||
<sts-button
|
||||
${ref(this.#fileTriggerRef)}
|
||||
dropdown
|
||||
icon="file"
|
||||
>
|
||||
File
|
||||
</sts-button>
|
||||
<sts-button
|
||||
icon="question"
|
||||
@click=${() => {
|
||||
// TODO
|
||||
}}
|
||||
>
|
||||
Help
|
||||
</sts-button>
|
||||
</div>
|
||||
|
||||
<sts-toolbar class="top-toolbar abs h-center v-start">
|
||||
|
||||
<sts-toolbar-group>
|
||||
<sts-button
|
||||
${ref(this.#mediaLibraryTriggerRef)}
|
||||
secondary
|
||||
icon="plus-large"
|
||||
title="Add asset from Media Library"
|
||||
></sts-button>
|
||||
</sts-toolbar-group>
|
||||
<hr />
|
||||
<sts-toolbar-group>
|
||||
<sts-button
|
||||
class="primitive"
|
||||
icon="cube"
|
||||
title="Cube"
|
||||
@click=${() => studio.dispatchBlockingCommand(BlockingCommand.Cube)}
|
||||
></sts-button>
|
||||
<sts-button
|
||||
class="primitive"
|
||||
icon="cylinder"
|
||||
title="Cylinder"
|
||||
@click=${() => studio.dispatchBlockingCommand(BlockingCommand.Cylinder)}
|
||||
></sts-button>
|
||||
<sts-button
|
||||
class="primitive"
|
||||
icon="sphere"
|
||||
title="Sphere"
|
||||
@click=${() => studio.dispatchBlockingCommand(BlockingCommand.Sphere)}
|
||||
></sts-button>
|
||||
<sts-button
|
||||
class="primitive"
|
||||
icon="torus"
|
||||
title="Torus"
|
||||
@click=${() => studio.dispatchBlockingCommand(BlockingCommand.Torus)}
|
||||
></sts-button>
|
||||
</sts-toolbar-group>
|
||||
|
||||
<hr />
|
||||
|
||||
<sts-toolbar-group>
|
||||
<sts-select class="transform-space"
|
||||
title="Transform space"
|
||||
.value=${bind(this, "_transformSpace")}
|
||||
>
|
||||
<sts-option .value=${TransformSpace.Local}>
|
||||
<sts-icon icon="xform-local"></sts-icon>
|
||||
Local
|
||||
</sts-option>
|
||||
<sts-option .value=${TransformSpace.World}>
|
||||
<sts-icon icon="globe"></sts-icon>
|
||||
Global
|
||||
</sts-option>
|
||||
</sts-select>
|
||||
|
||||
<sts-radio-group
|
||||
title="Transform type"
|
||||
.value=${bind(this, "_transformType")}
|
||||
>
|
||||
<sts-radio .value=${TransformType.Translate}>
|
||||
<sts-icon icon="up-down-left-right">Translate</sts-icon>
|
||||
</sts-radio>
|
||||
<sts-radio .value=${TransformType.Rotate}>
|
||||
<sts-icon icon="rotate">Rotate</sts-icon>
|
||||
</sts-radio>
|
||||
<sts-radio .value=${TransformType.Scale}>
|
||||
<sts-icon icon="scale">Scale</sts-icon>
|
||||
</sts-radio>
|
||||
</sts-radio-group>
|
||||
</sts-toolbar-group>
|
||||
|
||||
<hr />
|
||||
|
||||
<sts-toolbar-group>
|
||||
<sts-button class="stylize" primary>
|
||||
Stylize <sts-icon icon="chevron-right"></sts-icon>
|
||||
</sts-button>
|
||||
</sts-toolbar-group>
|
||||
</sts-toolbar>
|
||||
|
||||
<div class="abs h-end v-start offset">
|
||||
<sts-button>Switch to Camera View</sts-button>
|
||||
</div>
|
||||
|
||||
<sts-anim-timeline-controls
|
||||
class="timeline-controls abs h-center v-end"
|
||||
></sts-anim-timeline-controls>
|
||||
|
||||
${this.#selectedObject != null ? html`
|
||||
<div class="inspector abs h-end v-end offset">
|
||||
<header class="inspector__header">
|
||||
<div class="object-name">
|
||||
${this.#selectedObject.icon != null ? html`
|
||||
<sts-icon .icon=${this.#selectedObject.icon}></sts-icon>
|
||||
` : nothing}
|
||||
<h3>${this.#selectedObject.name}</h3>
|
||||
</div>
|
||||
<sts-button
|
||||
class="swap-object"
|
||||
icon="swap"
|
||||
>
|
||||
Swap object
|
||||
</sts-button>
|
||||
</header>
|
||||
<sts-entity-inspector></sts-entity-inspector>
|
||||
<footer class="inspector__footer">
|
||||
${this.#selectedEntityInTracklist ? html`
|
||||
<sts-button
|
||||
class="add-keyframe"
|
||||
keybind="K"
|
||||
@click=${() => this._timeline.addKeyframe()}
|
||||
>
|
||||
Add Keyframe
|
||||
</sts-button>
|
||||
` : this._sceneData.selectedEntity != null ? html`
|
||||
<sts-button
|
||||
class="add-to-timeline"
|
||||
@click=${() => this._timeline.addTrack(this._sceneData.selectedEntity!)}
|
||||
>
|
||||
Add to Timeline
|
||||
</sts-button>
|
||||
` : nothing}
|
||||
|
||||
<sts-button
|
||||
class="delete"
|
||||
icon="trash"
|
||||
title="Delete Entity"
|
||||
></sts-button>
|
||||
</footer>
|
||||
</div>
|
||||
` : nothing}
|
||||
|
||||
</sts-studio>
|
||||
|
||||
<sts-menu
|
||||
autoClose
|
||||
.trigger=${this.#fileTriggerRef}
|
||||
>
|
||||
<sts-button
|
||||
role="menuitem"
|
||||
keybind="Ctrl+N"
|
||||
@click=${() => {
|
||||
// TODO
|
||||
}}
|
||||
>
|
||||
New scene
|
||||
</sts-button>
|
||||
<sts-button
|
||||
role="menuitem"
|
||||
keybind="Ctrl+Shift+N"
|
||||
@click=${() => {
|
||||
// TODO
|
||||
}}
|
||||
>
|
||||
New scene from template...
|
||||
</sts-button>
|
||||
<hr />
|
||||
<sts-button
|
||||
role="menuitem"
|
||||
keybind="Ctrl+S"
|
||||
@click=${() => {
|
||||
// TODO: Should we show a spinner here while we're waiting?
|
||||
// Toast message for success/failure?
|
||||
// TODO: Need to disable this when the scene is not ours
|
||||
studio.saveScene();
|
||||
}}
|
||||
>
|
||||
Save scene
|
||||
</sts-button>
|
||||
<sts-button
|
||||
role="menuitem"
|
||||
keybind="Ctrl+Shift+S"
|
||||
@click=${() => {
|
||||
// TODO
|
||||
}}
|
||||
>
|
||||
Save scene as copy...
|
||||
</sts-button>
|
||||
</sts-menu>
|
||||
|
||||
<sts-dialog
|
||||
.trigger=${this.#mediaLibraryTriggerRef}
|
||||
tag="sts-media-library-dialog"
|
||||
nonBlocking
|
||||
></sts-dialog>
|
||||
`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user