diff --git a/studio-frontend/src/app/app.element.ts b/studio-frontend/src/app/app.element.ts
index e1ce04e..da2ace6 100644
--- a/studio-frontend/src/app/app.element.ts
+++ b/studio-frontend/src/app/app.element.ts
@@ -31,6 +31,8 @@ import "@storyteller/studio-web/transform-toolbar";
import "./anim-editor.element";
import "./help.element";
+import "./blocking.element";
+
import "./app.element.scss";
@customElement("app-root")
@@ -149,6 +151,8 @@ export class AppElement extends LitElement {
+
+
` : nothing}
diff --git a/studio-frontend/src/app/blocking.element.scss b/studio-frontend/src/app/blocking.element.scss
new file mode 100644
index 0000000..19a9a3d
--- /dev/null
+++ b/studio-frontend/src/app/blocking.element.scss
@@ -0,0 +1,8 @@
+:host {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ position: absolute;
+ top: 60px;
+ left: 16px;
+}
\ No newline at end of file
diff --git a/studio-frontend/src/app/blocking.element.ts b/studio-frontend/src/app/blocking.element.ts
new file mode 100644
index 0000000..9b88573
--- /dev/null
+++ b/studio-frontend/src/app/blocking.element.ts
@@ -0,0 +1,41 @@
+
+import { LitElement, html, nothing, unsafeCSS } from "lit";
+
+import styles from "./blocking.element.scss?inline";
+import { customElement } from "lit/decorators.js";
+import * as studio from "@storyteller/studio";
+
+@customElement("sts-blocking")
+export class BlockingElement extends LitElement {
+ static override styles = unsafeCSS(styles);
+
+ override render = () => html`
+ {
+ studio.dispatchBlockingCommand(studio.BlockingCommand.Cube);
+ }}>
+ Cube
+
+
+ {
+ studio.dispatchBlockingCommand(studio.BlockingCommand.Sphere);
+ }}>
+ Sphere
+
+
+ {
+ studio.dispatchBlockingCommand(studio.BlockingCommand.Cylinder);
+ }}>
+ Cylinder
+
+
+ {
+ studio.dispatchBlockingCommand(studio.BlockingCommand.Torus);
+ }}>
+ Torus
+
+ `;
+}
\ No newline at end of file
diff --git a/studio/src/ui/blocking.rs b/studio/src/ui/blocking.rs
new file mode 100644
index 0000000..b32a766
--- /dev/null
+++ b/studio/src/ui/blocking.rs
@@ -0,0 +1,83 @@
+use std::sync::Arc;
+
+use bevy::prelude::*;
+use bevy_mod_picking::PickableBundle;
+use space_editor::prelude::{
+ space_undo::{AddedEntity, NewChange},
+ *,
+};
+use wasm_bindgen::prelude::*;
+
+use crate::{
+ interaction::Selectable,
+ scene::SceneElement,
+ wasm::{StaticBuffer, WasmMessageBuffer},
+};
+
+pub struct UiBlockingPlugin;
+
+impl Plugin for UiBlockingPlugin {
+ fn build(&self, app: &mut App) {
+ app.add_systems(Update, read_command_system);
+ }
+}
+
+fn read_command_system(mut commands: Commands, mut change_event: EventWriter) {
+ let Some(cmd) = COMMAND.take_message() else {
+ return;
+ };
+
+ let mut new_entity = commands.spawn((
+ SpatialBundle::default(),
+ PrefabMarker,
+ Selectable,
+ SceneElement::Mesh,
+ PickableBundle::default(),
+ ));
+
+ match cmd {
+ BlockingCommand::Cube => {
+ new_entity
+ .insert(MeshPrimitivePrefab::Cube(1.0))
+ .insert(Name::new("Cube"));
+ }
+ BlockingCommand::Sphere => {
+ new_entity
+ .insert(MeshPrimitivePrefab::Sphere(SpherePrefab { r: 1.0 }))
+ .insert(Name::new("Sphere"));
+ }
+ BlockingCommand::Torus => {
+ new_entity
+ .insert(MeshPrimitivePrefab::Torus(TorusPrefab::default()))
+ .insert(Name::new("Torus"));
+ }
+ BlockingCommand::Cylinder => {
+ new_entity
+ .insert(MeshPrimitivePrefab::Cylinder(CylinderPrefab::default()))
+ .insert(Name::new("Cylinder"));
+ }
+ };
+
+ change_event.send(NewChange {
+ change: Arc::new(AddedEntity {
+ entity: new_entity.id(),
+ }),
+ });
+}
+
+#[derive(Clone, Copy, Debug)]
+#[wasm_bindgen]
+pub enum BlockingCommand {
+ Cube,
+ Sphere,
+ Torus,
+ Cylinder,
+}
+
+static COMMAND: WasmMessageBuffer = WasmMessageBuffer::new();
+
+#[wasm_bindgen(js_name = dispatchBlockingCommand)]
+pub fn dispatch_command(command: BlockingCommand) {
+ info!("Dispatching blocking command: {command:?}");
+ COMMAND.write_message(command);
+}
diff --git a/studio/src/ui/mod.rs b/studio/src/ui/mod.rs
index d3f0385..fa48932 100644
--- a/studio/src/ui/mod.rs
+++ b/studio/src/ui/mod.rs
@@ -4,6 +4,9 @@ use self::fps::FpsCounterPlugin;
mod fps;
+#[cfg(feature = "wasm")]
+mod blocking;
+
#[cfg(feature = "wasm")]
pub mod inspector;
@@ -14,6 +17,9 @@ impl Plugin for UiLayerPlugin {
app.add_plugins(FpsCounterPlugin);
#[cfg(feature = "wasm")]
- app.add_plugins(inspector::InspectorPlugin);
+ {
+ app.add_plugins(inspector::InspectorPlugin);
+ app.add_plugins(blocking::UiBlockingPlugin);
+ }
}
}