mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
Feature flag, conditional compilation attributes
This commit is contained in:
@@ -34,6 +34,8 @@ web-sys = { version = "0.3.65", optional = true, features = [
|
|||||||
] }
|
] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = []
|
||||||
|
headless = []
|
||||||
wasm = [
|
wasm = [
|
||||||
"dep:console_error_panic_hook",
|
"dep:console_error_panic_hook",
|
||||||
"dep:js-sys",
|
"dep:js-sys",
|
||||||
|
|||||||
+6
-4
@@ -9,13 +9,15 @@
|
|||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"executor": "@nxrs/cargo:build",
|
"executor": "@nxrs/cargo:build",
|
||||||
"inputs": ["assets"],
|
"options": {},
|
||||||
"options": {
|
|
||||||
"release": false
|
|
||||||
},
|
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
"release": true
|
"release": true
|
||||||
|
},
|
||||||
|
"headless": {
|
||||||
|
"bin": "studio-standalone",
|
||||||
|
"release": true,
|
||||||
|
"features": "headless"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+31
-10
@@ -1,29 +1,34 @@
|
|||||||
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_picking::DefaultPickingPlugins;
|
|
||||||
use camera_controller::CameraControllerPlugin;
|
|
||||||
use debug::DebugPlugin;
|
|
||||||
use input::StudioInputPlugin;
|
|
||||||
use interaction::InteractionPlugin;
|
|
||||||
use math::InterpolationPlugin;
|
|
||||||
use scene::ScenePlugin;
|
|
||||||
use skybox::SkyboxPlugin;
|
|
||||||
use ui::UiLayerPlugin;
|
|
||||||
use viewport::ViewportSize;
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod camera_controller;
|
mod camera_controller;
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod debug;
|
mod debug;
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod design_system;
|
mod design_system;
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod input;
|
mod input;
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod interaction;
|
mod interaction;
|
||||||
mod math;
|
mod math;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod skybox;
|
mod skybox;
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
mod ui;
|
mod ui;
|
||||||
mod viewport;
|
mod viewport;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
|
use crate::{
|
||||||
|
camera_controller::CameraControllerPlugin, debug::DebugPlugin, input::StudioInputPlugin,
|
||||||
|
interaction::InteractionPlugin, ui::UiLayerPlugin,
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
math::InterpolationPlugin, scene::ScenePlugin, skybox::SkyboxPlugin, viewport::ViewportSize,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
mod wasm;
|
mod wasm;
|
||||||
|
|
||||||
@@ -40,6 +45,7 @@ pub fn init(viewport_size: ViewportSize) {
|
|||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
app.add_plugins(viewport::wasm::ViewportPlugin);
|
app.add_plugins(viewport::wasm::ViewportPlugin);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
DefaultPlugins.set(WindowPlugin {
|
DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
@@ -61,4 +67,19 @@ pub fn init(viewport_size: ViewportSize) {
|
|||||||
UiLayerPlugin,
|
UiLayerPlugin,
|
||||||
))
|
))
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
#[cfg(feature = "headless")]
|
||||||
|
app.add_plugins((
|
||||||
|
bevy::log::LogPlugin::default(),
|
||||||
|
bevy::core::TaskPoolPlugin::default(),
|
||||||
|
bevy::core::TypeRegistrationPlugin,
|
||||||
|
bevy::time::TimePlugin,
|
||||||
|
bevy::transform::TransformPlugin,
|
||||||
|
bevy::hierarchy::HierarchyPlugin,
|
||||||
|
bevy::diagnostic::DiagnosticsPlugin,
|
||||||
|
InterpolationPlugin,
|
||||||
|
ScenePlugin,
|
||||||
|
SkyboxPlugin,
|
||||||
|
))
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ pub use traits::*;
|
|||||||
mod ecs;
|
mod ecs;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Easing {
|
pub enum Easing {
|
||||||
Linear,
|
Linear,
|
||||||
Sine,
|
Sine,
|
||||||
SineOut,
|
SineOut,
|
||||||
#[allow(dead_code)]
|
|
||||||
SineIn,
|
SineIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+62
-42
@@ -1,35 +1,43 @@
|
|||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::LoadState,
|
asset::LoadState,
|
||||||
|
gltf,
|
||||||
|
pbr::NotShadowCaster,
|
||||||
|
reflect::{TypePath, TypeUuid},
|
||||||
|
render::render_resource::{AsBindGroup, ShaderRef},
|
||||||
|
utils::HashSet,
|
||||||
|
};
|
||||||
|
use bevy::{
|
||||||
core_pipeline::{
|
core_pipeline::{
|
||||||
bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings},
|
bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings},
|
||||||
fxaa::Fxaa,
|
fxaa::Fxaa,
|
||||||
tonemapping::Tonemapping,
|
tonemapping::Tonemapping,
|
||||||
},
|
},
|
||||||
gltf::{self, Gltf},
|
gltf::Gltf,
|
||||||
math::vec3,
|
math::vec3,
|
||||||
pbr::NotShadowCaster,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::{TypePath, TypeUuid},
|
|
||||||
render::render_resource::{AsBindGroup, ShaderRef},
|
|
||||||
utils::HashSet,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
use bevy_mod_picking::PickableBundle;
|
use bevy_mod_picking::PickableBundle;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
use crate::{
|
use crate::{
|
||||||
camera_controller::{CameraController, CameraControllerBundle, CameraMotionSystem},
|
camera_controller::{CameraController, CameraControllerBundle, CameraMotionSystem},
|
||||||
interaction::Selectable,
|
interaction::Selectable,
|
||||||
skybox::SkyboxId,
|
|
||||||
MainCamera,
|
|
||||||
};
|
};
|
||||||
|
use crate::{skybox::SkyboxId, MainCamera};
|
||||||
|
|
||||||
pub struct ScenePlugin;
|
pub struct ScenePlugin;
|
||||||
|
|
||||||
impl Plugin for ScenePlugin {
|
impl Plugin for ScenePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(ClearColor(Color::hsl(0.0, 0.0, 0.25)))
|
app.insert_resource(ClearColor(Color::hsl(0.0, 0.0, 0.25)))
|
||||||
.insert_resource(Msaa::Off)
|
.add_systems(Startup, initialize);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
|
app.insert_resource(Msaa::Off)
|
||||||
.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
|
.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
|
||||||
.add_systems(Startup, initialize)
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
mark_scene_objects.run_if(
|
mark_scene_objects.run_if(
|
||||||
@@ -45,6 +53,7 @@ impl Plugin for ScenePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct WorldGridPlane;
|
struct WorldGridPlane;
|
||||||
|
|
||||||
@@ -57,8 +66,8 @@ struct Inspectable;
|
|||||||
fn initialize(
|
fn initialize(
|
||||||
mut cmd: Commands,
|
mut cmd: Commands,
|
||||||
assets: Res<AssetServer>,
|
assets: Res<AssetServer>,
|
||||||
mut ra_meshes: ResMut<Assets<Mesh>>,
|
#[cfg(not(feature = "headless"))] mut ra_meshes: ResMut<Assets<Mesh>>,
|
||||||
mut ra_mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
|
#[cfg(not(feature = "headless"))] mut ra_mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
|
||||||
) {
|
) {
|
||||||
// Skybox
|
// Skybox
|
||||||
cmd.insert_resource(SkyboxId("test_scene".into()));
|
cmd.insert_resource(SkyboxId("test_scene".into()));
|
||||||
@@ -89,6 +98,7 @@ fn initialize(
|
|||||||
},
|
},
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
CameraControllerBundle::new(focus, camera_xform.translation),
|
CameraControllerBundle::new(focus, camera_xform.translation),
|
||||||
BloomSettings {
|
BloomSettings {
|
||||||
composite_mode: BloomCompositeMode::EnergyConserving,
|
composite_mode: BloomCompositeMode::EnergyConserving,
|
||||||
@@ -106,6 +116,7 @@ fn initialize(
|
|||||||
// TODO: get Blender to export enough metadata to automate light placements
|
// TODO: get Blender to export enough metadata to automate light placements
|
||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("Ceiling Light"),
|
Name::new("Ceiling Light"),
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
Selectable,
|
Selectable,
|
||||||
Inspectable,
|
Inspectable,
|
||||||
PointLightBundle {
|
PointLightBundle {
|
||||||
@@ -124,6 +135,7 @@ fn initialize(
|
|||||||
// Monitor glow
|
// Monitor glow
|
||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("Monitor Glow"),
|
Name::new("Monitor Glow"),
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
Selectable,
|
Selectable,
|
||||||
Inspectable,
|
Inspectable,
|
||||||
PointLightBundle {
|
PointLightBundle {
|
||||||
@@ -140,43 +152,48 @@ fn initialize(
|
|||||||
));
|
));
|
||||||
|
|
||||||
// Plane
|
// Plane
|
||||||
let plane = ra_meshes.add(Mesh::from(shape::Plane {
|
#[cfg(not(feature = "headless"))]
|
||||||
size: 200.0,
|
{
|
||||||
subdivisions: 0,
|
let plane = ra_meshes.add(Mesh::from(shape::Plane {
|
||||||
}));
|
size: 200.0,
|
||||||
let proc_grid = ra_mat_proc_grid.add(ProceduralGridMaterial {});
|
subdivisions: 0,
|
||||||
|
}));
|
||||||
|
let proc_grid = ra_mat_proc_grid.add(ProceduralGridMaterial {});
|
||||||
|
|
||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("World Grid"),
|
Name::new("World Grid"),
|
||||||
SpatialBundle::from_transform(Transform::IDENTITY),
|
SpatialBundle::from_transform(Transform::IDENTITY),
|
||||||
WorldGridPlane,
|
WorldGridPlane,
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
MaterialMeshBundle {
|
MaterialMeshBundle {
|
||||||
mesh: plane.clone(),
|
mesh: plane.clone(),
|
||||||
material: proc_grid.clone(),
|
material: proc_grid.clone(),
|
||||||
transform: Transform::IDENTITY,
|
transform: Transform::IDENTITY,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
NotShadowCaster,
|
NotShadowCaster,
|
||||||
));
|
));
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
MaterialMeshBundle {
|
MaterialMeshBundle {
|
||||||
mesh: plane,
|
mesh: plane,
|
||||||
material: proc_grid,
|
material: proc_grid,
|
||||||
transform: Transform::IDENTITY.looking_to(Vec3::Z, Vec3::NEG_Y),
|
transform: Transform::IDENTITY.looking_to(Vec3::Z, Vec3::NEG_Y),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
NotShadowCaster,
|
NotShadowCaster,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
fn gltf_loaded(assets: Res<AssetServer>, gltf: Res<NewGltf>) -> bool {
|
fn gltf_loaded(assets: Res<AssetServer>, gltf: Res<NewGltf>) -> bool {
|
||||||
assets.get_load_state(&**gltf) == LoadState::Loaded
|
assets.get_load_state(&**gltf) == LoadState::Loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
fn gltf_scene_spawned(
|
fn gltf_scene_spawned(
|
||||||
r_assets: Res<AssetServer>,
|
r_assets: Res<AssetServer>,
|
||||||
r_gltf: Res<NewGltf>,
|
r_gltf: Res<NewGltf>,
|
||||||
@@ -200,6 +217,7 @@ fn gltf_scene_spawned(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
fn mark_scene_objects(
|
fn mark_scene_objects(
|
||||||
mut cmd: Commands,
|
mut cmd: Commands,
|
||||||
r_gltf: Res<NewGltf>,
|
r_gltf: Res<NewGltf>,
|
||||||
@@ -255,7 +273,6 @@ fn mark_scene_objects(
|
|||||||
})
|
})
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
|
||||||
// If the sets match, this is the entity that represents the glTF mesh
|
// If the sets match, this is the entity that represents the glTF mesh
|
||||||
if prims_from_gltf == prims_from_ecs {
|
if prims_from_gltf == prims_from_ecs {
|
||||||
cmd.entity(ent_parent).insert(Selectable);
|
cmd.entity(ent_parent).insert(Selectable);
|
||||||
@@ -271,6 +288,7 @@ fn mark_scene_objects(
|
|||||||
cmd.remove_resource::<NewGltf>();
|
cmd.remove_resource::<NewGltf>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
fn move_plane_with_camera(
|
fn move_plane_with_camera(
|
||||||
mut plane: Query<(&WorldGridPlane, &mut Transform)>,
|
mut plane: Query<(&WorldGridPlane, &mut Transform)>,
|
||||||
camera: Query<&CameraController, Changed<CameraController>>,
|
camera: Query<&CameraController, Changed<CameraController>>,
|
||||||
@@ -283,10 +301,12 @@ fn move_plane_with_camera(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
#[derive(AsBindGroup, Clone, TypePath, TypeUuid)]
|
#[derive(AsBindGroup, Clone, TypePath, TypeUuid)]
|
||||||
#[uuid = "CE331A13-F247-4F5B-A75E-670B2BD5776A"]
|
#[uuid = "CE331A13-F247-4F5B-A75E-670B2BD5776A"]
|
||||||
struct ProceduralGridMaterial {}
|
struct ProceduralGridMaterial {}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "headless"))]
|
||||||
impl Material for ProceduralGridMaterial {
|
impl Material for ProceduralGridMaterial {
|
||||||
fn fragment_shader() -> ShaderRef {
|
fn fragment_shader() -> ShaderRef {
|
||||||
"shaders/procedural_grid.wgsl".into()
|
"shaders/procedural_grid.wgsl".into()
|
||||||
|
|||||||
Reference in New Issue
Block a user