Upgrade to Bevy v0.12 (#12)

* Migrate `System::pipe(...)` calls to `System::map(...)`
* Migrate `EventReader::iter()` and `EventReader::into_iter()` calls to
  `EventReader::read()`
* Migrate asset handling
* Generate `*.meta` files for assets
* Migrate a shader import
* Fix emissive materials double-applying their emissive strength
* Fix non-normalized bone weights resulting in incorrect vertex positions
* Set shadow filtering to `Hardware2x2` to mitigate increase in shader
  compilation times
This commit is contained in:
Danny McGee
2023-11-22 23:05:42 -05:00
committed by GitHub
parent 8bf4abc3a4
commit 155272a5ba
148 changed files with 15479 additions and 16519 deletions
+3 -3
View File
@@ -85,7 +85,7 @@ fn camera_control_kinematic(
let mut any_started = false;
let mut any_stopped = false;
for action in input.iter().filter(|action| {
for action in input.read().filter(|action| {
!matches!(
action,
InputAction(_, Action::Camera(CameraMotion::Translate(_)))
@@ -123,7 +123,7 @@ fn process_physical_inputs(
q_camera: Query<(Entity, &Velocity), With<CameraController>>,
mut q_interp: Query<&mut InterpVelocity>,
) {
for action in input.iter() {
for action in input.read() {
let &InputAction(_, Action::Camera(CameraMotion::Translate(delta))) = action else {
continue;
};
@@ -162,7 +162,7 @@ fn process_focus_inputs(
mut q_interp_pos: Query<&mut InterpPosition>,
q_selected_xform: Query<&GlobalTransform, With<Selected>>,
) {
if input.iter().any(|action| {
if input.read().any(|action| {
matches!(
action,
InputAction(Lifecycle::Stop, Action::Selection(Selection::Focus))
+1 -1
View File
@@ -41,7 +41,7 @@ impl Plugin for DebugPlugin {
fn toggle_debug_mode(mut input: EventReader<InputAction>, mut r_debug: ResMut<DebugMode>) {
if input
.iter()
.read()
.any(|action| matches!(action, InputAction(Lifecycle::Stop, Action::ToggleDebug)))
{
**r_debug = !**r_debug;
+2 -2
View File
@@ -252,7 +252,7 @@ fn translate_fps_camera_events(
}
// Wheel zoom
for &MouseWheel { y, .. } in mouse_wheel.iter() {
for &MouseWheel { y, .. } in mouse_wheel.read() {
// info!("wheel: ({x}, {y}) [{unit:?}]");
// let rem_x = (100. / x).abs() % 1.;
// let rem_y = (100. / y).abs() % 1.;
@@ -288,6 +288,6 @@ fn translate_fps_camera_events(
#[inline]
fn read_mouse_delta(mut mouse_motion: EventReader<MouseMotion>) -> Vec2 {
mouse_motion
.into_iter()
.read()
.fold(Vec2::ZERO, |accum, current| accum + current.delta)
}
+3 -3
View File
@@ -20,7 +20,7 @@ impl Plugin for SelectionPlugin {
app.add_systems(
PostUpdate,
wasm::notify_entity_selection_change
.pipe(error)
.map(bevy::utils::error)
.run_if(resource_changed_or_removed::<Selection>()),
);
}
@@ -47,7 +47,7 @@ fn update_selection(
q_selectable: Query<&Selectable>,
q_selected: Query<Entity, With<Selected>>,
) {
if let Some(event) = ev_select.iter().last() {
if let Some(event) = ev_select.read().last() {
// Clear any existing `Selected` components
for ent in q_selected.iter() {
cmd.entity(ent).remove::<Selected>();
@@ -73,7 +73,7 @@ fn update_selection(
} else {
cmd.remove_resource::<Selection>();
}
} else if ev_input.iter().any(|action| {
} else if ev_input.read().any(|action| {
matches!(
action,
InputAction(Lifecycle::Stop, Action::Selection(input::Selection::Clear))
+16 -7
View File
@@ -41,15 +41,24 @@ pub fn init(viewport_size: ViewportSize) {
app.add_plugins(viewport::wasm::ViewportPlugin);
app.add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: viewport_size.into(),
title: "Storyteller Studio".into(),
canvas: Some("#studio_canvas".into()),
DefaultPlugins
// TODO: To generate asset .meta files (to prevent 404 errors on the
// web), it's currently necessary to uncomment the following
// block and run the app with this command:
// > cargo run -p studio --features bevy/asset_processor,bevy/tonemapping_luts
// .set(AssetPlugin {
// mode: AssetMode::Processed,
// ..default()
// })
.set(WindowPlugin {
primary_window: Some(Window {
resolution: viewport_size.into(),
title: "Storyteller Studio".into(),
canvas: Some("#studio_canvas".into()),
..default()
}),
..default()
}),
..default()
}),
DefaultPickingPlugins,
DebugPlugin,
InteractionPlugin,
+71 -30
View File
@@ -1,5 +1,4 @@
use bevy::{
asset::LoadState,
core_pipeline::{
bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings},
fxaa::Fxaa,
@@ -7,9 +6,9 @@ use bevy::{
},
gltf::{self, Gltf},
math::vec3,
pbr::NotShadowCaster,
pbr::{NotShadowCaster, ShadowFilteringMethod},
prelude::*,
reflect::{TypePath, TypeUuid},
reflect::TypePath,
render::render_resource::{AsBindGroup, ShaderRef},
utils::HashSet,
};
@@ -30,18 +29,29 @@ impl Plugin for ScenePlugin {
.insert_resource(Msaa::Off)
.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
.add_systems(Startup, initialize)
.add_systems(
PreUpdate,
spawn_new_gltf_scene.run_if(
resource_exists::<NewGltf>()
.and_then(new_gltf_loaded)
.and_then(run_once()),
),
)
.add_systems(
Update,
mark_scene_objects.run_if(
resource_exists::<NewGltf>()
.and_then(gltf_loaded)
.and_then(new_gltf_loaded)
.and_then(gltf_scene_spawned),
),
)
.add_systems(PostUpdate, move_plane_with_camera.after(CameraMotionSystem));
#[cfg(feature = "wasm")]
app.add_systems(PostUpdate, wasm::notify_entity_spawn_changes.pipe(error));
app.add_systems(
PostUpdate,
wasm::notify_entity_spawn_changes.map(bevy::utils::error),
);
}
}
@@ -65,14 +75,6 @@ fn initialize(
// glTF scene
cmd.insert_resource(NewGltf(assets.load("gltf/sample-room.gltf")));
cmd.spawn((
Name::new("Scene"),
Inspectable,
SceneBundle {
scene: assets.load("gltf/sample-room.gltf#Scene0"),
..default()
},
));
// Camera, graphics settings
let focus = vec3(0.35011, 0.5, -0.99576);
@@ -90,6 +92,7 @@ fn initialize(
..default()
},
CameraControllerBundle::new(focus, camera_xform.translation),
ShadowFilteringMethod::Hardware2x2,
BloomSettings {
composite_mode: BloomCompositeMode::EnergyConserving,
intensity: 0.25,
@@ -173,27 +176,66 @@ fn initialize(
});
}
fn gltf_loaded(assets: Res<AssetServer>, gltf: Res<NewGltf>) -> bool {
assets.get_load_state(&**gltf) == LoadState::Loaded
#[derive(Default)]
struct LoadState(Handle<Gltf>, bool);
fn new_gltf_loaded(
r_gltf: Res<NewGltf>,
ra_gltfs: Res<Assets<Gltf>>,
mut er_scene_events: EventReader<AssetEvent<Scene>>,
mut l_loaded: Local<LoadState>,
) -> bool {
if l_loaded.0.path() != r_gltf.path() {
*l_loaded = LoadState(r_gltf.clone(), false);
} else if l_loaded.1 {
return true;
}
l_loaded.1 = er_scene_events.read().any(|event| match event {
AssetEvent::LoadedWithDependencies { id } => {
let gltf = ra_gltfs.get(&**r_gltf).unwrap();
let Some(default_scene) = &gltf.default_scene else {
return false;
};
*id == default_scene.id()
}
_ => false,
});
l_loaded.1
}
fn spawn_new_gltf_scene(mut cmd: Commands, ra_gltfs: Res<Assets<Gltf>>, r_gltf: Res<NewGltf>) {
let gltf = ra_gltfs.get(&**r_gltf).unwrap();
let Some(scene) = &gltf.default_scene else {
return;
};
cmd.spawn((
Name::new("Scene"),
Inspectable,
SceneBundle {
scene: scene.clone(),
..default()
},
));
}
fn gltf_scene_spawned(
r_assets: Res<AssetServer>,
r_gltf: Res<NewGltf>,
ra_gltfs: Res<Assets<Gltf>>,
q_scenes: Query<&Handle<Scene>, (With<Name>, With<Children>)>,
) -> bool {
let gltf = ra_gltfs.get(&r_gltf).unwrap();
let Some(gltf_scene_path) = gltf
.default_scene
.as_ref()
.and_then(|handle| r_assets.get_handle_path(handle))
else {
let gltf = ra_gltfs.get(&**r_gltf).unwrap();
let Some(gltf_scene_path) = gltf.default_scene.as_ref().and_then(|handle| handle.path()) else {
warn!("No default scene found for glTF: {:#?}", gltf);
return false;
};
q_scenes.iter().any(|handle| {
let Some(path) = r_assets.get_handle_path(handle) else {
let Some(path) = handle.path() else {
return false;
};
path == gltf_scene_path
@@ -203,14 +245,15 @@ fn gltf_scene_spawned(
fn mark_scene_objects(
mut cmd: Commands,
r_gltf: Res<NewGltf>,
r_assets: Res<AssetServer>,
ra_gltfs: Res<Assets<Gltf>>,
ra_gltf_nodes: Res<Assets<gltf::GltfNode>>,
ra_gltf_meshes: Res<Assets<gltf::GltfMesh>>,
q_parents: Query<(Entity, &Name, &Children), Without<Selectable>>,
q_primitives: Query<&Handle<Mesh>>,
) {
let gltf = ra_gltfs.get(&r_gltf).unwrap();
info!("mark_scene_objects");
let gltf = ra_gltfs.get(&**r_gltf).unwrap();
for (ent_parent, name, children) in q_parents.iter() {
if gltf.named_nodes.contains_key(&**name) {
@@ -241,7 +284,7 @@ fn mark_scene_objects(
let prims_from_gltf = gltf_mesh
.primitives
.iter()
.filter_map(|prim| r_assets.get_handle_path(&prim.mesh))
.filter_map(|prim| prim.mesh.path())
.collect::<HashSet<_>>();
// Collect all of the mesh handles in this entity's children
@@ -251,11 +294,10 @@ fn mark_scene_objects(
q_primitives
.get(*ent_child)
.ok()
.and_then(|handle| r_assets.get_handle_path(handle))
.and_then(|handle| handle.path())
})
.collect::<HashSet<_>>();
// If the sets match, this is the entity that represents the glTF mesh
if prims_from_gltf == prims_from_ecs {
cmd.entity(ent_parent).insert(Selectable);
@@ -283,8 +325,7 @@ fn move_plane_with_camera(
}
}
#[derive(AsBindGroup, Clone, TypePath, TypeUuid)]
#[uuid = "CE331A13-F247-4F5B-A75E-670B2BD5776A"]
#[derive(Asset, AsBindGroup, TypePath, Clone)]
struct ProceduralGridMaterial {}
impl Material for ProceduralGridMaterial {
+14 -3
View File
@@ -52,9 +52,20 @@ fn skybox_assets_loaded(
return false;
};
assets.get_load_state(skybox_assets.cubemap.clone_weak()) == LoadState::Loaded
&& assets.get_load_state(skybox_assets.env_diffuse.clone_weak()) == LoadState::Loaded
&& assets.get_load_state(skybox_assets.env_specular.clone_weak()) == LoadState::Loaded
let load_states = (
assets.get_load_state(skybox_assets.cubemap.clone_weak()),
assets.get_load_state(skybox_assets.env_diffuse.clone_weak()),
assets.get_load_state(skybox_assets.env_specular.clone_weak()),
);
matches!(
load_states,
(
Some(LoadState::Loaded),
Some(LoadState::Loaded),
Some(LoadState::Loaded),
)
)
}
fn spawn_skybox(
+1 -1
View File
@@ -78,7 +78,7 @@ pub mod wasm {
mut events: EventReader<ViewportResizeEvent>,
mut window: Query<&mut Window>,
) {
if let Some(event) = events.into_iter().last() {
if let Some(event) = events.read().last() {
let ViewportSize { width, height } = event.0;
window.single_mut().resolution.set(width, height);
}