#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.
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.
### New `math` module
* Traits for error-tolerant floating-point comparisons
* Traits for interpolation and easing
* Bevy plugin to manage 3D interpolations with ECS components
### `skybox` module refactor
* ECS resource to enable external skybox selection/updates
* System run conditions for more idiomatic/ECS-friendly control flow
### Camera controller refactor
* Renamed from `orbit_cam` to `camera_controller`
* Now delegates to the new interpolation plugin for WASD motion smoothing
* Simple API for attaching the `CameraController` component to the camera from
another module -- this resolves an awkward separation-of-concerns situation
where we had to configure a bunch of render-quality settings in the camera
controller module
### Scene module refactor
* Renamed from `test_scene` to `scene`
* This module is now responsible for configuring the skybox
* This module is now responsible for spawning the camera and configuring the
render settings
Adds `Shift` as an alternate modifier for FPS-style camera rotation, and binds
wheel events to camera zoom/dolly.
An attempt was made to translate 2D scroll events on a touchpad to camera
panning (this is what Blender does, and it's smooth as butter), but Bevy and/or
`winit` and/or the browser is doing some weird preprocessing of those events
before we're able to read them, which makes that unfeasible for now. That issue
has been documented with a `FIXME` comment.
This PR adds FPS-style controls to the camera in addition to the existing DCC-style pan/orbit/dolly controls. Additionally, some architectural changes have been made to facilitate this and pave the way toward making all of the app controls configurable in the future. Namely, a new `input` module has been added, loosely inspired by Unreal Engine's "Enhanced Input" system (and as I understand it, conceptually similar to Unity's "new" input system as well).
The basic idea is that raw device inputs (coming from `bevy::input`) are mapped to named, app-specific "input actions" before being consumed by other parts of the application. For example, in the camera motion system, instead of checking for mouse motion while the middle mouse button is pressed, we now check for a `CameraMotion::Pan` input action event.
Input actions carry information about their lifecycle phase (`Start`, `Ongoing`, and `Stop` — a stand-in for Bevy's `just_pressed`, `pressed`, and `just_released` methods) and some type of magnitude (`f32`, `Vec2`, or `Vec3` depending on the action).
At present, we've simply moved the hard-coded device input checks from the `orbit_cam` module to the new `input` module, but theoretically, this could eventually be refactored to read the mappings between device inputs and input actions from some kind of user configuration.