From 3413810773f15025c0c86dbdeaa7b601520e10c9 Mon Sep 17 00:00:00 2001 From: Danny McGee Date: Thu, 29 Feb 2024 15:42:49 -0500 Subject: [PATCH] Small batch of misc enhancements (#64) This PR cherry-picks some improvements from #63 that are general-purpose and not specifically related to IK. * Some logic has been added to `AppElement` to track the currently selected Scene Element * `disabled` property has been added to `ButtonElement`, with custom styling and accessibility features * Tagging entities with their `SceneElement` type has been made more robust and reliable (previously, it was possible for all entities to appear in the hierarchy as "Generic" elements depending on the order of system execution) Additionally: * Forces the Netlify CI pipeline to always used the latest stable Rust version --- ci.sh | 4 ++- studio-frontend/src/app/app.element.ts | 32 ++++++++++++++++--- studio-ui/src/lib/button.element.scss | 6 ++++ studio-ui/src/lib/button.element.ts | 13 +++++++- studio-web/src/lib/scene-hierarchy.element.ts | 2 +- studio/src/inspector/wasm.rs | 6 +++- studio/src/scene.rs | 13 ++------ 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/ci.sh b/ci.sh index 5c97c09..d83add2 100755 --- a/ci.sh +++ b/ci.sh @@ -3,10 +3,12 @@ set -euxo pipefail # Install build dependencies +rustup update +rustup default stable rustup target add wasm32-unknown-unknown # Emit versions -rustup show active-toolchain +rustup show npm version # Install project dependencies diff --git a/studio-frontend/src/app/app.element.ts b/studio-frontend/src/app/app.element.ts index 622c554..e1ce04e 100644 --- a/studio-frontend/src/app/app.element.ts +++ b/studio-frontend/src/app/app.element.ts @@ -1,12 +1,17 @@ import { on } from "@storyteller/framework"; import * as studio from "@storyteller/studio"; import { + type EntitySelectEvent, type SceneSavedEvent, type SceneStateEvent, SceneState, StudioMode, } from "@storyteller/studio"; -import { StudioURLParams } from "@storyteller/studio-web"; +import { + SceneHierarchyElement, + type SceneObject, + StudioURLParams, +} from "@storyteller/studio-web"; import { CanvasProvider } from "@storyteller/studio-web/canvas-provider"; import { match } from "@storyteller/utility"; import { LitElement, html, nothing } from "lit"; @@ -33,6 +38,9 @@ export class AppElement extends LitElement { @state() showHelp = false; @state() loading = true; + @state() selection?: SceneObject; + + #hierarchy = createRef(); #params = new StudioURLParams(); #canvasProvider: Ref = createRef(); @@ -79,6 +87,15 @@ export class AppElement extends LitElement { }); } + @on("entity-select") + onEntitySelected({ detail: id }: EntitySelectEvent): void { + if (!id) { + this.selection = undefined; + } else { + this.selection = this.#hierarchy.value?.entityMap.get(id); + } + } + toggleHelp(): void { this.showHelp = !this.showHelp; } @@ -122,9 +139,16 @@ export class AppElement extends LitElement { ${this.#params.mode === StudioMode.Editor ? html` - - - + + + ` : nothing} diff --git a/studio-ui/src/lib/button.element.scss b/studio-ui/src/lib/button.element.scss index 2939af9..a171b45 100644 --- a/studio-ui/src/lib/button.element.scss +++ b/studio-ui/src/lib/button.element.scss @@ -31,6 +31,12 @@ color: #FFFF; } +:host(.disabled), +:host(.disabled:hover) { + background: #0003; + color: #FFF6; +} + .icon { fill: currentColor; } diff --git a/studio-ui/src/lib/button.element.ts b/studio-ui/src/lib/button.element.ts index a50ec94..73d6f5b 100644 --- a/studio-ui/src/lib/button.element.ts +++ b/studio-ui/src/lib/button.element.ts @@ -1,5 +1,5 @@ import { on } from "@storyteller/framework"; -import { LitElement, html, nothing, unsafeCSS } from "lit"; +import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit"; import { customElement, property } from "lit/decorators.js"; import styles from "./button.element.scss?inline"; @@ -11,10 +11,21 @@ export class ButtonElement extends LitElement { static override styles = unsafeCSS(styles); @property() icon?: string; + @property({ type: Boolean }) disabled = false; override role = "button"; override tabIndex = 0; + protected override willUpdate(changes: PropertyValues): void { + if (changes.has("disabled")) { + this.ariaDisabled = this.disabled ? "true" : null; + this.tabIndex = this.disabled ? -1 : 0; + this.classList.toggle("disabled", this.disabled); + } + + super.willUpdate(changes); + } + @on("keydown") onKeyDown(event: KeyboardEvent) { if (/^( |Enter)$/.test(event.key)) { diff --git a/studio-web/src/lib/scene-hierarchy.element.ts b/studio-web/src/lib/scene-hierarchy.element.ts index 7b14c1a..5d06e05 100644 --- a/studio-web/src/lib/scene-hierarchy.element.ts +++ b/studio-web/src/lib/scene-hierarchy.element.ts @@ -14,7 +14,7 @@ import styles from "./scene-hierarchy.element.scss?inline"; import "@storyteller/studio-ui/tree"; -interface SceneObject extends Omit { +export interface SceneObject extends Omit { icon?: string; children: SceneObject[]; } diff --git a/studio/src/inspector/wasm.rs b/studio/src/inspector/wasm.rs index 286619a..062a56b 100644 --- a/studio/src/inspector/wasm.rs +++ b/studio/src/inspector/wasm.rs @@ -131,6 +131,7 @@ pub(super) fn notify_entity_spawn_changes( mut l_missing_parents: Local>, q_window: Query<&Window, With>, q_inspectables: Query<(Entity, &SceneElement)>, + q_element_changes: Query>, q_others: Query>, q_names: Query<&Name>, q_parents: Query<&Children>, @@ -146,6 +147,7 @@ pub(super) fn notify_entity_spawn_changes( ent, type_, &q_inspectables, + &q_element_changes, &q_names, &q_parents, &q_children, @@ -166,6 +168,7 @@ pub(super) fn notify_entity_spawn_changes( ent, SceneElement::Generic, &q_inspectables, + &q_element_changes, &q_names, &q_parents, &q_children, @@ -204,11 +207,12 @@ fn build_scene_object( ent: Entity, type_: SceneElement, q_inspectables: &Query<(Entity, &SceneElement)>, + q_element_changes: &Query>, q_names: &Query<&Name>, q_parents: &Query<&Children>, q_children: &Query<&Parent>, ) -> Option { - if notified.contains(&ent) { + if notified.contains(&ent) && !q_element_changes.contains(ent) { return None; } diff --git a/studio/src/scene.rs b/studio/src/scene.rs index 9cd07df..c3665e8 100644 --- a/studio/src/scene.rs +++ b/studio/src/scene.rs @@ -233,13 +233,13 @@ pub struct ImportSceneEvent(pub String); derive(Serialize_repr, Deserialize_repr) )] #[derive(Component, Clone, Copy, Debug, PartialEq, Eq)] +#[allow(dead_code)] // Some variants only used in `wasm`, some planned for later use pub enum SceneElement { Generic, Mesh, Skeleton, Bone, Light, - #[allow(dead_code)] // TODO: Will be used for camera animation Camera, } @@ -395,17 +395,8 @@ fn tag_scene_elements( mesh_entities: Query>>, ) { for (e, children) in q_named_non_primitives.iter() { - let mut has_mesh = false; - for child in children { - if mesh_entities.contains(*child) { - has_mesh = true; - break; - } - } - if has_mesh { + if children.iter().any(|child| mesh_entities.contains(*child)) { cmd.entity(e).insert(SceneElement::Mesh); - } else { - cmd.entity(e).insert(SceneElement::Generic); } } }