mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-29 09:08:58 +00:00
Inspector frontend UI (#68)
This PR begins fleshing out the front-end UI for inspecting the selected entity's components. ### Implemented * Support for the `Name` component * Placeholder/WIP support for the `Transform` component ### To-do * Support for sending changes made in the inspector back to Bevy * A slider/field combo widget for numeric values (can be adapted from [this StackBlitz](https://stackblitz.com/edit/angular-wfikuy?file=src%2Ffloat-input%2Ffloat-input.component.ts)) * Quat -> Euler angles conversion ([example math here](https://github.com/dannymcgee/3DGameMath/blob/5cb7a8ff9310565329e57751cd8b9c33e9bd4cb7/libs/Math/include/math/quat.inl.hpp#L56-L78), or use a 3rd-party math library) ### Known issues * Selecting entities from the hierarchy doesn't always update the components list. I suspect this is the same issue as #39
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { on } from "@storyteller/framework";
|
||||
import * as studio from "@storyteller/studio";
|
||||
import { type EntitySelectEvent } from "@storyteller/studio";
|
||||
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { type DynamicProvider, inject, UniqueToken } from "@storyteller/framework";
|
||||
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@@ -10,6 +8,12 @@ import "./icon.element";
|
||||
|
||||
import styles from "./tree.element.scss?inline";
|
||||
|
||||
export const TREE_SELECTION_PROVIDER = UniqueToken.create<TreeSelectionProvider>();
|
||||
|
||||
export interface TreeSelectionProvider extends DynamicProvider<TreeSelectionProvider> {
|
||||
readonly selectedId: string | null;
|
||||
}
|
||||
|
||||
export interface Tree {
|
||||
id?: string;
|
||||
name: string;
|
||||
@@ -26,20 +30,40 @@ export class TreeElement extends LitElement {
|
||||
@property({ attribute: false }) treeChildren?: Tree[];
|
||||
@property({ type: Boolean }) expanded = true;
|
||||
|
||||
@state() selected = false;
|
||||
get selected() {
|
||||
return !!this.id && this._selectionProvider?.selectedId === this.id
|
||||
}
|
||||
|
||||
@inject(TREE_SELECTION_PROVIDER)
|
||||
_selectionProvider?: TreeSelectionProvider;
|
||||
|
||||
override connectedCallback(): void {
|
||||
this._selectionProvider?.addEventListener("property-changes", this.onProviderChanges);
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
override disconnectedCallback(): void {
|
||||
this._selectionProvider?.removeEventListener("property-changes", this.onProviderChanges);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
onProviderChanges = ({ detail: changes }: CustomEvent<PropertyValues<TreeSelectionProvider>>) => {
|
||||
if (changes.has("selectedId"))
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
toggleExpanded(): void {
|
||||
this.expanded = !this.expanded;
|
||||
}
|
||||
|
||||
@on("window:entity-select")
|
||||
onEntitySelect({ detail: entity }: EntitySelectEvent): void {
|
||||
this.selected = this.id === entity;
|
||||
}
|
||||
|
||||
selectEntity(): void {
|
||||
if (this.id)
|
||||
studio.select(this.id);
|
||||
if (this.id) {
|
||||
this.dispatchEvent(new CustomEvent("tree-select", {
|
||||
detail: this.id,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: A11y
|
||||
|
||||
Reference in New Issue
Block a user