48 Commits

Author SHA1 Message Date
Danny McGee 5cd98b4a35 Fix layout and UI visibility for viewer mode (#125) 2024-04-05 23:32:03 -04:00
Danny McGee bfc638b644 UI styling, main workspace layout (#119) 2024-04-05 20:15:09 -04:00
Lee-Orr d2ae2f5744 Timeline animation clips (#122)
This is a super initial version of animation clips in timeline.


https://github.com/storytold/storyteller-bevy/assets/10376144/b649162b-8758-4662-bfb9-6a492563b9f7


https://github.com/storytold/storyteller-bevy/assets/10376144/a5815685-bf52-4413-8828-d86051bf850a

---------

Co-authored-by: Danny McGee <dannymcgee@gmail.com>
2024-04-05 02:17:06 -04:00
Lee-Orr ec4809a509 Local assets (#114)
To use it, add "&mock-api" to the URL.
2024-04-02 14:04:53 -04:00
Brandon Thomas 46351e53d3 Brandon more styles (#118) 2024-03-31 15:52:09 -04:00
Brandon Thomas 5412db3b8a no-cors didn't work; undoing (#117) 2024-03-30 18:05:23 -04:00
Brandon Thomas 2b9e23418e no-cors mode for preview requests (#116) 2024-03-30 12:24:02 -04:00
Danny McGee fbc914fd7b Add WIP video style preview dialog (#115)
Co-authored-by: Victor <victor@storyteller.ai>
2024-03-29 22:33:44 -04:00
Victor O 3dba6cb284 added new components (#113)
various components for studio video style transfer

---------

Co-authored-by: Victor <victor@storyteller.ai>
Co-authored-by: Lee-Orr <lee-orr@users.noreply.github.com>
2024-03-29 12:51:02 -07:00
Lee-Orr 364460c774 fix pointer error (#112) 2024-03-28 15:35:19 -04:00
Lee-Orr da152b8585 Initial restyle (#111)
![image](https://github.com/storytold/storyteller-bevy/assets/10376144/b8078ef3-8d36-433d-b75b-5c410eec7b85)
2024-03-28 11:25:02 -04:00
Danny McGee 1163192d24 Media Library: Importing and spawning assets (#109)
This PR updates the Media Library feature to implement asset imports
from the local file system, and spawning assets from the library into
the scene. Additionally, some placeholder functionality has been
scaffolded for adding animations onto existing characters in the scene.

### Additional Changes
* Dialogs can be set to `nonBlocking` to allow interaction with
  background elements (note: this is fraught for accessibility and likely
  temporary, to facilitate testing while the UI/UX redesign is in
  progress)
* Dialogs can be moved around the screen by dragging their title-bars
* The `scene` module has been moved into a folder with a separate
  `wasm.rs` file for its submodule. (`scene/mod.rs` remains one of our
  largest single Rust files and could probably stand to be partitioned
  further.)

### To-Do
* Support for adding animations is not yet fully implemented, though
  some prerequisite functionality has been scaffolded. Namely, the "Add to
  Scene" button will be disabled if:
  - There is a mix of animations and non-animations selected in the Media
    Library
  - There is more than one animation selected in the Media Library
  - There is one animation selected in the Media Library, but no
    animatable character selected in the scene
* Adding full Storyteller-format scenes to the existing scene is not a
  use case that has been tested, and may not be a use case we wish to
  support in the long-term, as some of the data stored in Storyteller
  scenes are intended to be "singleton" resources that may conflict with
  existing data in the scene.
  
  **Attempting to spawn a Storyteller scene through the Media Library has
  not been explicitly blocked for now, but may cause unexpected
  behavior.** This needs additional UX consideration and grooming.
2024-03-27 19:20:33 -04:00
Lee-Orr 7cea820d78 Auto keyframe/scrubbing/snapping (#107)
Co-authored-by: Danny McGee <dannymcgee@gmail.com>
2024-03-27 15:22:14 -04:00
Lee-Orr c890665e16 - avoid updating seek time from UI if source of seek time is studio, … (#102)
…to avoid re-processing timeline info

- move generating animation to first thing in a frame, and notifying
about timeline changes to last, to ensure that it happens before the
time updates
- re-generate the animation tweens whenever you start playing or
manually seek a new time in the timeline to prevent inconsistencies
2024-03-22 17:09:58 -04:00
Brandon Thomas cd19b3e593 Comment out dev-only file save dialog
The `window.showSaveFilePicker()` is used in development to save
`scn.ron` files. Since it's not defined in the source, it's breaking
Netlify production builds. I'm commenting this out for now so we can
unblock production builds, but feel free to restore this
code/functionality for local testing.
2024-03-22 01:32:54 -04:00
Lee-Orr 67a12e42e2 Timeline Saving/Loading, Cameras, and Headless Playback (#98) 2024-03-21 20:35:25 -04:00
Lee-Orr 7f12634780 add url parameter for saving to the local file system &mock-save 2024-03-21 18:15:44 -04:00
Lee-Orr 0eff115eb5 Animation Timeline Initial (#88)
This PR adds an initial animation timeline.

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Danny McGee <dannymcgee@gmail.com>
2024-03-20 20:53:24 -04:00
Danny McGee 03f87b2544 "Add to Scene" menu and Media Library dialog (#78)
This PR adds a new "Add to Scene" dropdown menu for adding elements to
the current scene, and a new Media Library dialog for importing and/or
adding Storyteller Engine assets (characters, scenes, animations, etc.)
associated with the user's Storyteller.ai account.

The scope of this PR is limited to the UI &mdash; actual asset importing
behavior, and adding elements other than primitive shapes to the current
scene, will be implemented in follow-up PRs.

### Technical Details

In order to facilitate these changes, a new "overlay" abstraction has
been added to `@storyteller/studio-ui` (loosely modeled after
[`@angular/cdk/overlay`](https://material.angular.io/cdk/overlay/overview))
for managing DOM elements which should render in a self-contained
stacking context "above" the rest of the application.

Two new base UI components &mdash; `<sts-menu>` and `<sts-dialog>`
&mdash; have also been added to make use of this overlay system, but
it's worth noting that these new components have not yet been
exhaustively tested or thoroughly fleshed out, so they may require
significant changes in order to accommodate future use cases or address
unforeseen bugs.

### Testing

The Media Library makes some API calls which will run into CORS errors
in a normal browser. This can be bypassed by running Chrome with the
following command-line flags:
```
--disable-web-security --ignore-certificate-errors --user-data-dir=path/to/some/temporary/directory
```
Verify all of the following:

* The "Add to Scene" menu opens and closes as expected
* The primitive-shape menu items (Cube, Sphere, etc.) add the
  corresponding elements to the scene
* The "Media Library..." menu item correctly opens the Media Library
  dialog
* The Media Library's search bar and category filters work as expected
* A single asset can be selected by clicking on it
* Multiple assets can be selected by holding the "Ctrl" or "Cmd" key
* The selection can be cleared by clicking in an empty space in the
  results grid
* An "Add to Scene" button appears if (and only if) one or more assets
  are selected
* The Media Library dialog can be closed by:
  - Clicking the "X" in the upper right-hand corner
  - Pressing the "Esc" key
  - Clicking anywhere outside of the dialog boundaries

Additionally, ensure that the Media Library dialog handles all of the
following situations gracefully:
* User is not logged in to fakeyou.com
* User is logged in but does not have any engine-compatible assets
  uploaded (this can be tested by selecting any of the categories from the
  sidebar, since the database has not yet been migrated to use the new
  `media_file_class` field, so all of those categories should currently
  yield an empty list)
* User is logged in and there are engine-compatible assets to list (this
  can be tested by pressing the "Save" button in the main application
  toolbar to save the current scene to your account, and selecting the
  "Home" entry from the Media Library sidebar)
2024-03-15 13:30:06 -04:00
Danny McGee 970f5b25bd Communication bridge to storyteller-frontend (#74)
This PR establishes a rudimentary communication protocol between
Storyteller Studio and the parent application (at fakeyou.com /
storyteller.ai) via the `Window.postMessage` API. An example of how this
protocol can be used from the parent application is here:
https://github.com/storytold/storyteller-frontend/commit/d36e2a9e5c162233d7bd194fdbaa26199bbf6f7a
2024-03-05 18:04:41 -05:00
Danny McGee c9904a5293 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
2024-03-04 15:13:03 -05:00
Danny McGee 9875ea7cca Progress bar for scene loading (#71) 2024-03-04 14:39:48 -05:00
rewin 3a27f3b881 Blocking buttons (#69)
![image](https://github.com/storytold/storyteller-bevy/assets/10954133/6c963b6c-6551-4379-854e-9f3f57cb173d)

---------

Co-authored-by: Danny McGee <dannymcgee@gmail.com>
2024-03-04 21:33:44 +03:00
Danny McGee 3413810773 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
2024-02-29 15:42:49 -05:00
rewin ae88696213 Inspector: component view part (#55)
This PR allow to send entity components data to typescript with
inspector-dom event

Event data

![image](https://github.com/storytold/storyteller-bevy/assets/10954133/f4b5a88e-0a8d-4d56-ade2-d0102a6c08f7)

Component register example

![image](https://github.com/storytold/storyteller-bevy/assets/10954133/f9480f0a-a657-4445-a0d4-0984e2f69900)

Read event example

![image](https://github.com/storytold/storyteller-bevy/assets/10954133/2b6480f0-d1fb-42f1-bd6e-dfbc3d4676a2)


This PR is the first step of new inspector backend logic
Next parts is:
- Allow to edit components fields 
- Allow to show asset data (like show Handle<StandartMaterial> data)
- Allow to edit asset fields
2024-02-29 23:17:51 +03:00
Danny McGee c788bcf6b7 Refactor Studio entry-points (#54)
This PR heavily refactors the entry-point functions in
`studio/src/lib.rs` to simplify and consolidate. Additionally, the
frontend application should now be configurable as expected with any
valid combination of the following URL parameters:

* `objectId` : A pre-bundled library object to load (e.g., "couch.gltf")
* `bvh` : Any resolvable path to a BVH animation with a MocapNET
skeleton (e.g., "mocap/shuffle.bvh")
* `mixamo` : Any resolvable path to a glTF animation with the Mixamo
skeleton (e.g., "mocap/hip-hop-dancing.gltf")
* `sceneImport` : Any resolvable path to an arbitrary glTF scene
(untested, but should theoretically work)
* `scene` : Any resolvable path to a previously saved Storyteller Studio
scene in `*.scn.ron` format
* `skybox` : The ID of a pre-bundled skybox asset. Valid options are:
  - "gum_trees_4k"
  - "kloofenfal_28d_misty_4k"
  - "meadow_4k"
  - "promenade_de_vidy_4k"
  - "scythian_tombs_4k"
  - "test_scene" (this is the default if not specified)
* `mode` : One of "studio" or "viewer" (the default if not specified)

"Validity" rules are as follows:

* `objectId`, `bvh`, `mixamo`, `sceneImport` and `scene` are mutually
exclusive
* `skybox` is not supported for `scene` (the skybox should be saved and
loaded as part of the scene description, though this is not currently
working)
* Both `mode` options are valid for all other parameters
2024-02-27 10:22:00 -07:00
Brooks Palin d51eec52c3 Bootstrap Image Generator application (#53)
This PR begins scaffolding the Stable Diffusion Turbo application (title
TBD), which is a separate frontend for Storyteller Engine which focuses
on image generation.

### Design Overview

* The application renders a "split-screen" view, with Storyteller Studio
  on the left, and the Stable Diffusion Turbo output on the right
* When changes are made in the Studio editor:
  - A screenshot is taken from the Bevy application
  - Screenshot is piped into Stable Diffusion Turbo model
  - Model output is rendered to the screen
* This all happens in as close to real-time as possible

### Work completed in this PR

* The `studio-frontend` project has been (somewhat crudely) refactored
  to split most of its components into reusable libraries
  - `studio-ui` is a use-case-agnostic design system library for core UI
    components. These are "dumb" components which are controlled
    via `@property` inputs and send `CustomEvent`s in response to user
    input.
  - `studio-frontend` is a collection of reusable Storyteller Studio
    widgets. These are "smart" components which depend on
    `@storyteller/studio` directly, manage their own state, and require very
    little configuration or styling. They are designed to be drop-in
    building blocks that can be reused between various frontends.
* The new application has been bootstrapped as `image-generator-demo`
  - Currently, this simply grabs screenshots from the Bevy application and
    renders those screenshots on the right side of the split-screen view. A
    future PR will wire up to the Storyteller.ai backend to pipe these
    screenshots through Stable Diffusion Turbo, and render that model's
    output instead.

### Testing

* Install dependencies as described in the repo's README
* Run `npx nx serve image-generator-demo`
* Open [localhost:4200](http://localhost:4200) in your browser
  - Use the camera controller in the left side of the view to manipulate
    the Bevy scene
  - Verify the right side of the view updates with a fresh screenshot at a
    rate of ~5 fps
* Toggle the "Realtime Capture" checkbox
  - Verify the right side view no longer updates while the user is
    actively manipulating the editor
  - This should allow the app to run smoother on lower-spec hardware

---------

Co-authored-by: Danny McGee <dannymcgee@gmail.com>
2024-02-26 17:13:07 -05:00
Danny McGee 7b06d48c5d Scene storage backend integration (#51)
This PR adds Storyteller.ai API integration for saving and loading
Storyteller Studio scenes to/from the backend.

### Known issues
* The skybox is not currently stored in the serialized scene format
2024-02-23 22:04:06 -05:00
Danny McGee 6ca2a992e5 Storyteller.ai API integration (#49)
This PR integrates asset retrieval from the Storyteller.ai back-end API,
and begins implementing long-term scene saving and storage.

### Media retrieval
Instead of fetching raw asset URLs, going forward, media files from
remote sources (e.g., in URL parameters) should be specified with a path
like the following:
```
remote://<token>.<filetype>
```
where
* `token` is a media token (e.g., "m_70b77neq9jsgmy5v31mekzchcbd223")
* `filetype` is a file extension appropriate for the type of file being
  fetched (e.g., "gltf")

The `remote` protocol will be recognized by a [custom asset
reader](https://github.com/storytold/storyteller-bevy/blob/70726db111f6ccafd47feb055c5546540fef1786/studio/src/remote/reader.rs)
which will retrieve the file by calling a Storyteller API endpoint.

### Scene storage
Additionally, this PR begins laying the groundwork for
storing/retrieving Bevy scenes to/from the backend instead of solely
in-memory. This work is still incomplete -- as of this PR, a button has
been added to the web UI allowing the user to download the scene
file locally for testing/debugging purposes.

### Test URL
Media retrieval from the backend can be tested by [visiting this
URL](https://deploy-preview-49--storyteller-studio.netlify.app/?mode=viewer&mixamo=remote://m_70b77neq9jsgmy5v31mekzchcbd223.gltf)
in Chrome with the `--disable-web-security` flag (to bypass CORS errors)
2024-02-23 21:05:32 -05:00
Danny McGee bc975779d7 Animation Editor UI (#20)
This PR adds a WIP timeline UI for animating elements in the scene.

### Implemented Features

* The timeline can be panned with MMB and zoomed with Ctrl + Mouse Wheel
* The timeline can be "scrubbed" by dragging the red "play-head" with
  LMB
* The timeline sidebar (displaying the list of tracks) can be resized by
  dragging on the edge of the sidebar
* Keyframes can be added by pressing the "Add Keyframe" CTA in the UI
* Keyframes can be selected for editing by clicking the diamond-shaped
  markers in the timeline
* Selected entities (including but not limited to keyframes) can be
  deleted by pressing the "Delete" key
* Keyframes can be moved temporally by dragging the diamond-shaped
  markers in the timeline

### Known issues

* Zooming the timeline in too far results in a soft-lock
* When zooming the timeline, the "transform origin" is currently
  centered on the `00:00` timestamp. For ease of use, it should center on
  the mouse cursor position instead.
* The timeline track-list is currently hard-coded to list the Camera and
  Camera Target. Clicking on these entries currently serves no useful
  purpose and may result in a crash.
* Keyframe markers in the timeline are not currently associated with
  entries in the track-list and simply appear vertically centered in the
  timeline view.
* Added keyframes currently record the position and orientation of the
  scene camera when added, and are rendered in the world with debug
  visualizations, but serve no useful purpose. Some design work is needed
  (both user-experience and architectural) to decide on a workflow for
  actually animating scene elements.
* Entity deletion cannot currently be undone/redone
2024-02-22 14:21:02 -05:00
Danny McGee a5aeff7a3a Mixamo animation support (#37)
This PR adds support for Mixamo FBX imports (via backend conversion to
glTF/glB) and some miscellaneous improvements to the animation systems.

### User-facing improvements
* Retargeting math has been fixed to eliminate jittering issues
* Retargeter can now handle animated bone translations when present
  (generally this is only used for root motion)

### Housekeeping / Code improvements

* Animation-related components and system logic have been moved to a
  dedicated `anim` module and `AnimPlugin`
* Retargeting stuff has been moved from the `bvh` module to
  `anim::retargeting`
* Component-based solution for marking an entity as an animation
  retargeting source makes it easy to extend the retargeting functionality
  to new types of source animations

### Limitations

Currently the code assumes that there will be at most one animation
source at a time. That single animation (if present) will be retargeted
to all other skeletons in the scene. A component-based solution for
directing a specific target skeleton to use a specific source animation
is possible, but will require some additional consideration around the
implementation design for the read-only "viewer" modes.

### Test animations:

* Hip-Hop Dancing (Mixamo): ?mode=viewer&mixamo=mocap/hip-hop-dancing.gltf
* Shuffle (MocapNET): ?mode=viewer&bvh=mocap/shuffle.bvh
* Scott (MocapNET): ?mode=viewer&bvh=mocap/scott.bvh
* Scott 1 (MocapNET): ?mode=viewer&bvh=mocap/scott1.bvh
2024-02-09 13:21:16 -05:00
Danny McGee 0e3c285d30 Load remote BVH from URL param (#30)
This PR replaces the hard-coded BVH animation with a URL parameter, and
adds a specialized BVH viewer web component and entry-point function for
previewing the specified animation on our generic mannequin.
2024-01-19 00:17:51 -05:00
Brooks Palin 5cee4482ef Hotfix: Restore skybox property (#28)
Restores the `skyboxId` property that was acccidentally removed from the
`<sts-viewer />` element
2024-01-18 17:53:23 -05:00
Brooks Palin 4b19c76272 Add Generic Mannequin (#27)
Just adding the mannequin from Scott into the main branch so that it can
be used.

- added the mannequin.gltf
- also now requiring the file extention when selecting file to load.
This is to add flexability with file selection. Let me know if this is a
bad idea.
2024-01-18 15:41:56 -07:00
Danny McGee 1687bfd6ed BVH animation loading / retargeting (#25)
This PR adds support for BVH animation files, with a custom animation
player and retargeting solution for our Blender Rigify-based skeletal
meshes.

---------

Co-authored-by: Brooks Palin <brookspalin710@gmail.com>
2024-01-18 17:28:25 -05:00
Danny McGee 5f62a4024b StudioMode switch for full-editor capabilities (#23)
This PR adds a `StudioMode` resource to toggle editing capabilities, and
configures the frontend application to read the desired mode from a URL
parameter.

For now, setting the app to `StudioMode::Viewer` with
`<app-url>?mode=viewer` hides the Transform Toolbar and disables most of
the interactive features of the app, but otherwise exhibits the same
behavior as `StudioMode::Editor` / `<app-url>?mode=studio`.

In the future, the "Viewer" and "Editor" modes will receive different
initialization inputs to better serve the needs of their use cases. In
particular:

* The "Viewer" mode will accept a BVH animation handle, which should be
  played in a loop on a simple mannequin asset, allowing a user to preview
  a given animation before using it within the full studio workflow.
* The "Editor" mode will accept a full Bevy scene handle which can be
  edited and saved to the user's account. These scenes will serve as the
  basis for the generative-AI workflows Storyteller Studio is ultimately
  seeking to facilitate.
* It will likely be useful for "Editor" mode to alternatively accept
  only a BVH animation handle, which would be used to initialize a new
  scene for editing similar to "Viewer" mode, but with editing
  capabilities enabled.
2024-01-18 13:56:46 -05:00
Danny McGee afe6139f75 Refactor studio-frontend (#19)
This PR does some rudimentary cleanup / reorganizing to the
`studio-frontend` project.

### Changes
* Refactored `studio-frontend` to use the `<sts-canvas-provider/>` and
  `<sts-viewer/>` components from `studio-web`
* Added some CSS layout utilities for positioning overlayed UI elements
* Extracted `<sts-toolbar/>` and `<sts-toolbar-group/>` to their own
  components
* Extracted `<sts-transform-toolbar/>` to its own component
2024-01-12 16:35:32 -05:00
Danny McGee 0a0acacfdb Single-canvas juggling (#15)
This PR adds a `CanvasProviderElement` to `@storyteller/studio-web` to manage
the complexity of maintaining a single concrete `HTMLCanvasElement` for
`@storyteller/studio`, while still being able to treat components like the
`ViewerElement` as self-contained "views" that behave as expected with regards
to CSS styling, DOM placement, etc.

Consuming applications should wrap the new `<sts-canvas-provider />` element
around some common ancestor of all views into the `@storyteller/studio` app,
similar to a React context provider.

The `react-frontend` application has been updated to take advantage of the new
`CanvasProviderElement` by demonstrating a more realistic use case for the
`ViewerElement`. The new demo presents a grid of "thumbnails," one for each
object in our hard-coded "object library." Clicking on one of these thumbnails
will render a `ViewerElement` for that object in a modal dialog.
2023-12-19 16:11:25 -05:00
Danny McGee cba70a62ae Single-object viewer POC (#14)
This commit implements a Sketchfab-style single-object viewer as a minimal
proof-of-concept.

### `@storyteller/studio-web`
This is a new package to house web components for interfacing with the
`@storyteller/studio` WASM library. It currently includes a single component,
`<sts-viewer />`, which is exported from `@storyteller/studio-web/viewer`.

### `react-frontend`
This is a new application intended as a proof-of-concept and testbed for React
interop with `@storyteller/studio-web`.

Web components are currently a little bit fiddly to use in a React application.
`react-frontend/src/app/studio-viewer.tsx` demonstrates how a React-idiomatic
component can be written as a thin wrapper around a web component, and
`react-frontend/src/app/app.tsx` demonstrates that wrapper component in use.
2023-12-07 15:46:32 -05:00
Danny McGee 8bf4abc3a4 Scene Inspector (#11)
This PR adds the bones of a user-facing scene inspector.

### Work Done

To facilitate this work, the Bevy/frontend interface has been expanded to
accommodate two-way communications:

- The Bevy app can now dispatch JavaScript `CustomEvent`s via
  `wasm::dispatch_to_js(...)`
- The frontend application can receive those events by listening for the given
  event type on the `window` object

In its current state, the inspection system works by attaching the `Inspectable`
marker component to any entities which should be exposed to the user. A Bevy
system runs on `Update` to check for newly spawned or despawned entities with
that component, and emits events to notify the frontend. The frontend listens
for those events and updates its model of the scene accordingly, which is then
displayed with a simple tree view.

### Future Enhancements

There are many improvements that must be made to make this system actually
useful, but this PR is being expedited to focus on migrating to Bevy 0.12. A
shortlist of planned updates:

- Identify and expose the "type" of entity (e.g. lights, cameras, meshes,
  skeletons, etc.) via a field on the `Inspectable` component
- Highlight the currently selected entity in the frontend hierarchy
- Ask the Bevy app to update the selection when the user selects an entry in the
  hierarchy
- Add a separate UI panel to inspect and modify the selected entity's components
  via the frontend
2023-11-10 21:07:39 -05:00
Danny McGee 5fed2b6f59 Transform gizmos (#10)
This PR adds functional transform gizmos, along with some new frontend UI to
configure their state.

## Work Done
- [x] Global / Local space toggling
- [x] Gizmo type toggling
- [x] Translation gizmo
  - [x] Axis-constrained translation
  - [x] Plane-constrained translation
  - [x] Screen-space translation
- [x] Rotation gizmo
  - [x] Axis-constrained rotation
  - [x] Screen-space rotation
  - [x] "Trackball" rotation
- [ ] Scale gizmo
  - [ ] Single-axis non-uniform scaling
  - [ ] Two-axis non-uniform scaling
  - [ ] Uniform scaling
- [ ] Combination gizmos
  - [x] Translation + Rotation
  - [ ] Translation + Scale
  - [ ] Rotation + Scale
  - [ ] Translation + Rotation + Scale

## Future Enhancements

### Better visual feedback during transformations

Most DCCs update the visual representation of the transform gizmo while it's in
the process of being actively manipulated. (For example, Blender draws lines in
world-space to indicate that the transformation is constrained to a particular
axis or plane, hides widgets that aren't participating in the current
transformation, and illustrates the angle of difference between the original and
updated rotation.) At a minimum, we should indicate the current widget being
manipulated with a color change (like we already do when the widget is being
hovered). This requires a bit of additional state management effort but
shouldn't be overly difficult to add in a future PR.

### Better visual representation for rotation widgets

Currently, each axis of rotation is represented on the gizmo with a full-circle,
unlit "ring" shape. This can make it difficult to tell which half of the ring is
closer to the viewer, and thus to get an accurate understanding of how the
transform is currently oriented, without moving the camera around. A [previous
version of this work](#4) bisected the rings along a view-oriented plane and
rendered the "back-side" ring halves with reduced opacity. This PR uses static
meshes instead of an immediate-mode drawing API to render the gizmos, so a
custom shader would be the ideal way to reproduce that effect. That effort
should be deferred until after upgrading to Bevy 0.12, as it brings some changes
which would likely require some updates to that code.

### Better visual representation for translation arrows

A [previous version of this work](#4) faded the opacity of the translation
arrows when they were very close to parallel with the view direction — an idea
that was borrowed from Blender. It's a nice UX enhancement because translating
along an axis that's very close to parallel with the view direction can be janky
and error-prone, so it makes sense to disallow it and instead provide an
unobstructed view of the screen-space translation widget. This would also
require a custom shader, in addition to some extra state management logic (to
disable the widgets when their opacity is zeroed out). Given that it's only a
"nice-to-have," I think it makes sense to backlog this for the time being.

## Known Issues

### Picking

There's currently a bug in `bevy_mod_picking` that affects the hit-testing of
the gizmo widgets. The gizmos are currently _rendering_ on top of everything
else (via a second camera and render-layer configurations), but the picking
behavior doesn't take the rendering order into account. This means that portions
of the gizmo widgets which are occluded by geometry in the world cannot be
interacted with (because the occluding geometry interrupts the picking raycast).

> Update: This is fixed in the new release of `bevy_mod_picking` for Bevy 0.12.

### Delay on first-render

The first time a new widget shape is spawned, there's a noticeable delay (of 1
to several seconds) before the widget is rendered, during which the UI becomes
unresponsive. This is likely the same issue that triggers a much longer delay
when the glTF scene is being spawned. I'd like to see if Bevy 0.12 resolves or
mitigates this issue before addressing it on our end, but if it doesn't, I think
we can simply spawn an instance of each of the gizmo widgets off-screen on
application startup to prevent lag spikes from happening while a user is
interacting with the scene.

### Non-deterministic hover states

The widget colors are currently being updated by, e.g., multiplying on
mouser-over and dividing on mouse-out. Occasionally those events happen in quick
enough succession that our mouse-out listener is not invoked, so a widget gets
"stuck" in its hovered state. The fix for this is trivial but fairly annoying,
so I haven't gotten around to it yet. 🙂

> Update: This issue mostly occurs when in world-space mode. The gizmo is torn
> down and re-built from scratch once a drag event completes, which can despawn
> the gizmo while an element is still hovered. The solution will likely involve
> completely separate materials for default and hover states, similar to how
> `bevy_mod_picking`'s highlight plugin works.

### Object Selection

There's still some jank happening with object selection and camera orbiting, as
mentioned in #8. I don't anticipate this being overly difficult to resolve, but
I'm deferring that work until more of the core functionality is built out since
it's not a blocker for now.

### Skinned Mesh Selection

There's also still the issue of the skinned mesh being unselectable — which, it
turns out, is [technically not actually the
case](https://github.com/bevyengine/bevy/issues/4971). Rather, the picking
raycast "sees" the mesh as if it were still in its original rest pose, because
the mesh deformations are processed on the GPU and not reflected back to the
CPU-side representation.

I think the ideal workaround for this will be to attach capsule-shaped Rapier
colliders to the skeleton (similar to Unreal Engine's auto-generated "physics
assets" for skeletal meshes) and use those for picking instead. This would
automatically enable skeletal pose manipulation (by transforming the individual
joints), which is already a long term goal. It also makes more sense from a
practical standpoint, as the mesh itself cannot be independently transformed
while it's bound to the skeleton, so there's little point in directly selecting
it.
2023-11-10 15:51:17 -05:00
Danny McGee edbc1fa30f Debug toggling (#9)
#8 introduced some additional debug information to the view, which was already
rendering some information and visualizations which were not necessary relevant
to the end-user experience. This PR adds an input action (bound to Ctrl + `) to
toggle the display of those visualizations, and disables them by default.
2023-11-02 15:25:14 -04:00
Danny McGee 06751e54f6 Object picking (#8)
This PR implements basic object selection, with help from `bevy_mod_picking` and
`bevy_mod_outline`.

### Work Done
 * Click to select objects in the world
 * Selected objects become visually highlighted
 * The selected entity is available globally on the `Res<Selection>` resource
 * Selected entities can also be queried via the `Selected` marker component
 * Pressing `F` will "focus" the camera on the selected entity
 * Pressing `Esc` will clear the active selection

### Known Issues
 * We're currently using `bevy_mod_picking`'s "Selection" feature, which isn't 
   aware of our own input events. As a consequence, it will select the object
   under the cursor when releasing `LMB` after orbiting the camera, which is not
   what we want. This should be pretty easily fixable by dropping
   `bevy_mod_picking`'s selection feature and reading the object under the
   cursor in our own click listener that only runs if the LMB event is
   unhandled.
 * The skinned mesh is not currently selectable. This is likely fixable by
   adjusting the logic in `scene::mark_scene_objects`... somehow. The `Gltf`
   data structure is kind of a nightmare to work with, so this will take some
   investigation.

### Future Enhancements
 * For parity with other DCC apps, the "Focus" action should also adjust the
   camera zoom level to "frame" the selected object in the view. Punting on that
   for now because I'm not super confident about the math involved.
 * Group selection with Shift/Ctrl and/or marquee selection would be really nice
   to have, but probably not critical for now.
2023-11-02 13:32:58 -04:00
Danny McGee c84fd31387 UI infrastructure and simple "Help" dialog (#3)
Sets up some WIP infrastructure for building out the UI, and adds a simple popup
to show the navigation controls for the app.
2023-10-09 22:19:58 -04:00
Danny McGee 82157bd54a Document skybox generation process 2023-10-03 17:08:21 -04:00
Danny McGee 2e3979b336 Sync Bevy canvas size with browser viewport size 2023-09-29 22:15:18 -04:00
Danny McGee c1f92cc2d6 Spawn Bevy canvas at full viewport size 2023-09-29 20:36:23 -04:00
Danny McGee bed97cff47 Rename projects 2023-09-29 18:33:00 -04:00