feat(Blenvy): big overhaul, cleanup & fixed to the assets system
* now the blender side exports .meta.ron files in addition to the gltf files * these ron files contain the list of assets that are then preloaded on the Bevy side * removed the double loading of gltf files on the Bevy side, replaced with use of the new metadata/asset files * added bevy_common_assets/ ron as dependency for the file loading * big cleanup & partial restructure of the spawning steps * fixed premature removal of the BlueprintAssetsLoadState component that was leading to missing material gltf files in setups withouth hot reload * added OriginalVisibility component & logic to correctly reset the visibility of entities to what they where before the blueprint spawning * fixed a few not so visible issues with some components staying around after the blueprint instance has become "ready" * moved a number of component insertions to the new "get the assets list from the meta file" * also, loading speed feels faster ! (thanks to now loading the gltf files only once) * minor various tweaks & cleanups
This commit is contained in:
parent
0b038de584
commit
ee873b06f1
1
TODO.md
1
TODO.md
|
@ -339,5 +339,6 @@ Bevy Side:
|
||||||
- [ ] solving problems with scene renames
|
- [ ] solving problems with scene renames
|
||||||
- [ ] the ability to map external TEXT files to data in BLender (git-able, hand editable)
|
- [ ] the ability to map external TEXT files to data in BLender (git-able, hand editable)
|
||||||
- [x] make aabbs calculation non configurable, getting rid of the last setting (for now)
|
- [x] make aabbs calculation non configurable, getting rid of the last setting (for now)
|
||||||
|
- [ ] add information & screenshots about adding assets to the Blender add-on docs
|
||||||
|
|
||||||
clear && pytest -svv --blender-template ../../testing/bevy_example/art/testing_library.blend --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration_prepare.py && pytest -svv --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration.py
|
clear && pytest -svv --blender-template ../../testing/bevy_example/art/testing_library.blend --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration_prepare.py && pytest -svv --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration.py
|
|
@ -18,19 +18,7 @@ bevy = { version = "0.14", default-features = false, features = ["bevy_asset", "
|
||||||
serde = "1.0.188"
|
serde = "1.0.188"
|
||||||
ron = "0.8.1"
|
ron = "0.8.1"
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
gltf = { version = "1.4.0", default-features = false, features = [
|
bevy_common_assets = {version = "0.11", features = ["ron"]}
|
||||||
"KHR_lights_punctual",
|
|
||||||
"KHR_materials_transmission",
|
|
||||||
"KHR_materials_ior",
|
|
||||||
"KHR_materials_volume",
|
|
||||||
"KHR_materials_unlit",
|
|
||||||
"KHR_materials_emissive_strength",
|
|
||||||
"KHR_texture_transform",
|
|
||||||
"extras",
|
|
||||||
"extensions",
|
|
||||||
"names",
|
|
||||||
"utils",
|
|
||||||
] }
|
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn compute_scene_aabbs(
|
||||||
} else {
|
} else {
|
||||||
let aabb = compute_descendant_aabb(root_entity, &children, &existing_aabbs);
|
let aabb = compute_descendant_aabb(root_entity, &children, &existing_aabbs);
|
||||||
blenvy_config.aabb_cache.insert(name.to_string(), aabb);
|
blenvy_config.aabb_cache.insert(name.to_string(), aabb);
|
||||||
info!("generating aabb for {:?}", name);
|
info!("Step 7: generating aabb for {:?}", name);
|
||||||
commands
|
commands
|
||||||
.entity(root_entity)
|
.entity(root_entity)
|
||||||
.insert(aabb)
|
.insert(aabb)
|
||||||
|
|
|
@ -74,3 +74,26 @@ impl Default for BlueprintAssetsLoadState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for preloading asset files
|
||||||
|
#[derive(serde::Deserialize, bevy::asset::Asset, bevy::reflect::TypePath, Debug)]
|
||||||
|
pub(crate) struct File{
|
||||||
|
pub(crate) path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, bevy::asset::Asset, bevy::reflect::TypePath, Debug)]
|
||||||
|
pub(crate) struct BlueprintPreloadAssets{
|
||||||
|
pub(crate) assets: Vec<(String, File)>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub(crate) struct BlueprintMetaHandle(pub Handle<BlueprintPreloadAssets>);
|
||||||
|
|
||||||
|
/// flag component, usually added when a blueprint is loaded
|
||||||
|
#[derive(Component)]
|
||||||
|
pub(crate) struct BlueprintMetaLoaded;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub(crate) struct BlueprintMetaLoading;
|
|
@ -57,12 +57,17 @@ pub(crate) fn inject_materials(
|
||||||
material_found = Some(material);
|
material_found = Some(material);
|
||||||
} else {
|
} else {
|
||||||
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
||||||
let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| {
|
let Some(mat_gltf) = assets_gltf.get(model_handle.id()) else {
|
||||||
|
warn!("materials file {} should have been preloaded skipping",material_info.path);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
};
|
||||||
|
/*let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"materials file {} should have been preloaded",
|
"materials file {} should have been preloaded",
|
||||||
material_info.path
|
material_info.path
|
||||||
)
|
)
|
||||||
});
|
});*/
|
||||||
if mat_gltf
|
if mat_gltf
|
||||||
.named_materials
|
.named_materials
|
||||||
.contains_key(&material_info.name as &str)
|
.contains_key(&material_info.name as &str)
|
||||||
|
@ -79,6 +84,7 @@ pub(crate) fn inject_materials(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(material) = material_found {
|
if let Some(material) = material_found {
|
||||||
|
info!("Step 6: injecting/replacing materials");
|
||||||
for (child_index, child) in children.iter().enumerate() {
|
for (child_index, child) in children.iter().enumerate() {
|
||||||
if child_index == material_index {
|
if child_index == material_index {
|
||||||
if with_materials_and_meshes.contains(*child) {
|
if with_materials_and_meshes.contains(*child) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod spawn_from_blueprints;
|
pub mod spawn_from_blueprints;
|
||||||
|
use bevy_common_assets::ron::RonAssetPlugin;
|
||||||
pub use spawn_from_blueprints::*;
|
pub use spawn_from_blueprints::*;
|
||||||
|
|
||||||
pub mod animation;
|
pub mod animation;
|
||||||
|
@ -110,8 +111,10 @@ impl Plugin for BlueprintsPlugin {
|
||||||
.register_type::<Vec<String>>()
|
.register_type::<Vec<String>>()
|
||||||
.register_type::<BlueprintAssets>()
|
.register_type::<BlueprintAssets>()
|
||||||
.register_type::<HashMap<String, Vec<String>>>()
|
.register_type::<HashMap<String, Vec<String>>>()
|
||||||
.init_asset::<RawGltfAsset>()
|
//.init_asset::<RawGltfAsset>()
|
||||||
.init_asset_loader::<RawGltfAssetLoader>()
|
//.init_asset_loader::<RawGltfAssetLoader>()
|
||||||
|
.add_plugins(RonAssetPlugin::<BlueprintPreloadAssets>::new(&["meta.ron"]),)
|
||||||
|
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Update,
|
Update,
|
||||||
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
||||||
|
@ -121,7 +124,8 @@ impl Plugin for BlueprintsPlugin {
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
load_raw_gltf,
|
blueprints_prepare_metadata_file_for_spawn,
|
||||||
|
blueprints_check_assets_metadata_files_loading,
|
||||||
blueprints_prepare_spawn,
|
blueprints_prepare_spawn,
|
||||||
blueprints_check_assets_loading,
|
blueprints_check_assets_loading,
|
||||||
blueprints_assets_loaded,
|
blueprints_assets_loaded,
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
|
|
||||||
gltf::Gltf,
|
gltf::Gltf,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
scene::SceneInstance,
|
scene::SceneInstance,
|
||||||
utils::hashbrown::HashMap,
|
utils::{hashbrown::HashMap, warn},
|
||||||
};
|
};
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlueprintAnimationInfosLink,
|
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlueprintAnimationInfosLink, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintMetaLoading, BlueprintAssetsNotLoaded, BlueprintPreloadAssets, InstanceAnimationInfosLink, InstanceAnimationPlayerLink, InstanceAnimations, WatchingForChanges
|
||||||
BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState,
|
|
||||||
BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, InstanceAnimationInfosLink,
|
|
||||||
InstanceAnimationPlayerLink, InstanceAnimations, WatchingForChanges,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// this is a flag component for our levels/game world
|
/// this is a flag component for our levels/game world
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct GameWorldTag;
|
pub struct GameWorldTag;
|
||||||
|
@ -72,6 +68,13 @@ pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
||||||
/// as it would first become invisible before re-appearing again
|
/// as it would first become invisible before re-appearing again
|
||||||
pub struct HideUntilReady;
|
pub struct HideUntilReady;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
/// Companion to the `HideUntilReady` component: this stores the visibility of the entity before the blueprint was inserted into it
|
||||||
|
pub(crate) struct OriginalVisibility(Visibility);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// marker component, gets added to all children of a currently spawning blueprint instance, can be usefull to avoid manipulating still in progress entities
|
/// marker component, gets added to all children of a currently spawning blueprint instance, can be usefull to avoid manipulating still in progress entities
|
||||||
|
@ -103,8 +106,6 @@ pub enum BlueprintEvent {
|
||||||
/// component gets added when a blueprint starts spawning, removed when spawning is completely done
|
/// component gets added when a blueprint starts spawning, removed when spawning is completely done
|
||||||
pub struct BlueprintSpawning;
|
pub struct BlueprintSpawning;
|
||||||
|
|
||||||
use gltf::Gltf as RawGltf;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Overview of the Blueprint Spawning process
|
Overview of the Blueprint Spawning process
|
||||||
- Blueprint Load Assets
|
- Blueprint Load Assets
|
||||||
|
@ -121,62 +122,139 @@ Overview of the Blueprint Spawning process
|
||||||
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(Asset, TypePath, Debug)]
|
pub(super) fn blueprints_prepare_metadata_file_for_spawn(
|
||||||
pub struct RawGltfAsset(pub RawGltf);
|
blueprint_instances_to_spawn: Query<(
|
||||||
|
Entity,
|
||||||
|
&BlueprintInfo,
|
||||||
|
Option<&Name>,
|
||||||
|
Option<&Parent>,
|
||||||
|
Option<&HideUntilReady>,
|
||||||
|
Option<&Visibility>,
|
||||||
|
Option<&AddToGameWorld>,
|
||||||
|
|
||||||
#[derive(Default)]
|
), (Without<BlueprintMetaLoading>, Without<BlueprintSpawning>, Without<BlueprintInstanceReady>)>,
|
||||||
pub(super) struct RawGltfAssetLoader;
|
mut game_world: Query<Entity, With<GameWorldTag>>,
|
||||||
|
|
||||||
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<Self::Asset, Self::Error> {
|
|
||||||
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<RawGltfAsset>);
|
|
||||||
|
|
||||||
pub(super) fn load_raw_gltf(
|
|
||||||
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added<SpawnBlueprint>>,
|
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() {
|
for (entity, blueprint_info, entity_name, original_parent, hide_until_ready, original_visibility, add_to_world) in blueprint_instances_to_spawn.iter() {
|
||||||
let gltf_handle: Handle<RawGltfAsset> = asset_server.load(&blueprint_info.path);
|
// get path to assets / metadata file
|
||||||
commands
|
info!("Step 1: spawn request detected: loading metadata file for {:?}", blueprint_info);
|
||||||
.entity(entity)
|
let blueprint_path = blueprint_info.path.clone();
|
||||||
.insert(AssociatedRawGltfHandle(gltf_handle));
|
let metadata_path = blueprint_path.replace(".glb", ".meta.ron").replace(".gltf", ".meta.ron"); // FIXME: horrible
|
||||||
|
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||||
|
//let foo_handle:Handle<BlueprintPreloadAssets> = asset_server.load(metadata_path);
|
||||||
|
let untyped_handle = asset_server.load_untyped(metadata_path.clone());
|
||||||
|
let asset_id = untyped_handle.id();
|
||||||
|
|
||||||
|
asset_infos.push(AssetLoadTracker {
|
||||||
|
name: metadata_path.clone(),
|
||||||
|
path: metadata_path.clone(),
|
||||||
|
id: asset_id,
|
||||||
|
loaded: false,
|
||||||
|
handle: untyped_handle.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// add the blueprint spawning marker & co
|
||||||
|
commands.entity(entity).insert((
|
||||||
|
BlueprintAssetsLoadState {
|
||||||
|
all_loaded: false,
|
||||||
|
asset_infos,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
BlueprintMetaLoading,
|
||||||
|
BlueprintSpawning
|
||||||
|
));
|
||||||
|
|
||||||
|
// if the entity has no name, add one based on the blueprint's
|
||||||
|
if entity_name.is_none(){
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.insert(bevy::prelude::Name::from(blueprint_info.name.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if original_parent.is_none() {
|
||||||
|
// only allow hiding until ready when the entity does not have a parent (?)
|
||||||
|
if hide_until_ready.is_some() {
|
||||||
|
|
||||||
|
// if there is already a set visibility, save it for later
|
||||||
|
if let Some(original_visibility) = original_visibility {
|
||||||
|
commands.entity(entity).insert(OriginalVisibility(*original_visibility));
|
||||||
|
}
|
||||||
|
// & now hide the instance until it is ready
|
||||||
|
commands.entity(entity)
|
||||||
|
.insert(Visibility::Hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only allow automatically adding a newly spawned blueprint instance to the "world", if the entity does not have a parent
|
||||||
|
if add_to_world.is_some() {
|
||||||
|
let world = game_world
|
||||||
|
.get_single_mut()
|
||||||
|
.expect("there should be a game world present");
|
||||||
|
commands.entity(world).add_child(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge with other asset loading checker ?
|
||||||
|
pub(crate) fn blueprints_check_assets_metadata_files_loading(
|
||||||
|
mut blueprint_assets_to_load: Query<
|
||||||
|
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState),
|
||||||
|
With<BlueprintMetaLoading>,
|
||||||
|
>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
|
||||||
|
for (entity, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||||
|
|
||||||
|
let mut all_loaded = true;
|
||||||
|
let mut loaded_amount = 0;
|
||||||
|
let total = assets_to_load.asset_infos.len();
|
||||||
|
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||||
|
let asset_id = tracker.id;
|
||||||
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
|
|
||||||
|
let mut failed = false;
|
||||||
|
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
tracker.loaded = loaded || failed;
|
||||||
|
if loaded || failed {
|
||||||
|
loaded_amount += 1;
|
||||||
|
} else {
|
||||||
|
all_loaded = false;
|
||||||
|
}
|
||||||
|
if all_loaded {
|
||||||
|
commands.entity(entity).insert(BlueprintMetaHandle(asset_server.load(tracker.path.clone()))).remove::<BlueprintAssetsLoadState>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||||
|
assets_to_load.progress = progress;
|
||||||
|
// println!("LOADING: in progress for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) fn blueprints_prepare_spawn(
|
pub(super) fn blueprints_prepare_spawn(
|
||||||
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo, &AssociatedRawGltfHandle)>,
|
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo, &BlueprintMetaHandle, Option<&Name>), Added<BlueprintMetaHandle>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
// for hot reload
|
// for hot reload
|
||||||
watching_for_changes: Res<WatchingForChanges>,
|
watching_for_changes: Res<WatchingForChanges>,
|
||||||
mut assets_to_blueprint_instances: ResMut<AssetToBlueprintInstancesMapper>,
|
mut assets_to_blueprint_instances: ResMut<AssetToBlueprintInstancesMapper>,
|
||||||
raw_gltf_assets: Res<Assets<RawGltfAsset>>,
|
|
||||||
// for debug
|
// for debug
|
||||||
// all_names: Query<&Name>
|
// all_names: Query<&Name>
|
||||||
|
blueprint_metas: Res<Assets<BlueprintPreloadAssets>>,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
for (entity, blueprint_info, raw_gltf_handle) in blueprint_instances_to_spawn.iter() {
|
for (entity, blueprint_info, blueprint_meta_handle, entity_name) in blueprint_instances_to_spawn.iter() {
|
||||||
info!(
|
info!(
|
||||||
"BLUEPRINT: to spawn detected: {:?} path:{:?}",
|
"Step 2: metadata loaded: loading assets for {:?}",
|
||||||
blueprint_info.name, blueprint_info.path
|
blueprint_info,
|
||||||
);
|
);
|
||||||
// we add the asset of the blueprint itself
|
// we add the asset of the blueprint itself
|
||||||
// TODO: add detection of already loaded data
|
// TODO: add detection of already loaded data
|
||||||
|
@ -197,66 +275,56 @@ pub(super) fn blueprints_prepare_spawn(
|
||||||
|
|
||||||
// and we also add all its assets
|
// and we also add all its assets
|
||||||
/* prefetch attempt */
|
/* prefetch attempt */
|
||||||
let Some(RawGltfAsset(gltf)) = raw_gltf_assets.get(&raw_gltf_handle.0) else {
|
if let Some(blenvy_metadata) = blueprint_metas.get(&blueprint_meta_handle.0) {
|
||||||
continue;
|
for asset in blenvy_metadata.assets.iter() {
|
||||||
};
|
let asset_path = asset.1.path.clone();
|
||||||
for scene in gltf.scenes() {
|
let asset_name = asset.0.clone();
|
||||||
if let Some(scene_extras) = scene.extras().clone() {
|
|
||||||
let lookup: HashMap<String, Value> =
|
|
||||||
serde_json::from_str(scene_extras.get()).unwrap();
|
|
||||||
if lookup.contains_key("BlueprintAssets") {
|
|
||||||
let assets_raw = &lookup["BlueprintAssets"];
|
|
||||||
//println!("ASSETS RAW {}", assets_raw);
|
|
||||||
let all_assets: BlueprintAssets =
|
|
||||||
ron::from_str(assets_raw.as_str().unwrap()).unwrap();
|
|
||||||
// println!("all_assets {:?}", all_assets);
|
|
||||||
|
|
||||||
for asset in all_assets.assets.iter() {
|
let untyped_handle = asset_server.load_untyped(&asset_path);
|
||||||
let untyped_handle = asset_server.load_untyped(&asset.path);
|
let asset_id = untyped_handle.id();
|
||||||
let asset_id = untyped_handle.id();
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
if !loaded {
|
||||||
if !loaded {
|
asset_infos.push(AssetLoadTracker {
|
||||||
asset_infos.push(AssetLoadTracker {
|
name: asset_name.clone(),
|
||||||
name: asset.name.clone(),
|
path: asset_path.clone(),
|
||||||
path: asset.path.clone(),
|
id: asset_id,
|
||||||
id: asset_id,
|
loaded: false,
|
||||||
loaded: false,
|
handle: untyped_handle.clone(),
|
||||||
handle: untyped_handle.clone(),
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: dang, too early, asset server has not yet started loading yet
|
// FIXME: dang, too early, asset server has not yet started loading yet
|
||||||
// let path_id = asset_server.get_path_id(&asset.path).expect("we should have alread checked for this asset");
|
// let path_id = asset_server.get_path_id(&asset.path).expect("we should have alread checked for this asset");
|
||||||
let path_id = asset.path.clone();
|
let path_id = asset_path.clone();
|
||||||
|
|
||||||
// Only do this if hot reload is enabled
|
// Only do this if hot reload is enabled
|
||||||
if watching_for_changes.0 {
|
if watching_for_changes.0 {
|
||||||
if !assets_to_blueprint_instances
|
if !assets_to_blueprint_instances
|
||||||
.untyped_id_to_blueprint_entity_ids
|
.untyped_id_to_blueprint_entity_ids
|
||||||
.contains_key(&path_id)
|
.contains_key(&path_id)
|
||||||
{
|
{
|
||||||
assets_to_blueprint_instances
|
assets_to_blueprint_instances
|
||||||
.untyped_id_to_blueprint_entity_ids
|
.untyped_id_to_blueprint_entity_ids
|
||||||
.insert(path_id.clone(), vec![]);
|
.insert(path_id.clone(), vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only insert if not already present in mapping
|
// only insert if not already present in mapping
|
||||||
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids
|
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids
|
||||||
[&path_id]
|
[&path_id]
|
||||||
.contains(&entity)
|
.contains(&entity)
|
||||||
{
|
{
|
||||||
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
||||||
assets_to_blueprint_instances
|
assets_to_blueprint_instances
|
||||||
.untyped_id_to_blueprint_entity_ids
|
.untyped_id_to_blueprint_entity_ids
|
||||||
.get_mut(&path_id)
|
.get_mut(&path_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push(entity);
|
.push(entity);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else {
|
||||||
|
warn!("no asset metadata found for {}, please make sure to generate them using the Blender add-on, or preload your assets manually", blueprint_info.path);
|
||||||
|
}
|
||||||
|
|
||||||
// Only do this if hot reload is enabled
|
// Only do this if hot reload is enabled
|
||||||
// TODO: should this be added to the list of "all assets" on the blender side instead
|
// TODO: should this be added to the list of "all assets" on the blender side instead
|
||||||
|
@ -299,40 +367,35 @@ pub(super) fn blueprints_prepare_spawn(
|
||||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the entity has no name, add one based on the blueprint's
|
commands.entity(entity)
|
||||||
commands
|
.remove::<BlueprintMetaLoading>()
|
||||||
.entity(entity)
|
.remove::<BlueprintMetaHandle>();
|
||||||
.insert(bevy::prelude::Name::from(blueprint_info.name.clone()));
|
|
||||||
// add the blueprint spawning marker
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.insert(BlueprintSpawning)
|
|
||||||
.remove::<AssociatedRawGltfHandle>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This system tracks & updates the loading state of all blueprints assets
|
/// This system tracks & updates the loading state of all blueprints assets
|
||||||
pub(crate) fn blueprints_check_assets_loading(
|
pub(crate) fn blueprints_check_assets_loading(
|
||||||
mut blueprint_assets_to_load: Query<
|
mut blueprint_assets_to_load: Query<
|
||||||
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState),
|
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState, Option<&Name>),
|
||||||
With<BlueprintAssetsNotLoaded>,
|
With<BlueprintAssetsNotLoaded>,
|
||||||
>,
|
>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut blueprint_events: EventWriter<BlueprintEvent>,
|
mut blueprint_events: EventWriter<BlueprintEvent>,
|
||||||
// for hot reload
|
|
||||||
watching_for_changes: Res<WatchingForChanges>,
|
|
||||||
) {
|
) {
|
||||||
for (entity, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
for (entity, blueprint_info, mut assets_to_load, entity_name) in blueprint_assets_to_load.iter_mut() {
|
||||||
let mut all_loaded = true;
|
let mut all_loaded = true;
|
||||||
let mut loaded_amount = 0;
|
let mut loaded_amount = 0;
|
||||||
let total = assets_to_load.asset_infos.len();
|
let total = assets_to_load.asset_infos.len();
|
||||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||||
let asset_id = tracker.id;
|
let asset_id = tracker.id;
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
|
if loaded {
|
||||||
|
debug!("LOADED {}", tracker.path.clone());
|
||||||
|
}
|
||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
||||||
|
warn!("FAILED TO LOAD {}", tracker.path.clone());
|
||||||
failed = true
|
failed = true
|
||||||
}
|
}
|
||||||
tracker.loaded = loaded || failed;
|
tracker.loaded = loaded || failed;
|
||||||
|
@ -344,7 +407,7 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||||
}
|
}
|
||||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||||
assets_to_load.progress = progress;
|
assets_to_load.progress = progress;
|
||||||
// println!("LOADING: in progress for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
//println!("LOADING: in progress for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
||||||
|
|
||||||
if all_loaded {
|
if all_loaded {
|
||||||
assets_to_load.all_loaded = true;
|
assets_to_load.all_loaded = true;
|
||||||
|
@ -359,10 +422,6 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintAssetsLoaded)
|
.insert(BlueprintAssetsLoaded)
|
||||||
.remove::<BlueprintAssetsNotLoaded>();
|
.remove::<BlueprintAssetsNotLoaded>();
|
||||||
|
|
||||||
if !watching_for_changes.0 {
|
|
||||||
commands.entity(entity).remove::<BlueprintAssetsLoadState>(); //we REMOVE this component when in hot reload is OFF, as we
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,20 +432,15 @@ pub(crate) fn blueprints_assets_loaded(
|
||||||
Entity,
|
Entity,
|
||||||
&BlueprintInfo,
|
&BlueprintInfo,
|
||||||
Option<&Transform>,
|
Option<&Transform>,
|
||||||
Option<&Parent>,
|
|
||||||
Option<&AddToGameWorld>,
|
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
Option<&HideUntilReady>,
|
|
||||||
Option<&AnimationInfos>,
|
Option<&AnimationInfos>,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
With<BlueprintAssetsLoaded>,
|
|
||||||
Added<BlueprintAssetsLoaded>,
|
Added<BlueprintAssetsLoaded>,
|
||||||
Without<BlueprintAssetsNotLoaded>,
|
Without<BlueprintAssetsNotLoaded>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
all_children: Query<&Children>,
|
all_children: Query<&Children>,
|
||||||
mut game_world: Query<Entity, With<GameWorldTag>>,
|
|
||||||
assets_gltf: Res<Assets<Gltf>>,
|
assets_gltf: Res<Assets<Gltf>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
|
||||||
|
@ -398,10 +452,7 @@ pub(crate) fn blueprints_assets_loaded(
|
||||||
entity,
|
entity,
|
||||||
blueprint_info,
|
blueprint_info,
|
||||||
transform,
|
transform,
|
||||||
original_parent,
|
|
||||||
add_to_world,
|
|
||||||
name,
|
name,
|
||||||
hide_until_ready,
|
|
||||||
animation_infos,
|
animation_infos,
|
||||||
) in spawn_placeholders.iter()
|
) in spawn_placeholders.iter()
|
||||||
{
|
{
|
||||||
|
@ -411,8 +462,8 @@ pub(crate) fn blueprints_assets_loaded(
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"BLUEPRINT: all assets loaded, attempting to spawn blueprint SCENE {:?} for entity {:?}, id: {}",
|
"Step 3: all assets loaded, attempting to spawn blueprint scene {:?} for entity {:?}, id: {}",
|
||||||
blueprint_info.name, name, entity
|
blueprint_info, name, entity
|
||||||
);
|
);
|
||||||
|
|
||||||
// info!("attempting to spawn {:?}", model_path);
|
// info!("attempting to spawn {:?}", model_path);
|
||||||
|
@ -479,20 +530,7 @@ pub(crate) fn blueprints_assets_loaded(
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
if original_parent.is_none() {
|
|
||||||
// only allow hiding until ready when the entity does not have a parent (?)
|
|
||||||
if hide_until_ready.is_some() {
|
|
||||||
commands.entity(entity).insert(Visibility::Hidden); // visibility:
|
|
||||||
}
|
|
||||||
|
|
||||||
// only allow automatically adding a newly spawned blueprint instance to the "world", if the entity does not have a parent
|
|
||||||
if add_to_world.is_some() {
|
|
||||||
let world = game_world
|
|
||||||
.get_single_mut()
|
|
||||||
.expect("there should be a game world present");
|
|
||||||
commands.entity(world).add_child(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,7 +574,7 @@ pub(crate) fn blueprints_scenes_spawned(
|
||||||
) {
|
) {
|
||||||
for (entity, name, children, track_root) in spawned_blueprint_scene_instances.iter() {
|
for (entity, name, children, track_root) in spawned_blueprint_scene_instances.iter() {
|
||||||
info!(
|
info!(
|
||||||
"Done spawning blueprint scene for entity named {:?} (track root: {:?})",
|
"Step 4: Done spawning blueprint scene for entity named {:?} (track root: {:?})",
|
||||||
name, track_root
|
name, track_root
|
||||||
);
|
);
|
||||||
let mut sub_blueprint_instances: Vec<Entity> = vec![];
|
let mut sub_blueprint_instances: Vec<Entity> = vec![];
|
||||||
|
@ -614,6 +652,8 @@ pub(crate) fn blueprints_scenes_spawned(
|
||||||
use crate::CopyComponents;
|
use crate::CopyComponents;
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
use super::{BlueprintMetaHandle, BlueprintMetaLoaded};
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintReadyForPostProcess;
|
pub struct BlueprintReadyForPostProcess;
|
||||||
|
@ -646,7 +686,7 @@ pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
all_names: Query<&Name>,
|
all_names: Query<&Name>,
|
||||||
) {
|
) {
|
||||||
for (original, children, original_children, name, animations) in blueprint_scenes.iter() {
|
for (original, children, original_children, name, animations) in blueprint_scenes.iter() {
|
||||||
info!("Cleaning up spawned scene {:?}", name);
|
info!("Step 5: Cleaning up spawned scene {:?}", name);
|
||||||
|
|
||||||
if children.len() == 0 {
|
if children.len() == 0 {
|
||||||
// TODO: investigate, Honestly not sure if this issue from Bevy 0.12 is still present at all anymore
|
// TODO: investigate, Honestly not sure if this issue from Bevy 0.12 is still present at all anymore
|
||||||
|
@ -783,6 +823,7 @@ pub(crate) fn blueprints_finalize_instances(
|
||||||
&BlueprintInfo,
|
&BlueprintInfo,
|
||||||
Option<&SubBlueprintSpawnRoot>,
|
Option<&SubBlueprintSpawnRoot>,
|
||||||
Option<&HideUntilReady>,
|
Option<&HideUntilReady>,
|
||||||
|
Option<&OriginalVisibility>,
|
||||||
),
|
),
|
||||||
(With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>),
|
(With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>),
|
||||||
>,
|
>,
|
||||||
|
@ -793,10 +834,10 @@ pub(crate) fn blueprints_finalize_instances(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
// all_names: Query<&Name>
|
// all_names: Query<&Name>
|
||||||
) {
|
) {
|
||||||
for (entity, name, blueprint_info, parent_blueprint, hide_until_ready) in
|
for (entity, name, blueprint_info, parent_blueprint, hide_until_ready, original_visibility) in
|
||||||
blueprint_instances.iter()
|
blueprint_instances.iter()
|
||||||
{
|
{
|
||||||
info!("Finalizing blueprint instance {:?}", name);
|
info!("Step 8: Finalizing blueprint instance {:?}", name);
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.remove::<BlueprintReadyForFinalizing>()
|
.remove::<BlueprintReadyForFinalizing>()
|
||||||
|
@ -804,8 +845,9 @@ pub(crate) fn blueprints_finalize_instances(
|
||||||
.remove::<BlueprintSpawning>()
|
.remove::<BlueprintSpawning>()
|
||||||
.remove::<SpawnBlueprint>()
|
.remove::<SpawnBlueprint>()
|
||||||
//.remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
//.remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
||||||
//.remove::<BlueprintAssetsLoadState>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
.remove::<BlueprintAssetsLoadState>() // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
||||||
//.remove::<BlueprintAssetsLoaded>();
|
.remove::<BlueprintAssetsLoaded>()
|
||||||
|
.remove::<OriginalChildren>() // we do not need to keep the original children information
|
||||||
.insert(BlueprintInstanceReady);
|
.insert(BlueprintInstanceReady);
|
||||||
|
|
||||||
// Deal with sub blueprints
|
// Deal with sub blueprints
|
||||||
|
@ -839,12 +881,18 @@ pub(crate) fn blueprints_finalize_instances(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
commands.entity(entity).remove::<BlueprintInstanceDisabled>();
|
||||||
for child in all_children.iter_descendants(entity) {
|
for child in all_children.iter_descendants(entity) {
|
||||||
commands.entity(child).remove::<BlueprintInstanceDisabled>();
|
commands.entity(child).remove::<BlueprintInstanceDisabled>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if hide_until_ready.is_some() {
|
if hide_until_ready.is_some() {
|
||||||
commands.entity(entity).insert(Visibility::Inherited);
|
if let Some(original_visibility) = original_visibility {
|
||||||
|
commands.entity(entity).insert(original_visibility.0);
|
||||||
|
}else {
|
||||||
|
commands.entity(entity).insert(Visibility::Inherited);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blueprint_events.send(BlueprintEvent::InstanceReady {
|
blueprint_events.send(BlueprintEvent::InstanceReady {
|
||||||
|
|
|
@ -4,8 +4,7 @@ use blenvy::*;
|
||||||
pub struct CorePlugin;
|
pub struct CorePlugin;
|
||||||
impl Plugin for CorePlugin {
|
impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins((BlueprintsPlugin {
|
app.add_plugins((BlenvyPlugin {
|
||||||
material_library: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},));
|
},));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins(
|
app.add_plugins(
|
||||||
BlenvyPlugin {
|
BlenvyPlugin {
|
||||||
aabbs: true,
|
|
||||||
registry_component_filter: SceneFilter::Denylist(HashSet::from([
|
registry_component_filter: SceneFilter::Denylist(HashSet::from([
|
||||||
// this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
// this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
||||||
TypeId::of::<ComponentAToFilterOut>(),
|
TypeId::of::<ComponentAToFilterOut>(),
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
from blenvy.assets.assets_scan import get_blueprint_asset_tree
|
|
||||||
from blenvy.assets.generate_asset_file import write_ron_assets_file
|
|
||||||
from ....materials.materials_helpers import add_material_info_to_objects, get_blueprint_materials
|
from ....materials.materials_helpers import add_material_info_to_objects, get_blueprint_materials
|
||||||
from ..constants import TEMPSCENE_PREFIX
|
from ..constants import TEMPSCENE_PREFIX
|
||||||
from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene
|
from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene
|
||||||
from ..common.export_gltf import generate_gltf_export_settings
|
from ..common.export_gltf import generate_gltf_export_settings
|
||||||
from ..utils import upsert_blueprint_assets
|
from ..utils import upsert_blueprint_assets, write_blueprint_metadata_file
|
||||||
|
|
||||||
def export_blueprints(blueprints, settings, blueprints_data):
|
def export_blueprints(blueprints, settings, blueprints_data):
|
||||||
blueprints_path_full = getattr(settings, "blueprints_path_full")
|
blueprints_path_full = getattr(settings, "blueprints_path_full")
|
||||||
|
@ -33,6 +31,9 @@ def export_blueprints(blueprints, settings, blueprints_data):
|
||||||
(_, materials_per_object) = get_blueprint_materials(blueprint)
|
(_, materials_per_object) = get_blueprint_materials(blueprint)
|
||||||
add_material_info_to_objects(materials_per_object, settings)
|
add_material_info_to_objects(materials_per_object, settings)
|
||||||
|
|
||||||
|
write_blueprint_metadata_file(blueprint=blueprint, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
|
||||||
|
|
||||||
# do the actual export
|
# do the actual export
|
||||||
generate_temporary_scene_and_export(
|
generate_temporary_scene_and_export(
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -65,8 +65,9 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print("failed to export gltf !", error)
|
print("failed to export gltf !", error)
|
||||||
raise error
|
raise error
|
||||||
# restore everything
|
finally:
|
||||||
tempScene_cleaner(temp_scene, scene_filler_data)
|
# restore everything
|
||||||
|
tempScene_cleaner(temp_scene, scene_filler_data)
|
||||||
|
|
||||||
# reset active scene
|
# reset active scene
|
||||||
bpy.context.window.scene = active_scene
|
bpy.context.window.scene = active_scene
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ..constants import TEMPSCENE_PREFIX
|
from ..constants import TEMPSCENE_PREFIX
|
||||||
from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene
|
from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene
|
||||||
from ..common.export_gltf import (generate_gltf_export_settings, export_gltf)
|
from ..common.export_gltf import (generate_gltf_export_settings, export_gltf)
|
||||||
from .is_object_dynamic import is_object_dynamic, is_object_static
|
from .is_object_dynamic import is_object_dynamic, is_object_static
|
||||||
from ..utils import upsert_scene_assets
|
from ..utils import upsert_scene_assets, write_level_metadata_file
|
||||||
|
|
||||||
|
|
||||||
def export_level_scene(scene, settings, blueprints_data):
|
def export_level_scene(scene, settings, blueprints_data):
|
||||||
|
@ -28,6 +29,7 @@ def export_level_scene(scene, settings, blueprints_data):
|
||||||
# we inject assets into the scene before it gets exported
|
# we inject assets into the scene before it gets exported
|
||||||
# TODO: this should be done in the temporary scene !
|
# TODO: this should be done in the temporary scene !
|
||||||
upsert_scene_assets(scene, blueprints_data=blueprints_data, settings=settings)
|
upsert_scene_assets(scene, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
write_level_metadata_file(scene=scene, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
|
||||||
if export_separate_dynamic_and_static_objects:
|
if export_separate_dynamic_and_static_objects:
|
||||||
#print("SPLIT STATIC AND DYNAMIC")
|
#print("SPLIT STATIC AND DYNAMIC")
|
||||||
|
|
|
@ -4,6 +4,7 @@ from pathlib import Path
|
||||||
from blenvy.assets.assets_scan import get_blueprint_asset_tree, get_level_scene_assets_tree2
|
from blenvy.assets.assets_scan import get_blueprint_asset_tree, get_level_scene_assets_tree2
|
||||||
from blenvy.add_ons.bevy_components.utils import is_component_valid_and_enabled
|
from blenvy.add_ons.bevy_components.utils import is_component_valid_and_enabled
|
||||||
from .constants import custom_properties_to_filter_out
|
from .constants import custom_properties_to_filter_out
|
||||||
|
from ...assets.assets_scan import get_level_scene_assets_tree2
|
||||||
|
|
||||||
def remove_unwanted_custom_properties(object):
|
def remove_unwanted_custom_properties(object):
|
||||||
to_remove = []
|
to_remove = []
|
||||||
|
@ -42,3 +43,45 @@ def upsert_blueprint_assets(blueprint, blueprints_data, settings):
|
||||||
print("all_assets_raw", all_assets_raw)
|
print("all_assets_raw", all_assets_raw)
|
||||||
print("local assets", local_assets)
|
print("local assets", local_assets)
|
||||||
blueprint.collection["BlueprintAssets"] = assets_to_fake_ron(local_assets)
|
blueprint.collection["BlueprintAssets"] = assets_to_fake_ron(local_assets)
|
||||||
|
|
||||||
|
import os
|
||||||
|
def write_level_metadata_file(scene, blueprints_data, settings):
|
||||||
|
levels_path_full = getattr(settings,"levels_path_full")
|
||||||
|
all_assets_raw = get_level_scene_assets_tree2(level_scene=scene, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
|
||||||
|
formated_assets = []
|
||||||
|
for asset in all_assets_raw:
|
||||||
|
#if asset["internal"] :
|
||||||
|
formated_asset = f'\n ("{asset["name"]}", File ( path: "{asset["path"]}" )),'
|
||||||
|
formated_assets.append(formated_asset)
|
||||||
|
|
||||||
|
metadata_file_path_full = os.path.join(levels_path_full, scene.name+".meta.ron")
|
||||||
|
os.makedirs(os.path.dirname(metadata_file_path_full), exist_ok=True)
|
||||||
|
|
||||||
|
with open(metadata_file_path_full, "w") as assets_file:
|
||||||
|
assets_file.write("(\n ")
|
||||||
|
assets_file.write(" assets:\n [ ")
|
||||||
|
assets_file.writelines(formated_assets)
|
||||||
|
assets_file.write("\n ]\n")
|
||||||
|
assets_file.write(")")
|
||||||
|
|
||||||
|
def write_blueprint_metadata_file(blueprint, blueprints_data, settings):
|
||||||
|
blueprints_path_full = getattr(settings,"blueprints_path_full")
|
||||||
|
all_assets_raw = get_blueprint_asset_tree(blueprint=blueprint, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
|
||||||
|
formated_assets = []
|
||||||
|
for asset in all_assets_raw:
|
||||||
|
#if asset["internal"] :
|
||||||
|
formated_asset = f'\n ("{asset["name"]}", File ( path: "{asset["path"]}" )),'
|
||||||
|
formated_assets.append(formated_asset)
|
||||||
|
|
||||||
|
|
||||||
|
metadata_file_path_full = os.path.join(blueprints_path_full, blueprint.name+".meta.ron")
|
||||||
|
os.makedirs(os.path.dirname(metadata_file_path_full), exist_ok=True)
|
||||||
|
|
||||||
|
with open(metadata_file_path_full, "w") as assets_file:
|
||||||
|
assets_file.write("(\n ")
|
||||||
|
assets_file.write(" assets:\n [ ")
|
||||||
|
assets_file.writelines(formated_assets)
|
||||||
|
assets_file.write("\n ]\n")
|
||||||
|
assets_file.write(")")
|
Loading…
Reference in New Issue