feat(Blenvy): basic working loading of levels & assets
* removed/ obsoleted blueprintsList * now using AllAssets (meh naming) * modified example & internals to enable loading levels as Blueprints as well * internals quite messy for now, needs a big cleanup still * disabled materials library for now, needs to be overhauled to make use of asset logic as well * added more mock assets for testing * related changes to blender & bevy side
This commit is contained in:
parent
2a74dedcb8
commit
1fdb45bab6
|
@ -1,6 +1,6 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use bevy::{gltf::Gltf, prelude::*, utils::HashMap};
|
||||
use bevy::{asset::LoadedUntypedAsset, gltf::Gltf, prelude::*, utils::HashMap};
|
||||
|
||||
use crate::{BluePrintsConfig, BlueprintAnimations};
|
||||
|
||||
|
@ -24,30 +24,35 @@ pub struct AllAssets(pub Vec<MyAsset>);
|
|||
|
||||
|
||||
|
||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct BlueprintsList(pub HashMap<String, Vec<String>>);
|
||||
////////////////////////
|
||||
///
|
||||
/// flag component, usually added when a blueprint is loaded
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsLoaded;
|
||||
/// flag component
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsNotLoaded;
|
||||
|
||||
/// helper component, for tracking loaded assets's loading state, id , handle etc
|
||||
#[derive(Default, Debug)]
|
||||
pub(crate) struct AssetLoadTracker<T: bevy::prelude::Asset> {
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AssetLoadTracker {
|
||||
#[allow(dead_code)]
|
||||
pub name: String,
|
||||
pub id: AssetId<T>,
|
||||
pub id: AssetId<LoadedUntypedAsset>,
|
||||
pub loaded: bool,
|
||||
#[allow(dead_code)]
|
||||
pub handle: Handle<T>,
|
||||
pub handle: Handle<LoadedUntypedAsset>,
|
||||
}
|
||||
|
||||
|
||||
/// helper component, for tracking loaded assets
|
||||
#[derive(Component, Debug)]
|
||||
pub(crate) struct AssetsToLoad<T: bevy::prelude::Asset> {
|
||||
pub(crate) struct AssetsToLoad {
|
||||
pub all_loaded: bool,
|
||||
pub asset_infos: Vec<AssetLoadTracker<T>>,
|
||||
pub asset_infos: Vec<AssetLoadTracker>,
|
||||
pub progress: f32,
|
||||
}
|
||||
impl<T: bevy::prelude::Asset> Default for AssetsToLoad<T> {
|
||||
impl Default for AssetsToLoad {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
all_loaded: Default::default(),
|
||||
|
@ -56,10 +61,3 @@ impl<T: bevy::prelude::Asset> Default for AssetsToLoad<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// flag component, usually added when a blueprint is loaded
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsLoaded;
|
||||
/// flag component
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsNotLoaded;
|
||||
|
|
|
@ -129,13 +129,13 @@ impl Plugin for BlueprintsPlugin {
|
|||
.register_type::<HashMap<u32, Vec<String>>>()
|
||||
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
||||
.add_event::<AnimationMarkerReached>()
|
||||
.register_type::<BlueprintsList>()
|
||||
.register_type::<MyAsset>()
|
||||
.register_type::<Vec<MyAsset>>()
|
||||
.register_type::<Vec<String>>()
|
||||
.register_type::<LocalAssets>()
|
||||
.register_type::<AllAssets>()
|
||||
|
||||
|
||||
.register_type::<HashMap<String, Vec<String>>>()
|
||||
.insert_resource(BluePrintsConfig {
|
||||
format: self.format,
|
||||
|
@ -158,20 +158,23 @@ impl Plugin for BlueprintsPlugin {
|
|||
Update,
|
||||
(
|
||||
test_thingy,
|
||||
(
|
||||
check_for_loaded2,
|
||||
spawn_from_blueprints2,
|
||||
|
||||
/*(
|
||||
prepare_blueprints,
|
||||
check_for_loaded,
|
||||
spawn_from_blueprints,
|
||||
apply_deferred,
|
||||
)
|
||||
.chain(),
|
||||
.chain(),*/
|
||||
(compute_scene_aabbs, apply_deferred)
|
||||
.chain()
|
||||
.run_if(aabbs_enabled),
|
||||
apply_deferred,
|
||||
(
|
||||
materials_inject,
|
||||
check_for_material_loaded,
|
||||
// check_for_material_loaded,
|
||||
materials_inject2,
|
||||
)
|
||||
.chain()
|
||||
|
|
|
@ -66,7 +66,9 @@ pub(crate) fn materials_inject(
|
|||
} else {
|
||||
let material_file_handle: Handle<Gltf> = asset_server.load(materials_path.clone());
|
||||
let material_file_id = material_file_handle.id();
|
||||
let asset_infos: Vec<AssetLoadTracker<Gltf>> = vec![AssetLoadTracker {
|
||||
|
||||
// FIXME: fix this stuff
|
||||
/*let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
||||
name: material_full_path,
|
||||
id: material_file_id,
|
||||
loaded: false,
|
||||
|
@ -81,12 +83,14 @@ pub(crate) fn materials_inject(
|
|||
..Default::default()
|
||||
})
|
||||
.insert(BlueprintMaterialAssetsNotLoaded);
|
||||
/**/
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO, merge with check_for_loaded, make generic ?
|
||||
// FIXME: fix this:
|
||||
/*
|
||||
pub(crate) fn check_for_material_loaded(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &mut AssetsToLoad<Gltf>),
|
||||
|
@ -121,7 +125,7 @@ pub(crate) fn check_for_material_loaded(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/// system that injects / replaces materials from material library
|
||||
pub(crate) fn materials_inject2(
|
||||
mut blueprints_config: ResMut<BluePrintsConfig>,
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
|
||||
|
||||
/// helper component, for tracking loaded assets's loading state, id , handle etc
|
||||
#[derive(Default, Debug)]
|
||||
pub(crate) struct AssetLoadTracker<T: bevy::prelude::Asset> {
|
||||
#[allow(dead_code)]
|
||||
pub name: String,
|
||||
pub id: AssetId<T>,
|
||||
pub loaded: bool,
|
||||
#[allow(dead_code)]
|
||||
pub handle: Handle<T>,
|
||||
}
|
||||
|
||||
/// helper component, for tracking loaded assets
|
||||
#[derive(Component, Debug)]
|
||||
pub(crate) struct AssetsToLoad<T: bevy::prelude::Asset> {
|
||||
pub all_loaded: bool,
|
||||
pub asset_infos: Vec<AssetLoadTracker<T>>,
|
||||
pub progress: f32,
|
||||
}
|
||||
impl<T: bevy::prelude::Asset> Default for AssetsToLoad<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
all_loaded: Default::default(),
|
||||
asset_infos: Default::default(),
|
||||
progress: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// flag component, usually added when a blueprint is loaded
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsLoaded;
|
||||
/// flag component
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintAssetsNotLoaded;
|
||||
|
||||
|
||||
|
||||
/// spawning prepare function,
|
||||
/// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint
|
||||
pub(crate) fn prepare_blueprints(
|
||||
spawn_placeholders: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintName,
|
||||
Option<&Parent>,
|
||||
Option<&Library>,
|
||||
Option<&Name>,
|
||||
Option<&BlueprintsList>,
|
||||
),
|
||||
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
||||
>,
|
||||
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
blueprints_config: Res<BluePrintsConfig>,
|
||||
) {
|
||||
for (entity, blupeprint_name, original_parent, library_override, name, blueprints_list) in
|
||||
spawn_placeholders.iter()
|
||||
{
|
||||
debug!(
|
||||
"requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||
blupeprint_name.0, name, entity, original_parent
|
||||
);
|
||||
|
||||
// println!("main model path {:?}", model_path);
|
||||
if blueprints_list.is_some() {
|
||||
let blueprints_list = blueprints_list.unwrap();
|
||||
// println!("blueprints list {:?}", blueprints_list.0.keys());
|
||||
let mut asset_infos: Vec<AssetLoadTracker<Gltf>> = vec![];
|
||||
let library_path =
|
||||
library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0);
|
||||
for (blueprint_name, _) in blueprints_list.0.iter() {
|
||||
let model_file_name = format!("{}.{}", &blueprint_name, &blueprints_config.format);
|
||||
let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str()));
|
||||
|
||||
let model_handle: Handle<Gltf> = asset_server.load(model_path.clone());
|
||||
let model_id = model_handle.id();
|
||||
let loaded = asset_server.is_loaded_with_dependencies(model_id);
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: model_path.to_string_lossy().into(),
|
||||
id: model_id,
|
||||
loaded: false,
|
||||
handle: model_handle.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// if not all assets are already loaded, inject a component to signal that we need them to be loaded
|
||||
if !asset_infos.is_empty() {
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(AssetsToLoad {
|
||||
all_loaded: false,
|
||||
asset_infos,
|
||||
..Default::default()
|
||||
})
|
||||
.insert(BlueprintAssetsNotLoaded);
|
||||
} else {
|
||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
} else {
|
||||
// in case there are no blueprintsList, we revert back to the old behaviour
|
||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_for_loaded(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &mut AssetsToLoad<Gltf>),
|
||||
With<BlueprintAssetsNotLoaded>,
|
||||
>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, 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);
|
||||
tracker.loaded = loaded;
|
||||
if loaded {
|
||||
loaded_amount += 1;
|
||||
} else {
|
||||
all_loaded = false;
|
||||
}
|
||||
}
|
||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||
// println!("progress: {}",progress);
|
||||
assets_to_load.progress = progress;
|
||||
|
||||
if all_loaded {
|
||||
assets_to_load.all_loaded = true;
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintAssetsLoaded)
|
||||
.remove::<BlueprintAssetsNotLoaded>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_from_blueprints(
|
||||
spawn_placeholders: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintName,
|
||||
Option<&Transform>,
|
||||
Option<&Parent>,
|
||||
Option<&Library>,
|
||||
Option<&AddToGameWorld>,
|
||||
Option<&Name>,
|
||||
),
|
||||
(
|
||||
With<BlueprintAssetsLoaded>,
|
||||
Added<BlueprintAssetsLoaded>,
|
||||
Without<BlueprintAssetsNotLoaded>,
|
||||
),
|
||||
>,
|
||||
|
||||
mut commands: Commands,
|
||||
mut game_world: Query<Entity, With<GameWorldTag>>,
|
||||
|
||||
assets_gltf: Res<Assets<Gltf>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
blueprints_config: Res<BluePrintsConfig>,
|
||||
|
||||
children: Query<&Children>,
|
||||
) {
|
||||
for (
|
||||
entity,
|
||||
blupeprint_name,
|
||||
transform,
|
||||
original_parent,
|
||||
library_override,
|
||||
add_to_world,
|
||||
name,
|
||||
) in spawn_placeholders.iter()
|
||||
{
|
||||
debug!(
|
||||
"attempting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||
blupeprint_name.0, name, entity, original_parent
|
||||
);
|
||||
|
||||
let what = &blupeprint_name.0;
|
||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
||||
|
||||
// library path is either defined at the plugin level or overriden by optional Library components
|
||||
let library_path =
|
||||
library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0);
|
||||
let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str()));
|
||||
|
||||
// info!("attempting to spawn {:?}", model_path);
|
||||
let model_handle: Handle<Gltf> = asset_server.load(model_path.clone()); // FIXME: kinda weird now
|
||||
|
||||
let gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"gltf file {:?} should have been loaded",
|
||||
model_path.to_str()
|
||||
)
|
||||
});
|
||||
|
||||
// WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one
|
||||
let main_scene_name = gltf
|
||||
.named_scenes
|
||||
.keys()
|
||||
.next()
|
||||
.expect("there should be at least one named scene in the gltf file to spawn");
|
||||
|
||||
let scene = &gltf.named_scenes[main_scene_name];
|
||||
|
||||
// transforms are optional, but still deal with them correctly
|
||||
let mut transforms: Transform = Transform::default();
|
||||
if transform.is_some() {
|
||||
transforms = *transform.unwrap();
|
||||
}
|
||||
|
||||
let mut original_children: Vec<Entity> = vec![];
|
||||
if let Ok(c) = children.get(entity) {
|
||||
for child in c.iter() {
|
||||
original_children.push(*child);
|
||||
}
|
||||
}
|
||||
commands.entity(entity).insert((
|
||||
SceneBundle {
|
||||
scene: scene.clone(),
|
||||
transform: transforms,
|
||||
..Default::default()
|
||||
},
|
||||
Spawned,
|
||||
OriginalChildren(original_children),
|
||||
BlueprintAnimations {
|
||||
// these are animations specific to the inside of the blueprint
|
||||
named_animations: gltf.named_animations.clone(),
|
||||
},
|
||||
));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use bevy::{gltf::Gltf, prelude::*, utils::HashMap};
|
||||
|
||||
use crate::{BluePrintsConfig, BlueprintAnimations, BlueprintsList, AssetLoadTracker, AssetsToLoad, BlueprintAssetsNotLoaded, BlueprintAssetsLoaded};
|
||||
use crate::{AllAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
|
||||
/// this is a flag component for our levels/game world
|
||||
#[derive(Component)]
|
||||
|
@ -59,81 +59,103 @@ pub(crate) fn test_thingy(
|
|||
Entity,
|
||||
&BlueprintPath,
|
||||
),
|
||||
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnHere>),
|
||||
>,
|
||||
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnHere>)>,
|
||||
|
||||
// before 0.14 we have to use a seperate query, after migrating we can query at the root level
|
||||
entities_with_assets: Query<
|
||||
(
|
||||
Entity,
|
||||
/*&BlueprintName,
|
||||
&BlueprintPath,
|
||||
Option<&Parent>,*/
|
||||
Option<&Name>,
|
||||
Option<&AllAssets>,
|
||||
),
|
||||
(Added<AllAssets>), // Added<AllAssets>
|
||||
>,
|
||||
|
||||
|
||||
bla_bla : Query<
|
||||
(Entity,
|
||||
&BlueprintName,
|
||||
&BlueprintPath,
|
||||
Option<&Parent>,),(Added<BlueprintPath>)
|
||||
>,
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
||||
|
||||
) {
|
||||
for (entity, blueprint_path) in spawn_placeholders.iter() {
|
||||
println!("added blueprint_path {:?}", blueprint_path);
|
||||
commands.entity(entity).insert(
|
||||
//println!("added blueprint_path {:?}", blueprint_path);
|
||||
/*commands.entity(entity).insert(
|
||||
SceneBundle {
|
||||
scene: asset_server.load(format!("{}#Scene0", &blueprint_path.0)), // "levels/World.glb#Scene0"),
|
||||
..default()
|
||||
},
|
||||
);
|
||||
);*/
|
||||
// let model_handle: Handle<Gltf> = asset_server.load(model_path.clone());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
for (entity, blueprint_name, blueprint_path, parent) in bla_bla.iter() {
|
||||
println!("added blueprint to spawn {:?} {:?}", blueprint_name, blueprint_path);
|
||||
let untyped_handle = asset_server.load_untyped(&blueprint_path.0);
|
||||
let asset_id = untyped_handle.id();
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
|
||||
/// spawning prepare function,
|
||||
/// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint
|
||||
pub(crate) fn prepare_blueprints(
|
||||
spawn_placeholders: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintName,
|
||||
Option<&Parent>,
|
||||
Option<&Library>,
|
||||
Option<&Name>,
|
||||
Option<&BlueprintsList>,
|
||||
),
|
||||
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
||||
>,
|
||||
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: blueprint_name.0.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: untyped_handle.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
blueprints_config: Res<BluePrintsConfig>,
|
||||
) {
|
||||
for (entity, blupeprint_name, original_parent, library_override, name, blueprints_list) in
|
||||
spawn_placeholders.iter()
|
||||
{
|
||||
debug!(
|
||||
"requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||
blupeprint_name.0, name, entity, original_parent
|
||||
);
|
||||
// now insert load tracker
|
||||
if !asset_infos.is_empty() {
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(AssetsToLoad {
|
||||
all_loaded: false,
|
||||
asset_infos,
|
||||
..Default::default()
|
||||
})
|
||||
.insert(BlueprintAssetsNotLoaded);
|
||||
} else {
|
||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
// println!("main model path {:?}", model_path);
|
||||
if blueprints_list.is_some() {
|
||||
let blueprints_list = blueprints_list.unwrap();
|
||||
// println!("blueprints list {:?}", blueprints_list.0.keys());
|
||||
let mut asset_infos: Vec<AssetLoadTracker<Gltf>> = vec![];
|
||||
let library_path =
|
||||
library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0);
|
||||
for (blueprint_name, _) in blueprints_list.0.iter() {
|
||||
let model_file_name = format!("{}.{}", &blueprint_name, &blueprints_config.format);
|
||||
let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str()));
|
||||
for (child_entity, child_entity_name, all_assets) in entities_with_assets.iter(){
|
||||
println!("added assets {:?} to {:?}", all_assets, child_entity_name);
|
||||
if all_assets.is_some() {
|
||||
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||
|
||||
let model_handle: Handle<Gltf> = asset_server.load(model_path.clone());
|
||||
let model_id = model_handle.id();
|
||||
let loaded = asset_server.is_loaded_with_dependencies(model_id);
|
||||
for asset in all_assets.unwrap().0.iter() {
|
||||
let untyped_handle = asset_server.load_untyped(&asset.path);
|
||||
//println!("untyped handle {:?}", untyped_handle);
|
||||
//asset_server.load(asset.path);
|
||||
|
||||
let asset_id = untyped_handle.id();
|
||||
//println!("ID {:?}", asset_id);
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
//println!("Loaded ? {:?}", loaded);
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: model_path.to_string_lossy().into(),
|
||||
id: model_id,
|
||||
name: asset.name.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: model_handle.clone(),
|
||||
handle: untyped_handle.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// if not all assets are already loaded, inject a component to signal that we need them to be loaded
|
||||
|
||||
// now insert load tracker
|
||||
if !asset_infos.is_empty() {
|
||||
commands
|
||||
.entity(entity)
|
||||
.entity(child_entity)
|
||||
.insert(AssetsToLoad {
|
||||
all_loaded: false,
|
||||
asset_infos,
|
||||
|
@ -141,59 +163,66 @@ pub(crate) fn prepare_blueprints(
|
|||
})
|
||||
.insert(BlueprintAssetsNotLoaded);
|
||||
} else {
|
||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
commands.entity(child_entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
} else {
|
||||
// in case there are no blueprintsList, we revert back to the old behaviour
|
||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_for_loaded(
|
||||
pub(crate) fn check_for_loaded2(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &mut AssetsToLoad<Gltf>),
|
||||
(Entity, Option<&Name>, &mut AssetsToLoad),
|
||||
With<BlueprintAssetsNotLoaded>,
|
||||
>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
for (entity,entity_name, 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);
|
||||
tracker.loaded = loaded;
|
||||
if loaded {
|
||||
println!("loading {}: // load state: {:?}", tracker.name, asset_server.load_state(asset_id));
|
||||
|
||||
// FIXME: hack for now
|
||||
let failed = asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed;
|
||||
|
||||
tracker.loaded = loaded || failed;
|
||||
if loaded || failed {
|
||||
loaded_amount += 1;
|
||||
} else {
|
||||
all_loaded = false;
|
||||
}
|
||||
}
|
||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||
// println!("progress: {}",progress);
|
||||
println!("progress: {}",progress);
|
||||
assets_to_load.progress = progress;
|
||||
|
||||
if all_loaded {
|
||||
assets_to_load.all_loaded = true;
|
||||
println!("done with loading {:?}, inserting components", entity_name);
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintAssetsLoaded)
|
||||
.remove::<BlueprintAssetsNotLoaded>();
|
||||
.remove::<BlueprintAssetsNotLoaded>()
|
||||
.remove::<AssetsToLoad>()
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_from_blueprints(
|
||||
|
||||
|
||||
pub(crate) fn spawn_from_blueprints2(
|
||||
spawn_placeholders: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintName,
|
||||
&BlueprintPath,
|
||||
Option<&Transform>,
|
||||
Option<&Parent>,
|
||||
Option<&Library>,
|
||||
Option<&AddToGameWorld>,
|
||||
Option<&Name>,
|
||||
),
|
||||
|
@ -216,33 +245,28 @@ pub(crate) fn spawn_from_blueprints(
|
|||
for (
|
||||
entity,
|
||||
blupeprint_name,
|
||||
blueprint_path,
|
||||
transform,
|
||||
original_parent,
|
||||
library_override,
|
||||
add_to_world,
|
||||
name,
|
||||
) in spawn_placeholders.iter()
|
||||
{
|
||||
debug!(
|
||||
"attempting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||
info!(
|
||||
"attempting to spawn blueprint {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||
blupeprint_name.0, name, entity, original_parent
|
||||
);
|
||||
|
||||
let what = &blupeprint_name.0;
|
||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
||||
|
||||
// library path is either defined at the plugin level or overriden by optional Library components
|
||||
let library_path =
|
||||
library_override.map_or_else(|| &blueprints_config.library_folder, |l| &l.0);
|
||||
let model_path = Path::new(&library_path).join(Path::new(model_file_name.as_str()));
|
||||
|
||||
// info!("attempting to spawn {:?}", model_path);
|
||||
let model_handle: Handle<Gltf> = asset_server.load(model_path.clone()); // FIXME: kinda weird now
|
||||
let model_handle: Handle<Gltf> = asset_server.load(blueprint_path.0.clone()); // FIXME: kinda weird now
|
||||
|
||||
let gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"gltf file {:?} should have been loaded",
|
||||
model_path.to_str()
|
||||
&blueprint_path.0
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -289,3 +313,8 @@ pub(crate) fn spawn_from_blueprints(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -95,8 +95,8 @@ pub(crate) fn spawned_blueprint_post_process(
|
|||
commands.entity(original).remove::<SpawnHere>();
|
||||
commands.entity(original).remove::<Spawned>();
|
||||
commands.entity(original).remove::<Handle<Scene>>();
|
||||
commands.entity(original).remove::<AssetsToLoad<Gltf>>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
||||
commands.entity(original).remove::<BlueprintAssetsLoaded>();
|
||||
//commands.entity(original).remove::<AssetsToLoad>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
||||
//commands.entity(original).remove::<BlueprintAssetsLoaded>();
|
||||
commands.entity(root_entity).despawn_recursive();
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
some text
|
|
@ -1,5 +1,5 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, GameWorldTag};
|
||||
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, BlueprintPath, GameWorldTag};
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{GameState, InAppRunning};
|
||||
|
||||
use bevy_rapier3d::prelude::Velocity;
|
||||
|
@ -11,7 +11,7 @@ pub fn setup_game(
|
|||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
// here we actually spawn our game world/level
|
||||
commands.spawn((
|
||||
/*commands.spawn((
|
||||
SceneBundle {
|
||||
scene: asset_server.load("levels/World.glb#Scene0"),
|
||||
..default()
|
||||
|
@ -19,7 +19,16 @@ pub fn setup_game(
|
|||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));*/
|
||||
|
||||
commands.spawn((
|
||||
BlueprintName("World".into()),
|
||||
BlueprintPath("levels/World.glb".into()),
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use in_game::*;
|
|||
use std::{collections::HashMap, fs, time::Duration};
|
||||
|
||||
use bevy_gltf_blueprints::{
|
||||
BlueprintAnimationPlayerLink, BlueprintName, BlueprintsList, GltfBlueprintsSet, SceneAnimations,
|
||||
AllAssets, BlueprintAnimationPlayerLink, BlueprintName, GltfBlueprintsSet, SceneAnimations
|
||||
};
|
||||
|
||||
use bevy::{
|
||||
|
@ -23,7 +23,7 @@ fn start_game(mut next_app_state: ResMut<NextState<AppState>>) {
|
|||
|
||||
// if the export from Blender worked correctly, we should have animations (simplified here by using AnimationPlayerLink)
|
||||
// if the export from Blender worked correctly, we should have an Entity called "Blueprint4_nested" that has a child called "Blueprint3" that has a "BlueprintName" component with value Blueprint3
|
||||
// if the export from Blender worked correctly, we should have a blueprints_list
|
||||
// if the export from Blender worked correctly, we should have an assets_list
|
||||
// if the export from Blender worked correctly, we should have the correct tree of entities
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
@ -36,7 +36,7 @@ fn validate_export(
|
|||
scene_animations: Query<(Entity, &SceneAnimations)>,
|
||||
empties_candidates: Query<(Entity, &Name, &GlobalTransform)>,
|
||||
|
||||
blueprints_list: Query<(Entity, &BlueprintsList)>,
|
||||
assets_list: Query<(Entity, &AllAssets)>,
|
||||
root: Query<(Entity, &Name, &Children), (Without<Parent>, With<Children>)>,
|
||||
) {
|
||||
let animations_found =
|
||||
|
@ -66,8 +66,8 @@ fn validate_export(
|
|||
break;
|
||||
}
|
||||
}
|
||||
// check if there are blueprints_list components
|
||||
let blueprints_list_found = !blueprints_list.is_empty();
|
||||
// check if there are assets_list components
|
||||
let assets_list_found = !assets_list.is_empty();
|
||||
|
||||
// there should be no entity named xxx____bak as it means an error in the Blender side export process
|
||||
let mut exported_names_correct = true;
|
||||
|
@ -104,8 +104,8 @@ fn validate_export(
|
|||
fs::write(
|
||||
"bevy_diagnostics.json",
|
||||
format!(
|
||||
"{{ \"animations\": {}, \"nested_blueprint_found\": {}, \"empty_found\": {}, \"blueprints_list_found\": {}, \"exported_names_correct\": {} }}",
|
||||
animations_found, nested_blueprint_found, empty_found, blueprints_list_found, exported_names_correct
|
||||
"{{ \"animations\": {}, \"nested_blueprint_found\": {}, \"empty_found\": {}, \"assets_list_found\": {}, \"exported_names_correct\": {} }}",
|
||||
animations_found, nested_blueprint_found, empty_found, assets_list_found, exported_names_correct
|
||||
),
|
||||
)
|
||||
.expect("Unable to write file");
|
||||
|
|
|
@ -116,6 +116,8 @@ General issues:
|
|||
- [ ] remove 'export_marked_assets' it should be a default setting
|
||||
- [x] disable/ hide asset editing ui for external assets
|
||||
- [ ] inject_export_path_into_internal_blueprints should be called on every asset/blueprint scan !! Not just on export
|
||||
- [ ] fix level asets UI
|
||||
- [x] fix level asets UI
|
||||
|
||||
- [x] remove BlueprintsList & replace is with assets list
|
||||
|
||||
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
|
|
@ -108,13 +108,6 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
|||
empty_obj['BlueprintName'] = f'("{blueprint_name}")'
|
||||
empty_obj["BlueprintPath"] = f'("{blueprint_path}")'
|
||||
empty_obj['SpawnHere'] = '()'
|
||||
|
||||
# we also inject a list of all sub blueprints, so that the bevy side can preload them
|
||||
children_per_blueprint = {}
|
||||
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||
if blueprint:
|
||||
children_per_blueprint[blueprint_name] = blueprint.nested_blueprints
|
||||
empty_obj["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})"
|
||||
|
||||
# we copy custom properties over from our original object to our empty
|
||||
for component_name, component_value in object.items():
|
||||
|
|
|
@ -8,6 +8,12 @@ from blenvy.materials.materials_helpers import get_all_materials
|
|||
from .generate_temporary_scene_and_export import generate_temporary_scene_and_export
|
||||
from .export_gltf import (generate_gltf_export_settings)
|
||||
|
||||
# material library logic
|
||||
# To avoid redundant materials (can be very costly, mostly when using high res textures)
|
||||
# - we explore a gltf file containing all materials from a blend file
|
||||
# - we add materialInfo component to each object that uses one of the materials, so that "what material is used by which object" is preserved
|
||||
#
|
||||
|
||||
def clear_material_info(collection_names, library_scenes):
|
||||
for scene in library_scenes:
|
||||
root_collection = scene.collection
|
||||
|
|
|
@ -9,7 +9,7 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
|||
number_of_generated_assets = len(generated_assets)
|
||||
|
||||
header, panel = layout.panel(f"assets{name}", default_closed=True)
|
||||
header.label(text=title + f"({number_of_user_assets + number_of_generated_assets})", icon="ASSET_MANAGER")
|
||||
header.label(text=title + f"({number_of_user_assets})", icon="ASSET_MANAGER")
|
||||
|
||||
|
||||
blueprint_assets = target_type == 'BLUEPRINT'
|
||||
|
@ -42,8 +42,9 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
|||
if editable:
|
||||
row = panel.row()
|
||||
#panel.separator()
|
||||
|
||||
print("here", user_assets)
|
||||
for asset in user_assets:
|
||||
print("asset", asset)
|
||||
row = panel.row()
|
||||
split = row.split(factor=nesting_indent)
|
||||
col = split.column()
|
||||
|
|
|
@ -59,7 +59,7 @@ def setup_data(request):
|
|||
if os.path.exists(screenshot_observed_path):
|
||||
os.remove(screenshot_observed_path)
|
||||
|
||||
request.addfinalizer(finalizer)
|
||||
#request.addfinalizer(finalizer)
|
||||
|
||||
return None
|
||||
|
||||
|
@ -105,7 +105,7 @@ def test_export_complex(setup_data):
|
|||
blenvy.auto_export.auto_export = True
|
||||
blenvy.auto_export.export_scene_settings = True
|
||||
blenvy.auto_export.export_blueprints = True
|
||||
blenvy.auto_export.export_materials_library = True
|
||||
blenvy.auto_export.export_materials_library = False # TODO: switch back
|
||||
|
||||
bpy.data.scenes['World'].blenvy_scene_type = 'Level' # set scene as main/level scene
|
||||
bpy.data.scenes['Library'].blenvy_scene_type = 'Library' # set scene as Library scene
|
||||
|
|
|
@ -53,7 +53,7 @@ def test_export_external_blueprints(setup_data):
|
|||
blenvy.auto_export.auto_export = True
|
||||
blenvy.auto_export.export_scene_settings = True
|
||||
blenvy.auto_export.export_blueprints = True
|
||||
blenvy.auto_export.export_materials_library = True
|
||||
blenvy.auto_export.export_materials_library = False # TODO switch back
|
||||
|
||||
print("SCENES", bpy.data.scenes)
|
||||
for scene in bpy.data.scenes:
|
||||
|
|
Loading…
Reference in New Issue