mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-18 00:23:14 +00:00
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.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
use bevy::{
|
||||
pbr::NotShadowCaster,
|
||||
prelude::*,
|
||||
render::render_resource::{AsBindGroup, ShaderRef},
|
||||
};
|
||||
|
||||
use crate::camera_controller::{CameraController, CameraMotionSystem};
|
||||
|
||||
pub struct WorldGridPlugin;
|
||||
|
||||
impl Plugin for WorldGridPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
|
||||
.add_systems(Startup, spawn_world_grid)
|
||||
.add_systems(PostUpdate, move_plane_with_camera.after(CameraMotionSystem));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct WorldGridPlane;
|
||||
|
||||
#[derive(Asset, AsBindGroup, TypePath, Clone)]
|
||||
struct ProceduralGridMaterial {}
|
||||
|
||||
impl Material for ProceduralGridMaterial {
|
||||
fn fragment_shader() -> ShaderRef {
|
||||
"shaders/procedural_grid.wgsl".into()
|
||||
}
|
||||
|
||||
fn alpha_mode(&self) -> AlphaMode {
|
||||
AlphaMode::Blend
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_world_grid(
|
||||
mut cmd: Commands,
|
||||
mut ra_meshes: ResMut<Assets<Mesh>>,
|
||||
mut ra_mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
|
||||
) {
|
||||
let plane = ra_meshes.add(Mesh::from(shape::Plane {
|
||||
size: 200.0,
|
||||
subdivisions: 0,
|
||||
}));
|
||||
let proc_grid = ra_mat_proc_grid.add(ProceduralGridMaterial {});
|
||||
|
||||
cmd.spawn((
|
||||
Name::new("World Grid"),
|
||||
SpatialBundle::from_transform(Transform::IDENTITY),
|
||||
WorldGridPlane,
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
MaterialMeshBundle {
|
||||
mesh: plane.clone(),
|
||||
material: proc_grid.clone(),
|
||||
transform: Transform::IDENTITY,
|
||||
..default()
|
||||
},
|
||||
NotShadowCaster,
|
||||
));
|
||||
parent.spawn((
|
||||
MaterialMeshBundle {
|
||||
mesh: plane,
|
||||
material: proc_grid,
|
||||
transform: Transform::IDENTITY.looking_to(Vec3::Z, Vec3::NEG_Y),
|
||||
..default()
|
||||
},
|
||||
NotShadowCaster,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
fn move_plane_with_camera(
|
||||
mut plane: Query<(&WorldGridPlane, &mut Transform)>,
|
||||
camera: Query<&CameraController, Changed<CameraController>>,
|
||||
) {
|
||||
if let Ok(&CameraController { focus, .. }) = camera.get_single() {
|
||||
let (_, mut xform) = plane.single_mut();
|
||||
|
||||
xform.translation.x = focus.x;
|
||||
xform.translation.z = focus.z;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user