mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
Merge branch 'main' into add-persistance
This commit is contained in:
+2
-1
@@ -26,6 +26,7 @@ node_modules
|
|||||||
|
|
||||||
# misc
|
# misc
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
|
/.nx
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
@@ -37,4 +38,4 @@ testem.log
|
|||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
/target
|
/target
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
TransformSpace,
|
TransformSpace,
|
||||||
TransformType,
|
TransformType,
|
||||||
SceneState,
|
SceneState,
|
||||||
|
StudioMode,
|
||||||
} from "@storyteller/studio";
|
} from "@storyteller/studio";
|
||||||
import { CanvasProvider } from "@storyteller/studio-web/canvas-provider";
|
import { CanvasProvider } from "@storyteller/studio-web/canvas-provider";
|
||||||
import { match } from "@storyteller/utility";
|
import { match } from "@storyteller/utility";
|
||||||
@@ -43,6 +44,8 @@ export class AppElement extends LitElement {
|
|||||||
@state() sceneObjects: SceneObject[] = [];
|
@state() sceneObjects: SceneObject[] = [];
|
||||||
@state() selection?: string | null;
|
@state() selection?: string | null;
|
||||||
|
|
||||||
|
@state() mode?: StudioMode;
|
||||||
|
|
||||||
#sceneObjects: studio.SceneObject[] = [];
|
#sceneObjects: studio.SceneObject[] = [];
|
||||||
#entityMap = new Map<string, SceneObject>();
|
#entityMap = new Map<string, SceneObject>();
|
||||||
#canvasProvider: Ref<CanvasProvider> = createRef();
|
#canvasProvider: Ref<CanvasProvider> = createRef();
|
||||||
@@ -54,6 +57,18 @@ export class AppElement extends LitElement {
|
|||||||
return document.getElementById(provider.canvasId) as HTMLCanvasElement | null;
|
return document.getElementById(provider.canvasId) as HTMLCanvasElement | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
|
||||||
|
const params = new URLSearchParams(document.location.search);
|
||||||
|
|
||||||
|
this.mode = match (params.get("mode"), {
|
||||||
|
"studio": () => StudioMode.Editor,
|
||||||
|
"viewer": () => StudioMode.Viewer,
|
||||||
|
_: () => StudioMode.Viewer,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected override createRenderRoot(): Element | ShadowRoot {
|
protected override createRenderRoot(): Element | ShadowRoot {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -169,9 +184,14 @@ export class AppElement extends LitElement {
|
|||||||
class="app-root"
|
class="app-root"
|
||||||
${ref(this.#canvasProvider as any)}
|
${ref(this.#canvasProvider as any)}
|
||||||
>
|
>
|
||||||
|
${
|
||||||
|
// TODO: See notes in studio-web/src/lib/viewer.element.ts
|
||||||
|
nothing
|
||||||
|
}
|
||||||
<sts-viewer
|
<sts-viewer
|
||||||
objectId="sample-room"
|
objectId="sample-room"
|
||||||
skyboxId="test_scene"
|
skyboxId="test_scene"
|
||||||
|
.mode=${this.mode}
|
||||||
@scene-state=${this.onSceneStateChange}
|
@scene-state=${this.onSceneStateChange}
|
||||||
></sts-viewer>
|
></sts-viewer>
|
||||||
|
|
||||||
@@ -187,13 +207,15 @@ export class AppElement extends LitElement {
|
|||||||
</sts-toolbar-group>
|
</sts-toolbar-group>
|
||||||
</sts-toolbar>
|
</sts-toolbar>
|
||||||
|
|
||||||
<sts-transform-toolbar
|
${this.mode === StudioMode.Editor ? html`
|
||||||
class="v-start h-center"
|
<sts-transform-toolbar
|
||||||
.type=${this.transformType}
|
class="v-start h-center"
|
||||||
@type-change=${this.onTransformTypeChange}
|
.type=${this.transformType}
|
||||||
.space=${this.transformSpace}
|
@type-change=${this.onTransformTypeChange}
|
||||||
@space-change=${this.onTransformSpaceChange}
|
.space=${this.transformSpace}
|
||||||
></sts-transform-toolbar>
|
@space-change=${this.onTransformSpaceChange}
|
||||||
|
></sts-transform-toolbar>
|
||||||
|
` : nothing}
|
||||||
|
|
||||||
<div class="hierarchy v-start h-end">
|
<div class="hierarchy v-start h-end">
|
||||||
${this.sceneObjects.map(obj => html`
|
${this.sceneObjects.map(obj => html`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as studio from "@storyteller/studio";
|
import * as studio from "@storyteller/studio";
|
||||||
import { ViewportSize } from "@storyteller/studio";
|
import { StudioMode, ViewportSize } from "@storyteller/studio";
|
||||||
import { inject } from "@storyteller/framework";
|
import { inject } from "@storyteller/framework";
|
||||||
import { LitElement, PropertyValues, html, unsafeCSS } from "lit";
|
import { LitElement, PropertyValues, html, unsafeCSS } from "lit";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
@@ -12,8 +12,18 @@ import styles from "./viewer.element.scss?inline";
|
|||||||
export class ViewerElement extends LitElement {
|
export class ViewerElement extends LitElement {
|
||||||
static override styles = unsafeCSS(styles);
|
static override styles = unsafeCSS(styles);
|
||||||
|
|
||||||
|
// TODO: `<sts-viewer />` and `<sts-studio />` should be separate element
|
||||||
|
// types with different inputs. `<sts-viewer />` should take a BVH
|
||||||
|
// animation and load a simple mannequin asset playing the given
|
||||||
|
// animation in a loop, while `<sts-studio />` should take a scene
|
||||||
|
// asset handle and load it with full editing capabilities.
|
||||||
|
//
|
||||||
|
// Both elements should share most of the core functionality here,
|
||||||
|
// which could easily be extracted to a base class for inheritance by
|
||||||
|
// making `#startViewer` an abstract method.
|
||||||
@property() objectId?: string;
|
@property() objectId?: string;
|
||||||
@property() skyboxId?: string;
|
@property() skyboxId?: string;
|
||||||
|
@property({ type: Number }) mode?: StudioMode;
|
||||||
|
|
||||||
@inject(CANVAS_PROVIDER)
|
@inject(CANVAS_PROVIDER)
|
||||||
_canvasProvider?: CanvasProvider;
|
_canvasProvider?: CanvasProvider;
|
||||||
@@ -68,15 +78,17 @@ export class ViewerElement extends LitElement {
|
|||||||
if (!this.#canvas) return;
|
if (!this.#canvas) return;
|
||||||
if (!this.objectId) return;
|
if (!this.objectId) return;
|
||||||
if (!this.skyboxId) return;
|
if (!this.skyboxId) return;
|
||||||
|
if (this.mode == null) return;
|
||||||
|
|
||||||
const { width, height } = this.getBoundingClientRect();
|
const { width, height } = this.getBoundingClientRect();
|
||||||
try {
|
try {
|
||||||
studio.startViewer(
|
studio.start(
|
||||||
this.objectId,
|
this.objectId,
|
||||||
this.skyboxId,
|
this.skyboxId,
|
||||||
`#${this._canvasProvider!.canvasId}`,
|
`#${this._canvasProvider!.canvasId}`,
|
||||||
"Storyteller Studio",
|
"Storyteller Studio",
|
||||||
new ViewportSize(width, height),
|
new ViewportSize(width, height),
|
||||||
|
this.mode,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err as Error).message?.startsWith("Using exceptions for control flow"))
|
if (!(err as Error).message?.startsWith("Using exceptions for control flow"))
|
||||||
|
|||||||
+4
-2
@@ -8,7 +8,7 @@ use space_editor::{space_editor_ui::{EditorPluginGroup, EditorPickingPlugin, Edi
|
|||||||
use crate::{
|
use crate::{
|
||||||
camera_controller::{CameraController, CameraMotionSystem},
|
camera_controller::{CameraController, CameraMotionSystem},
|
||||||
input::{Action, InputAction, Lifecycle},
|
input::{Action, InputAction, Lifecycle},
|
||||||
MainCamera, interaction::gizmos::camera::GizmoCamera,
|
is_editor, MainCamera,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Resource, Deref, DerefMut)]
|
#[derive(Resource, Deref, DerefMut)]
|
||||||
@@ -36,7 +36,9 @@ impl Plugin for DebugPlugin {
|
|||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
toggle_debug_mode,
|
toggle_debug_mode,
|
||||||
update_debug_picking_mode.run_if(resource_changed::<DebugMode>()),
|
update_debug_picking_mode
|
||||||
|
.run_if(is_editor)
|
||||||
|
.run_if(resource_changed::<DebugMode>()),
|
||||||
update_gizmo_line_thickness,
|
update_gizmo_line_thickness,
|
||||||
(draw_world_axes, draw_debug_points)
|
(draw_world_axes, draw_debug_points)
|
||||||
.after(CameraMotionSystem)
|
.after(CameraMotionSystem)
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,8 @@ use bevy::{
|
|||||||
};
|
};
|
||||||
use space_editor::prelude::space_undo::UndoRedo;
|
use space_editor::prelude::space_undo::UndoRedo;
|
||||||
|
|
||||||
|
use crate::is_editor;
|
||||||
|
|
||||||
#[derive(SystemSet, Hash, Debug, PartialEq, Eq, Clone)]
|
#[derive(SystemSet, Hash, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct StudioInputSystem;
|
pub struct StudioInputSystem;
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ impl Plugin for StudioInputPlugin {
|
|||||||
translate_debug_toggle,
|
translate_debug_toggle,
|
||||||
translate_dcc_camera_events,
|
translate_dcc_camera_events,
|
||||||
translate_fps_camera_events,
|
translate_fps_camera_events,
|
||||||
send_undo_event,
|
send_undo_event.run_if(is_editor),
|
||||||
)
|
)
|
||||||
.in_set(StudioInputSystem)
|
.in_set(StudioInputSystem)
|
||||||
.after(bevy::input::InputSystem)
|
.after(bevy::input::InputSystem)
|
||||||
|
|||||||
+96
-18
@@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{app::PluginGroupBuilder, prelude::*};
|
||||||
use bevy_mod_picking::DefaultPickingPlugins;
|
use bevy_mod_picking::DefaultPickingPlugins;
|
||||||
|
|
||||||
use space_editor::{
|
use space_editor::{
|
||||||
@@ -44,6 +44,46 @@ mod wasm;
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub(crate) struct MainCamera;
|
pub(crate) struct MainCamera;
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
||||||
|
#[derive(Resource, Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub enum StudioMode {
|
||||||
|
Editor,
|
||||||
|
Viewer,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_editor(r_studio_mode: Res<StudioMode>) -> bool {
|
||||||
|
matches!(*r_studio_mode, StudioMode::Editor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The collection of plugins that should be loaded for both viewer-mode and
|
||||||
|
/// editor-mode instances of the app.
|
||||||
|
struct CommonPlugins;
|
||||||
|
impl PluginGroup for CommonPlugins {
|
||||||
|
fn build(self) -> PluginGroupBuilder {
|
||||||
|
PluginGroupBuilder::start::<Self>()
|
||||||
|
.add(CameraControllerPlugin)
|
||||||
|
.add(DebugPlugin)
|
||||||
|
.add(InspectorPlugin)
|
||||||
|
.add(InterpolationPlugin)
|
||||||
|
.add(ScenePlugin)
|
||||||
|
.add(SkyboxPlugin)
|
||||||
|
.add(StudioInputPlugin)
|
||||||
|
.add(UiLayerPlugin)
|
||||||
|
.add(WorldGridPlugin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The collection of plugins that should be loaded only for editor-mode
|
||||||
|
/// instances of the app.
|
||||||
|
struct EditorPlugins;
|
||||||
|
impl PluginGroup for EditorPlugins {
|
||||||
|
fn build(self) -> PluginGroupBuilder {
|
||||||
|
PluginGroupBuilder::start::<Self>()
|
||||||
|
.add(InteractionPlugin)
|
||||||
|
.add(UndoPlugin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
#[cfg_attr(feature = "wasm", wasm_bindgen)]
|
||||||
pub fn init(viewport_size: ViewportSize) {
|
pub fn init(viewport_size: ViewportSize) {
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
@@ -119,6 +159,46 @@ pub fn start_viewer(
|
|||||||
canvas_selector: &str,
|
canvas_selector: &str,
|
||||||
canvas_alt: &str,
|
canvas_alt: &str,
|
||||||
viewport_size: ViewportSize,
|
viewport_size: ViewportSize,
|
||||||
|
) {
|
||||||
|
start_internal(
|
||||||
|
object_id,
|
||||||
|
skybox_id,
|
||||||
|
canvas_selector,
|
||||||
|
canvas_alt,
|
||||||
|
viewport_size,
|
||||||
|
StudioMode::Viewer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = startEditor))]
|
||||||
|
pub fn start_editor(
|
||||||
|
object_id: &str,
|
||||||
|
skybox_id: &str,
|
||||||
|
canvas_selector: &str,
|
||||||
|
canvas_alt: &str,
|
||||||
|
viewport_size: ViewportSize,
|
||||||
|
) {
|
||||||
|
start_internal(
|
||||||
|
object_id,
|
||||||
|
skybox_id,
|
||||||
|
canvas_selector,
|
||||||
|
canvas_alt,
|
||||||
|
viewport_size,
|
||||||
|
StudioMode::Editor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: These `start_` functiions should be refactored to better support the
|
||||||
|
// needs of the "reaodnly viewer" vs "full studio editor" use cases. See
|
||||||
|
// notes in `studio-web/src/lib/viewer.element.ts` for more info.
|
||||||
|
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = start))]
|
||||||
|
pub fn start_internal(
|
||||||
|
object_id: &str,
|
||||||
|
skybox_id: &str,
|
||||||
|
canvas_selector: &str,
|
||||||
|
canvas_alt: &str,
|
||||||
|
viewport_size: ViewportSize,
|
||||||
|
studio_mode: StudioMode,
|
||||||
) {
|
) {
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
@@ -127,6 +207,9 @@ pub fn start_viewer(
|
|||||||
let skybox_id = skybox_id.to_string();
|
let skybox_id = skybox_id.to_string();
|
||||||
|
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
|
app.insert_resource(studio_mode);
|
||||||
|
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
viewport::wasm::ViewportPlugin,
|
viewport::wasm::ViewportPlugin,
|
||||||
@@ -139,19 +222,18 @@ pub fn start_viewer(
|
|||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
DefaultPickingPlugins,
|
CommonPlugins,
|
||||||
DebugPlugin,
|
));
|
||||||
InteractionPlugin,
|
|
||||||
InspectorPlugin,
|
if matches!(studio_mode, StudioMode::Editor) {
|
||||||
StudioInputPlugin,
|
app.add_plugins((DefaultPickingPlugins, EditorPlugins));
|
||||||
InterpolationPlugin,
|
|
||||||
CameraControllerPlugin,
|
// Only for registering components for undo
|
||||||
ScenePlugin,
|
use space_editor::prelude::space_undo::AppAutoUndo;
|
||||||
SkyboxPlugin,
|
app.auto_reflected_undo::<Transform>();
|
||||||
UiLayerPlugin,
|
}
|
||||||
WorldGridPlugin,
|
|
||||||
))
|
app.add_systems(
|
||||||
.add_systems(
|
|
||||||
Startup,
|
Startup,
|
||||||
move |mut cmd: Commands, mut ew: EventWriter<LoadSceneEvent>| {
|
move |mut cmd: Commands, mut ew: EventWriter<LoadSceneEvent>| {
|
||||||
cmd.insert_resource(SkyboxId(skybox_id.clone()));
|
cmd.insert_resource(SkyboxId(skybox_id.clone()));
|
||||||
@@ -159,10 +241,6 @@ pub fn start_viewer(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Only for registering components for undo
|
|
||||||
use space_editor::prelude::space_undo::AppAutoUndo;
|
|
||||||
app.auto_reflected_undo::<Transform>();
|
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
wasm::initialize();
|
wasm::initialize();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user