From b92081d06ebea3ca25b32b974ef18b42e4f51e20 Mon Sep 17 00:00:00 2001 From: Jan Hohenheim Date: Tue, 23 Jul 2024 23:42:25 +0200 Subject: [PATCH] fix(Blenvy:Bevy): Fix direct file access for gltf preload on Wasm (#199) * Fix direct file access * Fix dropped handles * Remove debug messages * Minor refactoring * Fix access --- crates/blenvy/src/blueprints/mod.rs | 13 ++-- .../src/blueprints/spawn_from_blueprints.rs | 63 +++++++++++++++++-- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/crates/blenvy/src/blueprints/mod.rs b/crates/blenvy/src/blueprints/mod.rs index 4a1c2d2..2d1ade6 100644 --- a/crates/blenvy/src/blueprints/mod.rs +++ b/crates/blenvy/src/blueprints/mod.rs @@ -49,16 +49,14 @@ impl Default for BluePrintBundle { #[derive(Debug, Clone)] /// Plugin for gltf blueprints -pub struct BlueprintsPlugin { -} +pub struct BlueprintsPlugin {} impl Default for BlueprintsPlugin { fn default() -> Self { - Self { } + Self {} } } - fn hot_reload(watching_for_changes: Res) -> bool { // println!("hot reload ? {}", watching_for_changes.0); watching_for_changes.0 @@ -110,6 +108,8 @@ impl Plugin for BlueprintsPlugin { .register_type::>() .register_type::() .register_type::>>() + .init_asset::() + .init_asset_loader::() .configure_sets( Update, (GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn) @@ -119,6 +119,7 @@ impl Plugin for BlueprintsPlugin { .add_systems( Update, ( + load_raw_gltf, blueprints_prepare_spawn, blueprints_check_assets_loading, blueprints_assets_loaded, @@ -132,16 +133,14 @@ impl Plugin for BlueprintsPlugin { .chain() .in_set(GltfBlueprintsSet::Spawn), ) - // animation .add_systems( Update, ( trigger_blueprint_animation_markers_events, - trigger_instance_animation_markers_events + trigger_instance_animation_markers_events, ), ) - // hot reload .add_systems(Update, react_to_asset_changes.run_if(hot_reload)); } diff --git a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs index 67b9c8a..dd8084f 100644 --- a/crates/blenvy/src/blueprints/spawn_from_blueprints.rs +++ b/crates/blenvy/src/blueprints/spawn_from_blueprints.rs @@ -1,6 +1,12 @@ use std::path::Path; -use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashMap}; +use bevy::{ + asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, + gltf::Gltf, + prelude::*, + scene::SceneInstance, + utils::hashbrown::HashMap, +}; use serde_json::Value; use crate::{ @@ -115,17 +121,59 @@ Overview of the Blueprint Spawning process => distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ?? */ -pub(crate) fn blueprints_prepare_spawn( +#[derive(Asset, TypePath, Debug)] +pub struct RawGltfAsset(pub RawGltf); + +#[derive(Default)] +pub(super) struct RawGltfAssetLoader; + +impl AssetLoader for RawGltfAssetLoader { + type Asset = RawGltfAsset; + type Settings = (); + type Error = gltf::Error; + + async fn load<'a>( + &'a self, + reader: &'a mut Reader<'_>, + _settings: &'a (), + _load_context: &'a mut LoadContext<'_>, + ) -> Result { + let mut bytes = Vec::new(); + reader.read_to_end(&mut bytes).await?; + let gltf = RawGltf::from_slice_without_validation(&bytes)?; + Ok(RawGltfAsset(gltf)) + } +} + +#[derive(Debug, Component, Deref, DerefMut)] +#[component(storage = "SparseSet")] +pub(super) struct AssociatedRawGltfHandle(Handle); + +pub(super) fn load_raw_gltf( blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added>, + asset_server: Res, + mut commands: Commands, +) { + for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() { + let gltf_handle: Handle = asset_server.load(&blueprint_info.path); + commands + .entity(entity) + .insert(AssociatedRawGltfHandle(gltf_handle)); + } +} + +pub(super) fn blueprints_prepare_spawn( + blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo, &AssociatedRawGltfHandle)>, mut commands: Commands, asset_server: Res, // for hot reload watching_for_changes: Res, mut assets_to_blueprint_instances: ResMut, + raw_gltf_assets: Res>, // for debug // all_names: Query<&Name> ) { - for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() { + for (entity, blueprint_info, raw_gltf_handle) in blueprint_instances_to_spawn.iter() { info!( "BLUEPRINT: to spawn detected: {:?} path:{:?}", blueprint_info.name, blueprint_info.path @@ -149,7 +197,9 @@ pub(crate) fn blueprints_prepare_spawn( // and we also add all its assets /* prefetch attempt */ - let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap(); + let Some(RawGltfAsset(gltf)) = raw_gltf_assets.get(&raw_gltf_handle.0) else { + continue; + }; for scene in gltf.scenes() { if let Some(scene_extras) = scene.extras().clone() { let lookup: HashMap = @@ -254,7 +304,10 @@ pub(crate) fn blueprints_prepare_spawn( .entity(entity) .insert(bevy::prelude::Name::from(blueprint_info.name.clone())); // add the blueprint spawning marker - commands.entity(entity).insert(BlueprintSpawning); + commands + .entity(entity) + .insert(BlueprintSpawning) + .remove::(); } }