Compare commits
7 Commits
0cf3ec99cb
...
ed0c85b66e
Author | SHA1 | Date |
---|---|---|
kaosat.dev | ed0c85b66e | |
kaosat.dev | 1fdb45bab6 | |
kaosat.dev | 2a74dedcb8 | |
kaosat.dev | 37f4514b31 | |
kaosat.dev | ba25c3cb20 | |
kaosat.dev | 6f6b813474 | |
kaosat.dev | 29c8eba49c |
|
@ -0,0 +1,63 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use bevy::{asset::LoadedUntypedAsset, gltf::Gltf, prelude::*, utils::HashMap};
|
||||||
|
|
||||||
|
use crate::{BluePrintsConfig, BlueprintAnimations};
|
||||||
|
|
||||||
|
/// 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 MyAsset{
|
||||||
|
pub name: String,
|
||||||
|
pub path: String
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 LocalAssets(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 AllAssets(pub Vec<MyAsset>);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
///
|
||||||
|
/// 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(Debug)]
|
||||||
|
pub(crate) struct AssetLoadTracker {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub name: String,
|
||||||
|
pub id: AssetId<LoadedUntypedAsset>,
|
||||||
|
pub loaded: bool,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub handle: Handle<LoadedUntypedAsset>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// helper component, for tracking loaded assets
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub(crate) struct AssetsToLoad {
|
||||||
|
pub all_loaded: bool,
|
||||||
|
pub asset_infos: Vec<AssetLoadTracker>,
|
||||||
|
pub progress: f32,
|
||||||
|
}
|
||||||
|
impl Default for AssetsToLoad {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
all_loaded: Default::default(),
|
||||||
|
asset_infos: Default::default(),
|
||||||
|
progress: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,9 @@ pub use animation::*;
|
||||||
pub mod aabb;
|
pub mod aabb;
|
||||||
pub use aabb::*;
|
pub use aabb::*;
|
||||||
|
|
||||||
|
pub mod assets;
|
||||||
|
pub use assets::*;
|
||||||
|
|
||||||
pub mod materials;
|
pub mod materials;
|
||||||
pub use materials::*;
|
pub use materials::*;
|
||||||
|
|
||||||
|
@ -32,12 +35,14 @@ pub enum GltfBlueprintsSet {
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct BluePrintBundle {
|
pub struct BluePrintBundle {
|
||||||
pub blueprint: BlueprintName,
|
pub blueprint: BlueprintName,
|
||||||
|
pub blueprint_path: BlueprintPath,
|
||||||
pub spawn_here: SpawnHere,
|
pub spawn_here: SpawnHere,
|
||||||
}
|
}
|
||||||
impl Default for BluePrintBundle {
|
impl Default for BluePrintBundle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
BluePrintBundle {
|
BluePrintBundle {
|
||||||
blueprint: BlueprintName("default".into()),
|
blueprint: BlueprintName("default".into()),
|
||||||
|
blueprint_path: BlueprintPath("".into()),
|
||||||
spawn_here: SpawnHere,
|
spawn_here: SpawnHere,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +117,7 @@ impl Plugin for BlueprintsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins(ComponentsFromGltfPlugin {})
|
app.add_plugins(ComponentsFromGltfPlugin {})
|
||||||
.register_type::<BlueprintName>()
|
.register_type::<BlueprintName>()
|
||||||
|
.register_type::<BlueprintPath>()
|
||||||
.register_type::<MaterialInfo>()
|
.register_type::<MaterialInfo>()
|
||||||
.register_type::<SpawnHere>()
|
.register_type::<SpawnHere>()
|
||||||
.register_type::<BlueprintAnimations>()
|
.register_type::<BlueprintAnimations>()
|
||||||
|
@ -123,7 +129,13 @@ impl Plugin for BlueprintsPlugin {
|
||||||
.register_type::<HashMap<u32, Vec<String>>>()
|
.register_type::<HashMap<u32, Vec<String>>>()
|
||||||
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
||||||
.add_event::<AnimationMarkerReached>()
|
.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>>>()
|
.register_type::<HashMap<String, Vec<String>>>()
|
||||||
.insert_resource(BluePrintsConfig {
|
.insert_resource(BluePrintsConfig {
|
||||||
format: self.format,
|
format: self.format,
|
||||||
|
@ -145,20 +157,24 @@ impl Plugin for BlueprintsPlugin {
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
(
|
test_thingy,
|
||||||
|
check_for_loaded2,
|
||||||
|
spawn_from_blueprints2,
|
||||||
|
|
||||||
|
/*(
|
||||||
prepare_blueprints,
|
prepare_blueprints,
|
||||||
check_for_loaded,
|
check_for_loaded,
|
||||||
spawn_from_blueprints,
|
spawn_from_blueprints,
|
||||||
apply_deferred,
|
apply_deferred,
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),*/
|
||||||
(compute_scene_aabbs, apply_deferred)
|
(compute_scene_aabbs, apply_deferred)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(aabbs_enabled),
|
.run_if(aabbs_enabled),
|
||||||
apply_deferred,
|
apply_deferred,
|
||||||
(
|
(
|
||||||
materials_inject,
|
materials_inject,
|
||||||
check_for_material_loaded,
|
// check_for_material_loaded,
|
||||||
materials_inject2,
|
materials_inject2,
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
|
|
|
@ -17,14 +17,14 @@ use bevy::{
|
||||||
render::mesh::Mesh,
|
render::mesh::Mesh,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{AssetLoadTracker, AssetsToLoad, BluePrintsConfig};
|
use crate::{AssetLoadTracker, AssetsToLoad, BluePrintsConfig, BlueprintInstanceReady};
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// struct containing the name & source of the material to apply
|
/// struct containing the name & path of the material to apply
|
||||||
pub struct MaterialInfo {
|
pub struct MaterialInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub source: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// flag component
|
/// flag component
|
||||||
|
@ -37,21 +37,21 @@ pub(crate) struct BlueprintMaterialAssetsNotLoaded;
|
||||||
/// system that injects / replaces materials from material library
|
/// system that injects / replaces materials from material library
|
||||||
pub(crate) fn materials_inject(
|
pub(crate) fn materials_inject(
|
||||||
blueprints_config: ResMut<BluePrintsConfig>,
|
blueprints_config: ResMut<BluePrintsConfig>,
|
||||||
material_infos: Query<(Entity, &MaterialInfo), Added<MaterialInfo>>,
|
|
||||||
|
ready_blueprints: Query<(Entity, &Children), (With<BlueprintInstanceReady>)>,
|
||||||
|
material_infos: Query<(Entity, &MaterialInfo, &Parent), Added<MaterialInfo>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (entity, material_info) in material_infos.iter() {
|
|
||||||
let model_file_name = format!(
|
|
||||||
"{}_materials_library.{}",
|
|
||||||
&material_info.source, &blueprints_config.format
|
|
||||||
);
|
|
||||||
let materials_path = Path::new(&blueprints_config.material_library_folder)
|
|
||||||
.join(Path::new(model_file_name.as_str()));
|
|
||||||
let material_name = &material_info.name;
|
|
||||||
let material_full_path = materials_path.to_str().unwrap().to_string() + "#" + material_name; // TODO: yikes, cleanup
|
|
||||||
|
|
||||||
if blueprints_config
|
/*for(entity, children) in ready_blueprints.iter() {
|
||||||
|
println!("Blueprint ready !");
|
||||||
|
} */
|
||||||
|
for (entity, material_info, parent) in material_infos.iter() {
|
||||||
|
println!("Entity with material info {:?} {:?}", entity, material_info);
|
||||||
|
let parent_blueprint = ready_blueprints.get(parent.get());
|
||||||
|
println!("Parent blueprint {:?}", parent_blueprint)
|
||||||
|
/*if blueprints_config
|
||||||
.material_library_cache
|
.material_library_cache
|
||||||
.contains_key(&material_full_path)
|
.contains_key(&material_full_path)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +66,9 @@ pub(crate) fn materials_inject(
|
||||||
} else {
|
} else {
|
||||||
let material_file_handle: Handle<Gltf> = asset_server.load(materials_path.clone());
|
let material_file_handle: Handle<Gltf> = asset_server.load(materials_path.clone());
|
||||||
let material_file_id = material_file_handle.id();
|
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,
|
name: material_full_path,
|
||||||
id: material_file_id,
|
id: material_file_id,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
|
@ -81,15 +83,17 @@ pub(crate) fn materials_inject(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.insert(BlueprintMaterialAssetsNotLoaded);
|
.insert(BlueprintMaterialAssetsNotLoaded);
|
||||||
/**/
|
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, merge with check_for_loaded, make generic ?
|
// TODO, merge with check_for_loaded, make generic ?
|
||||||
|
// FIXME: fix this:
|
||||||
|
|
||||||
pub(crate) fn check_for_material_loaded(
|
pub(crate) fn check_for_material_loaded(
|
||||||
mut blueprint_assets_to_load: Query<
|
mut blueprint_assets_to_load: Query<
|
||||||
(Entity, &mut AssetsToLoad<Gltf>),
|
(Entity, &mut AssetsToLoad),
|
||||||
With<BlueprintMaterialAssetsNotLoaded>,
|
With<BlueprintMaterialAssetsNotLoaded>,
|
||||||
>,
|
>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
@ -148,7 +152,7 @@ pub(crate) fn materials_inject2(
|
||||||
for (material_info, children) in material_infos.iter() {
|
for (material_info, children) in material_infos.iter() {
|
||||||
let model_file_name = format!(
|
let model_file_name = format!(
|
||||||
"{}_materials_library.{}",
|
"{}_materials_library.{}",
|
||||||
&material_info.source, &blueprints_config.format
|
&material_info.path, &blueprints_config.format
|
||||||
);
|
);
|
||||||
let materials_path = Path::new(&blueprints_config.material_library_folder)
|
let materials_path = Path::new(&blueprints_config.material_library_folder)
|
||||||
.join(Path::new(model_file_name.as_str()));
|
.join(Path::new(model_file_name.as_str()));
|
||||||
|
|
|
@ -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 bevy::{gltf::Gltf, prelude::*, utils::HashMap};
|
||||||
|
|
||||||
use crate::{BluePrintsConfig, BlueprintAnimations};
|
use crate::{AllAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||||
|
|
||||||
/// this is a flag component for our levels/game world
|
/// this is a flag component for our levels/game world
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
@ -13,6 +13,11 @@ pub struct GameWorldTag;
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintName(pub String);
|
pub struct BlueprintName(pub String);
|
||||||
|
|
||||||
|
/// path component for the blueprints
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct BlueprintPath(pub String);
|
||||||
|
|
||||||
/// flag component needed to signify the intent to spawn a Blueprint
|
/// flag component needed to signify the intent to spawn a Blueprint
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
|
@ -22,6 +27,13 @@ pub struct SpawnHere;
|
||||||
/// flag component for dynamically spawned scenes
|
/// flag component for dynamically spawned scenes
|
||||||
pub struct Spawned;
|
pub struct Spawned;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
/// flag component added when a Blueprint instance ist Ready : ie :
|
||||||
|
/// - its assets have loaded
|
||||||
|
/// - it has finished spawning
|
||||||
|
pub struct BlueprintInstanceReady;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// flag component marking any spwaned child of blueprints ..unless the original entity was marked with the `NoInBlueprint` marker component
|
/// flag component marking any spwaned child of blueprints ..unless the original entity was marked with the `NoInBlueprint` marker component
|
||||||
|
@ -46,100 +58,111 @@ pub struct AddToGameWorld;
|
||||||
/// helper component, just to transfer child data
|
/// helper component, just to transfer child data
|
||||||
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
||||||
|
|
||||||
/// 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>>);
|
|
||||||
|
|
||||||
/// 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
|
pub(crate) fn test_thingy(
|
||||||
#[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<
|
spawn_placeholders: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
&BlueprintPath,
|
||||||
|
),
|
||||||
|
(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,
|
Entity,
|
||||||
&BlueprintName,
|
/*&BlueprintName,
|
||||||
Option<&Parent>,
|
&BlueprintPath,
|
||||||
Option<&Library>,
|
Option<&Parent>,*/
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
Option<&BlueprintsList>,
|
Option<&AllAssets>,
|
||||||
),
|
),
|
||||||
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
(Added<AllAssets>), // Added<AllAssets>
|
||||||
>,
|
>,
|
||||||
|
|
||||||
mut commands: Commands,
|
|
||||||
asset_server: Res<AssetServer>,
|
bla_bla : Query<
|
||||||
blueprints_config: Res<BluePrintsConfig>,
|
(Entity,
|
||||||
|
&BlueprintName,
|
||||||
|
&BlueprintPath,
|
||||||
|
Option<&Parent>,),(Added<BlueprintPath>)
|
||||||
|
>,
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
for (entity, blupeprint_name, original_parent, library_override, name, blueprints_list) in
|
for (entity, blueprint_path) in spawn_placeholders.iter() {
|
||||||
spawn_placeholders.iter()
|
//println!("added blueprint_path {:?}", blueprint_path);
|
||||||
{
|
/*commands.entity(entity).insert(
|
||||||
debug!(
|
SceneBundle {
|
||||||
"requesting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
scene: asset_server.load(format!("{}#Scene0", &blueprint_path.0)), // "levels/World.glb#Scene0"),
|
||||||
blupeprint_name.0, name, entity, original_parent
|
..default()
|
||||||
);
|
},
|
||||||
|
);*/
|
||||||
|
// let model_handle: Handle<Gltf> = asset_server.load(model_path.clone());
|
||||||
|
}
|
||||||
|
|
||||||
// println!("main model path {:?}", model_path);
|
for (entity, blueprint_name, blueprint_path, parent) in bla_bla.iter() {
|
||||||
if blueprints_list.is_some() {
|
println!("added blueprint to spawn {:?} {:?}", blueprint_name, blueprint_path);
|
||||||
let blueprints_list = blueprints_list.unwrap();
|
let untyped_handle = asset_server.load_untyped(&blueprint_path.0);
|
||||||
// println!("blueprints list {:?}", blueprints_list.0.keys());
|
let asset_id = untyped_handle.id();
|
||||||
let mut asset_infos: Vec<AssetLoadTracker<Gltf>> = vec![];
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
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 mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||||
let model_id = model_handle.id();
|
if !loaded {
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(model_id);
|
asset_infos.push(AssetLoadTracker {
|
||||||
|
name: blueprint_name.0.clone(),
|
||||||
|
id: asset_id,
|
||||||
|
loaded: false,
|
||||||
|
handle: untyped_handle.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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![];
|
||||||
|
|
||||||
|
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 {
|
if !loaded {
|
||||||
asset_infos.push(AssetLoadTracker {
|
asset_infos.push(AssetLoadTracker {
|
||||||
name: model_path.to_string_lossy().into(),
|
name: asset.name.clone(),
|
||||||
id: model_id,
|
id: asset_id,
|
||||||
loaded: false,
|
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() {
|
if !asset_infos.is_empty() {
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(child_entity)
|
||||||
.insert(AssetsToLoad {
|
.insert(AssetsToLoad {
|
||||||
all_loaded: false,
|
all_loaded: false,
|
||||||
asset_infos,
|
asset_infos,
|
||||||
|
@ -147,59 +170,66 @@ pub(crate) fn prepare_blueprints(
|
||||||
})
|
})
|
||||||
.insert(BlueprintAssetsNotLoaded);
|
.insert(BlueprintAssetsNotLoaded);
|
||||||
} else {
|
} 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<
|
mut blueprint_assets_to_load: Query<
|
||||||
(Entity, &mut AssetsToLoad<Gltf>),
|
(Entity, Option<&Name>, &mut AssetsToLoad),
|
||||||
With<BlueprintAssetsNotLoaded>,
|
With<BlueprintAssetsNotLoaded>,
|
||||||
>,
|
>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
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 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);
|
||||||
tracker.loaded = loaded;
|
println!("loading {}: // load state: {:?}", tracker.name, asset_server.load_state(asset_id));
|
||||||
if loaded {
|
|
||||||
|
// 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;
|
loaded_amount += 1;
|
||||||
} else {
|
} else {
|
||||||
all_loaded = false;
|
all_loaded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||||
// println!("progress: {}",progress);
|
println!("progress: {}",progress);
|
||||||
assets_to_load.progress = progress;
|
assets_to_load.progress = progress;
|
||||||
|
|
||||||
if all_loaded {
|
if all_loaded {
|
||||||
assets_to_load.all_loaded = true;
|
assets_to_load.all_loaded = true;
|
||||||
|
println!("done with loading {:?}, inserting components", entity_name);
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintAssetsLoaded)
|
.insert(BlueprintAssetsLoaded)
|
||||||
.remove::<BlueprintAssetsNotLoaded>();
|
.remove::<BlueprintAssetsNotLoaded>()
|
||||||
|
.remove::<AssetsToLoad>()
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn spawn_from_blueprints(
|
|
||||||
|
|
||||||
|
pub(crate) fn spawn_from_blueprints2(
|
||||||
spawn_placeholders: Query<
|
spawn_placeholders: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&BlueprintName,
|
&BlueprintName,
|
||||||
|
&BlueprintPath,
|
||||||
Option<&Transform>,
|
Option<&Transform>,
|
||||||
Option<&Parent>,
|
Option<&Parent>,
|
||||||
Option<&Library>,
|
|
||||||
Option<&AddToGameWorld>,
|
Option<&AddToGameWorld>,
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
),
|
),
|
||||||
|
@ -222,33 +252,28 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
blupeprint_name,
|
blupeprint_name,
|
||||||
|
blueprint_path,
|
||||||
transform,
|
transform,
|
||||||
original_parent,
|
original_parent,
|
||||||
library_override,
|
|
||||||
add_to_world,
|
add_to_world,
|
||||||
name,
|
name,
|
||||||
) in spawn_placeholders.iter()
|
) in spawn_placeholders.iter()
|
||||||
{
|
{
|
||||||
debug!(
|
info!(
|
||||||
"attempting to spawn {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
"attempting to spawn blueprint {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||||
blupeprint_name.0, name, entity, original_parent
|
blupeprint_name.0, name, entity, original_parent
|
||||||
);
|
);
|
||||||
|
|
||||||
let what = &blupeprint_name.0;
|
let what = &blupeprint_name.0;
|
||||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
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);
|
// 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(|| {
|
let gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"gltf file {:?} should have been loaded",
|
"gltf file {:?} should have been loaded",
|
||||||
model_path.to_str()
|
&blueprint_path.0
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -280,6 +305,7 @@ pub(crate) fn spawn_from_blueprints(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Spawned,
|
Spawned,
|
||||||
|
BlueprintInstanceReady, // FIXME: not sure if this is should be added here or in the post process
|
||||||
OriginalChildren(original_children),
|
OriginalChildren(original_children),
|
||||||
BlueprintAnimations {
|
BlueprintAnimations {
|
||||||
// these are animations specific to the inside of the blueprint
|
// these are animations specific to the inside of the blueprint
|
||||||
|
@ -295,3 +321,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::<SpawnHere>();
|
||||||
commands.entity(original).remove::<Spawned>();
|
commands.entity(original).remove::<Spawned>();
|
||||||
commands.entity(original).remove::<Handle<Scene>>();
|
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::<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(original).remove::<BlueprintAssetsLoaded>();
|
||||||
commands.entity(root_entity).despawn_recursive();
|
commands.entity(root_entity).despawn_recursive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
some text
|
|
@ -1,5 +1,5 @@
|
||||||
use bevy::prelude::*;
|
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_gltf_worlflow_examples_common_rapier::{GameState, InAppRunning};
|
||||||
|
|
||||||
use bevy_rapier3d::prelude::Velocity;
|
use bevy_rapier3d::prelude::Velocity;
|
||||||
|
@ -11,7 +11,7 @@ pub fn setup_game(
|
||||||
mut next_game_state: ResMut<NextState<GameState>>,
|
mut next_game_state: ResMut<NextState<GameState>>,
|
||||||
) {
|
) {
|
||||||
// here we actually spawn our game world/level
|
// here we actually spawn our game world/level
|
||||||
commands.spawn((
|
/*commands.spawn((
|
||||||
SceneBundle {
|
SceneBundle {
|
||||||
scene: asset_server.load("levels/World.glb#Scene0"),
|
scene: asset_server.load("levels/World.glb#Scene0"),
|
||||||
..default()
|
..default()
|
||||||
|
@ -19,7 +19,16 @@ pub fn setup_game(
|
||||||
bevy::prelude::Name::from("world"),
|
bevy::prelude::Name::from("world"),
|
||||||
GameWorldTag,
|
GameWorldTag,
|
||||||
InAppRunning,
|
InAppRunning,
|
||||||
|
));*/
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
BlueprintName("World".into()),
|
||||||
|
BlueprintPath("levels/World.glb".into()),
|
||||||
|
bevy::prelude::Name::from("world"),
|
||||||
|
GameWorldTag,
|
||||||
|
InAppRunning,
|
||||||
));
|
));
|
||||||
|
|
||||||
next_game_state.set(GameState::InGame)
|
next_game_state.set(GameState::InGame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub use in_game::*;
|
||||||
use std::{collections::HashMap, fs, time::Duration};
|
use std::{collections::HashMap, fs, time::Duration};
|
||||||
|
|
||||||
use bevy_gltf_blueprints::{
|
use bevy_gltf_blueprints::{
|
||||||
BlueprintAnimationPlayerLink, BlueprintName, BlueprintsList, GltfBlueprintsSet, SceneAnimations,
|
AllAssets, BlueprintAnimationPlayerLink, BlueprintName, GltfBlueprintsSet, SceneAnimations
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy::{
|
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 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 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
|
// if the export from Blender worked correctly, we should have the correct tree of entities
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
|
@ -36,7 +36,7 @@ fn validate_export(
|
||||||
scene_animations: Query<(Entity, &SceneAnimations)>,
|
scene_animations: Query<(Entity, &SceneAnimations)>,
|
||||||
empties_candidates: Query<(Entity, &Name, &GlobalTransform)>,
|
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>)>,
|
root: Query<(Entity, &Name, &Children), (Without<Parent>, With<Children>)>,
|
||||||
) {
|
) {
|
||||||
let animations_found =
|
let animations_found =
|
||||||
|
@ -66,8 +66,8 @@ fn validate_export(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if there are blueprints_list components
|
// check if there are assets_list components
|
||||||
let blueprints_list_found = !blueprints_list.is_empty();
|
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
|
// 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;
|
let mut exported_names_correct = true;
|
||||||
|
@ -104,8 +104,8 @@ fn validate_export(
|
||||||
fs::write(
|
fs::write(
|
||||||
"bevy_diagnostics.json",
|
"bevy_diagnostics.json",
|
||||||
format!(
|
format!(
|
||||||
"{{ \"animations\": {}, \"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, blueprints_list_found, exported_names_correct
|
animations_found, nested_blueprint_found, empty_found, assets_list_found, exported_names_correct
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.expect("Unable to write file");
|
.expect("Unable to write file");
|
||||||
|
|
|
@ -15,7 +15,7 @@ Auto export
|
||||||
- [x] main/ library scene names
|
- [x] main/ library scene names
|
||||||
- [x] paths
|
- [x] paths
|
||||||
|
|
||||||
Data storage for custom properties:
|
- [ ] Data storage for custom properties:
|
||||||
- for scenes (main scenes)
|
- for scenes (main scenes)
|
||||||
- at scene level
|
- at scene level
|
||||||
- for blueprints
|
- for blueprints
|
||||||
|
@ -106,6 +106,22 @@ General issues:
|
||||||
- [x] add ability to FORCE export specific blueprints & levels
|
- [x] add ability to FORCE export specific blueprints & levels
|
||||||
- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this
|
- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this
|
||||||
- [ ] handle scene renames between saves (breaks diffing)
|
- [ ] handle scene renames between saves (breaks diffing)
|
||||||
- [ ] change scene selector to work on actual scenes aka to deal with renamed scenes
|
- [x] change scene selector to work on actual scenes aka to deal with renamed scenes
|
||||||
|
- [x] remove get_main_and_library_scenes as it should not be needed anymore
|
||||||
- [x] fix asset file selection
|
- [x] fix asset file selection
|
||||||
- [x] change "assets" tab to "levels"/worlds tab & modify UI accordingly
|
- [x] change "assets" tab to "levels"/worlds tab & modify UI accordingly
|
||||||
|
- [ ] add option to 'split out' meshes from blueprints ?
|
||||||
|
- [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs
|
||||||
|
|
||||||
|
- [x] 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
|
||||||
|
- [x] fix level asets UI
|
||||||
|
- [ ] persist exported materials path in blueprints so that it can be read from library file users
|
||||||
|
- [ ] just like "export_path" write it into each blueprint's collection
|
||||||
|
- [ ] scan for used materials per blueprint !
|
||||||
|
- [ ] for scenes, scan for used materials of all non instance objects (TODO: what about overrides ?)
|
||||||
|
|
||||||
|
- [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
|
|
@ -50,9 +50,8 @@ from .blueprints.operators import OT_select_blueprint
|
||||||
# blenvy core
|
# blenvy core
|
||||||
from .core.blenvy_manager import BlenvyManager
|
from .core.blenvy_manager import BlenvyManager
|
||||||
from .core.operators import OT_switch_bevy_tooling
|
from .core.operators import OT_switch_bevy_tooling
|
||||||
from .core.scene_helpers import (SceneSelector)
|
|
||||||
from .core.ui.ui import (BLENVY_PT_SidePanel)
|
from .core.ui.ui import (BLENVY_PT_SidePanel)
|
||||||
from .core.ui.scenes_list import SCENES_LIST_OT_actions, SCENE_UL_Blenvy
|
from .core.ui.scenes_list import SCENES_LIST_OT_actions
|
||||||
from .core.ui.assets_folder_browser import OT_OpenAssetsFolderBrowser
|
from .core.ui.assets_folder_browser import OT_OpenAssetsFolderBrowser
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +62,6 @@ def glTF2_post_export_callback(data):
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
# common/core
|
# common/core
|
||||||
SceneSelector,
|
|
||||||
SCENE_UL_Blenvy,
|
|
||||||
SCENES_LIST_OT_actions,
|
SCENES_LIST_OT_actions,
|
||||||
OT_OpenAssetsFolderBrowser,
|
OT_OpenAssetsFolderBrowser,
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,12 @@ 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
|
||||||
|
|
||||||
|
def assets_to_fake_ron(list_like):
|
||||||
|
result = []
|
||||||
|
for item in list_like:
|
||||||
|
result.append(f"(name: \"{item['name']}\", path: \"{item['path']}\")")
|
||||||
|
return result#.join(", ")
|
||||||
|
|
||||||
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")
|
||||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||||
|
@ -15,7 +21,7 @@ def export_blueprints(blueprints, settings, blueprints_data):
|
||||||
|
|
||||||
for blueprint in blueprints:
|
for blueprint in blueprints:
|
||||||
print("exporting collection", blueprint.name)
|
print("exporting collection", blueprint.name)
|
||||||
gltf_output_path = os.path.join(blueprints_path_full, blueprint.name)
|
gltf_output_path = os.path.join(blueprints_path_full, blueprint.name) # TODO: reuse the export_path custom property ?
|
||||||
gltf_export_settings = { **gltf_export_settings, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
|
gltf_export_settings = { **gltf_export_settings, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
|
||||||
|
|
||||||
# if we are using the material library option, do not export materials, use placeholder instead
|
# if we are using the material library option, do not export materials, use placeholder instead
|
||||||
|
@ -23,10 +29,23 @@ def export_blueprints(blueprints, settings, blueprints_data):
|
||||||
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
|
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
|
||||||
|
|
||||||
collection = bpy.data.collections[blueprint.name]
|
collection = bpy.data.collections[blueprint.name]
|
||||||
|
|
||||||
|
print("BLUEPRINT", blueprint.name)
|
||||||
|
|
||||||
|
for asset in collection.user_assets:
|
||||||
|
print(" user asset", asset.name, asset.path)
|
||||||
|
|
||||||
|
all_assets = []
|
||||||
|
auto_assets = []
|
||||||
|
collection["local_assets"] = assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets)
|
||||||
|
collection["AllAssets"] = assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in collection.user_assets]) #all_assets + [{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets)
|
||||||
|
|
||||||
|
|
||||||
# do the actual export
|
# do the actual export
|
||||||
generate_temporary_scene_and_export(
|
generate_temporary_scene_and_export(
|
||||||
settings,
|
settings,
|
||||||
temp_scene_name=TEMPSCENE_PREFIX+collection.name,
|
temp_scene_name=TEMPSCENE_PREFIX+collection.name,
|
||||||
|
additional_data = collection,
|
||||||
gltf_export_settings=gltf_export_settings,
|
gltf_export_settings=gltf_export_settings,
|
||||||
gltf_output_path=gltf_output_path,
|
gltf_output_path=gltf_output_path,
|
||||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
|
||||||
from blenvy.blueprints.blueprint_helpers import find_blueprints_not_on_disk
|
from blenvy.blueprints.blueprint_helpers import find_blueprints_not_on_disk
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +12,6 @@ def get_blueprints_to_export(changes_per_scene, changed_export_parameters, bluep
|
||||||
change_detection = getattr(settings.auto_export, "change_detection")
|
change_detection = getattr(settings.auto_export, "change_detection")
|
||||||
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
||||||
|
|
||||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
|
||||||
internal_blueprints = blueprints_data.internal_blueprints
|
internal_blueprints = blueprints_data.internal_blueprints
|
||||||
blueprints_to_export = internal_blueprints # just for clarity
|
blueprints_to_export = internal_blueprints # just for clarity
|
||||||
|
|
||||||
|
@ -28,7 +26,7 @@ def get_blueprints_to_export(changes_per_scene, changed_export_parameters, bluep
|
||||||
# in your current Blender session for example)
|
# in your current Blender session for example)
|
||||||
blueprints_not_on_disk = find_blueprints_not_on_disk(internal_blueprints, blueprints_path_full, export_gltf_extension)
|
blueprints_not_on_disk = find_blueprints_not_on_disk(internal_blueprints, blueprints_path_full, export_gltf_extension)
|
||||||
|
|
||||||
for scene in library_scenes:
|
for scene in settings.library_scenes:
|
||||||
if scene.name in changes_per_scene:
|
if scene.name in changes_per_scene:
|
||||||
changed_objects = list(changes_per_scene[scene.name].keys())
|
changed_objects = list(changes_per_scene[scene.name].keys())
|
||||||
changed_blueprints = [blueprints_data.blueprints_from_objects[changed] for changed in changed_objects if changed in blueprints_data.blueprints_from_objects]
|
changed_blueprints = [blueprints_data.blueprints_from_objects[changed] for changed in changed_objects if changed in blueprints_data.blueprints_from_objects]
|
||||||
|
|
|
@ -3,7 +3,6 @@ import os
|
||||||
import bpy
|
import bpy
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
|
||||||
from blenvy.blueprints.blueprints_scan import blueprints_scan
|
from blenvy.blueprints.blueprints_scan import blueprints_scan
|
||||||
from blenvy.blueprints.blueprint_helpers import inject_export_path_into_internal_blueprints
|
from blenvy.blueprints.blueprint_helpers import inject_export_path_into_internal_blueprints
|
||||||
|
|
||||||
|
@ -39,8 +38,6 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
|
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
|
||||||
settings.export_gltf_extension = gltf_extension
|
settings.export_gltf_extension = gltf_extension
|
||||||
|
|
||||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
|
||||||
|
|
||||||
blueprints_data = bpy.context.window_manager.blueprints_registry.refresh_blueprints()
|
blueprints_data = bpy.context.window_manager.blueprints_registry.refresh_blueprints()
|
||||||
#blueprints_data = bpy.context.window_manager.blueprints_registry.blueprints_data
|
#blueprints_data = bpy.context.window_manager.blueprints_registry.blueprints_data
|
||||||
#print("blueprints_data", blueprints_data)
|
#print("blueprints_data", blueprints_data)
|
||||||
|
@ -58,7 +55,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
|
|
||||||
if export_scene_settings:
|
if export_scene_settings:
|
||||||
# inject/ update scene components
|
# inject/ update scene components
|
||||||
upsert_scene_components(level_scenes)
|
upsert_scene_components(settings.main_scenes)
|
||||||
#inject/ update light shadow information
|
#inject/ update light shadow information
|
||||||
for light in bpy.data.lights:
|
for light in bpy.data.lights:
|
||||||
enabled = 'true' if light.use_shadow else 'false'
|
enabled = 'true' if light.use_shadow else 'false'
|
||||||
|
@ -76,7 +73,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
# since materials export adds components we need to call this before blueprints are exported
|
# since materials export adds components we need to call this before blueprints are exported
|
||||||
# export materials & inject materials components into relevant objects
|
# export materials & inject materials components into relevant objects
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
export_materials(blueprints_data.blueprint_names, library_scenes, settings)
|
export_materials(blueprints_data.blueprint_names, settings.library_scenes, settings)
|
||||||
|
|
||||||
# update the list of tracked exports
|
# update the list of tracked exports
|
||||||
exports_total = len(blueprints_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0)
|
exports_total = len(blueprints_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0)
|
||||||
|
@ -108,7 +105,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
print("export MAIN scenes")
|
print("export MAIN scenes")
|
||||||
for scene_name in main_scenes_to_export:
|
for scene_name in main_scenes_to_export:
|
||||||
print(" exporting scene:", scene_name)
|
print(" exporting scene:", scene_name)
|
||||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, blueprints_data)
|
export_main_scene(bpy.data.scenes[scene_name], settings, blueprints_data)
|
||||||
|
|
||||||
# now deal with blueprints/collections
|
# now deal with blueprints/collections
|
||||||
do_export_library_scene = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
|
do_export_library_scene = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
|
||||||
|
@ -123,11 +120,11 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
for obj in old_selections:
|
for obj in old_selections:
|
||||||
obj.select_set(True)
|
obj.select_set(True)
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
cleanup_materials(blueprints_data.blueprint_names, library_scenes)
|
cleanup_materials(blueprints_data.blueprint_names, settings.library_scenes)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for scene_name in main_scene_names:
|
for scene in settings.main_scenes:
|
||||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, [])
|
export_main_scene(scene, settings, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,9 +138,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# FIXME: error handling ? also redundant
|
# FIXME: error handling ? also redundant
|
||||||
[main_scene_names, main_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
|
||||||
|
|
||||||
if export_scene_settings:
|
if export_scene_settings:
|
||||||
# inject/ update scene components
|
# inject/ update scene components
|
||||||
remove_scene_components(main_scenes)
|
remove_scene_components(settings.main_scenes)
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,8 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
||||||
original_collection = object.instance_collection
|
original_collection = object.instance_collection
|
||||||
original_name = object.name
|
original_name = object.name
|
||||||
blueprint_name = original_collection.name
|
blueprint_name = original_collection.name
|
||||||
|
# FIXME: blueprint path is WRONG !
|
||||||
|
print("BLUEPRINT PATH", original_collection.get('export_path', None))
|
||||||
blueprint_path = original_collection['export_path'] if 'export_path' in original_collection else f'./{blueprint_name}' # TODO: the default requires the currently used extension !!
|
blueprint_path = original_collection['export_path'] if 'export_path' in original_collection else f'./{blueprint_name}' # TODO: the default requires the currently used extension !!
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,13 +108,6 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
||||||
empty_obj['BlueprintName'] = f'("{blueprint_name}")'
|
empty_obj['BlueprintName'] = f'("{blueprint_name}")'
|
||||||
empty_obj["BlueprintPath"] = f'("{blueprint_path}")'
|
empty_obj["BlueprintPath"] = f'("{blueprint_path}")'
|
||||||
empty_obj['SpawnHere'] = '()'
|
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
|
# we copy custom properties over from our original object to our empty
|
||||||
for component_name, component_value in object.items():
|
for component_name, component_value in object.items():
|
||||||
|
|
|
@ -4,10 +4,16 @@ from pathlib import Path
|
||||||
|
|
||||||
from blenvy.core.helpers_collections import (traverse_tree)
|
from blenvy.core.helpers_collections import (traverse_tree)
|
||||||
from blenvy.core.object_makers import make_cube
|
from blenvy.core.object_makers import make_cube
|
||||||
from blenvy.materials.materials_helpers import get_all_materials
|
from blenvy.materials.materials_helpers import add_material_info_to_objects, get_all_materials
|
||||||
from .generate_temporary_scene_and_export import generate_temporary_scene_and_export
|
from .generate_temporary_scene_and_export import generate_temporary_scene_and_export
|
||||||
from .export_gltf import (generate_gltf_export_settings)
|
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):
|
def clear_material_info(collection_names, library_scenes):
|
||||||
for scene in library_scenes:
|
for scene in library_scenes:
|
||||||
root_collection = scene.collection
|
root_collection = scene.collection
|
||||||
|
@ -63,8 +69,8 @@ def export_materials(collections, library_scenes, settings):
|
||||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||||
materials_path_full = getattr(settings,"materials_path_full")
|
materials_path_full = getattr(settings,"materials_path_full")
|
||||||
|
|
||||||
used_material_names = get_all_materials(collections, library_scenes)
|
(used_material_names, materials_per_object) = get_all_materials(collections, library_scenes)
|
||||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
add_material_info_to_objects(materials_per_object, settings)
|
||||||
|
|
||||||
gltf_export_settings = { **gltf_export_settings,
|
gltf_export_settings = { **gltf_export_settings,
|
||||||
'use_active_scene': True,
|
'use_active_scene': True,
|
||||||
|
@ -74,8 +80,9 @@ def export_materials(collections, library_scenes, settings):
|
||||||
'use_renderable': False,
|
'use_renderable': False,
|
||||||
'export_apply':True
|
'export_apply':True
|
||||||
}
|
}
|
||||||
|
|
||||||
gltf_output_path = os.path.join(materials_path_full, current_project_name + "_materials_library")
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
|
gltf_output_path = os.path.join(materials_path_full, current_project_name + "_materials")
|
||||||
|
|
||||||
print(" exporting Materials to", gltf_output_path, ".gltf/glb")
|
print(" exporting Materials to", gltf_output_path, ".gltf/glb")
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import json
|
||||||
import bpy
|
import bpy
|
||||||
from blenvy.core.helpers_collections import (set_active_collection)
|
from blenvy.core.helpers_collections import (set_active_collection)
|
||||||
from blenvy.core.object_makers import (make_empty)
|
from blenvy.core.object_makers import (make_empty)
|
||||||
from .duplicate_object import duplicate_object
|
from .duplicate_object import duplicate_object
|
||||||
from .export_gltf import export_gltf
|
from .export_gltf import export_gltf
|
||||||
|
from blenvy.core.scene_helpers import add_scene_property
|
||||||
|
|
||||||
"""
|
"""
|
||||||
generates a temporary scene, fills it with data, cleans up after itself
|
generates a temporary scene, fills it with data, cleans up after itself
|
||||||
|
@ -12,11 +14,30 @@ generates a temporary scene, fills it with data, cleans up after itself
|
||||||
* cleaned up using tempScene_cleaner
|
* cleaned up using tempScene_cleaner
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
|
def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None, additional_data=None):
|
||||||
|
|
||||||
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
|
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
|
||||||
temp_root_collection = temp_scene.collection
|
temp_root_collection = temp_scene.collection
|
||||||
|
|
||||||
|
print("additional_dataAAAAAAAAAAAAAAAH", additional_data)
|
||||||
|
if additional_data is not None: # FIXME not a fan of having this here
|
||||||
|
for entry in dict(additional_data):
|
||||||
|
print("entry in additional data", entry)
|
||||||
|
if entry == "local_assets":
|
||||||
|
temp_scene["local_assets"] = additional_data[entry] # this is for bevy 0.14
|
||||||
|
temp_root_collection["local_assets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
||||||
|
bla = "[(name: \"test_asset\", path: \"audio/fake.mp3\")]"
|
||||||
|
local_assets = additional_data.get(entry, [])
|
||||||
|
local_assets = [entry for entry in local_assets]
|
||||||
|
add_scene_property(temp_scene, 'assets_components', {"LocalAssets": f"LocalAssets({local_assets})".replace("'", '')})
|
||||||
|
|
||||||
|
if entry == entry == "AllAssets":
|
||||||
|
temp_scene["AllAssets"] = additional_data[entry]
|
||||||
|
temp_root_collection["AllAssets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
||||||
|
all_assets = additional_data.get(entry, [])
|
||||||
|
all_assets = [entry for entry in all_assets]
|
||||||
|
add_scene_property(temp_scene, 'assets_components', {"AllAssets": f"AllAssets({all_assets})".replace("'", '')})
|
||||||
|
|
||||||
# save active scene
|
# save active scene
|
||||||
original_scene = bpy.context.window.scene
|
original_scene = bpy.context.window.scene
|
||||||
# and selected collection
|
# and selected collection
|
||||||
|
@ -43,6 +64,7 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out
|
||||||
scene_filler_data = tempScene_filler(temp_root_collection)
|
scene_filler_data = tempScene_filler(temp_root_collection)
|
||||||
# export the temporary scene
|
# export the temporary scene
|
||||||
try:
|
try:
|
||||||
|
print("dry_run MODE", settings.auto_export.dry_run)
|
||||||
if settings.auto_export.dry_run == "DISABLED":
|
if settings.auto_export.dry_run == "DISABLED":
|
||||||
export_gltf(gltf_output_path, gltf_export_settings)
|
export_gltf(gltf_output_path, gltf_export_settings)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
|
|
@ -15,9 +15,10 @@ def prepare_and_export():
|
||||||
# determine changed objects
|
# determine changed objects
|
||||||
per_scene_changes = get_changes_per_scene(settings=blenvy)
|
per_scene_changes = get_changes_per_scene(settings=blenvy)
|
||||||
# determine changed parameters
|
# determine changed parameters
|
||||||
setting_changes = False # get_setting_changes()
|
setting_changes = get_setting_changes()
|
||||||
|
print("setting_changes", setting_changes)
|
||||||
# do the actual export
|
# do the actual export
|
||||||
blenvy.auto_export.dry_run = 'NO_EXPORT'#'DISABLED'#
|
# blenvy.auto_export.dry_run = 'NO_EXPORT'#'DISABLED'#
|
||||||
auto_export(per_scene_changes, setting_changes, blenvy)
|
auto_export(per_scene_changes, setting_changes, blenvy)
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
|
|
|
@ -21,7 +21,6 @@ parameter_names_whitelist_auto_export = [
|
||||||
'export_separate_dynamic_and_static_objects',
|
'export_separate_dynamic_and_static_objects',
|
||||||
'export_materials_library',
|
'export_materials_library',
|
||||||
'collection_instances_combine_mode',
|
'collection_instances_combine_mode',
|
||||||
'export_marked_assets'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_setting_changes():
|
def get_setting_changes():
|
||||||
|
@ -37,6 +36,7 @@ def get_setting_changes():
|
||||||
|
|
||||||
previous_gltf_settings = load_settings(".blenvy_gltf_settings_previous")
|
previous_gltf_settings = load_settings(".blenvy_gltf_settings_previous")
|
||||||
current_gltf_settings = load_settings(".blenvy_gltf_settings")
|
current_gltf_settings = load_settings(".blenvy_gltf_settings")
|
||||||
|
print("previous_gltf_settings", previous_gltf_settings, "current_gltf_settings", current_gltf_settings)
|
||||||
gltf_settings_changed = not are_settings_identical(previous_gltf_settings, current_gltf_settings)
|
gltf_settings_changed = not are_settings_identical(previous_gltf_settings, current_gltf_settings)
|
||||||
|
|
||||||
# write the new settings to the old settings
|
# write the new settings to the old settings
|
||||||
|
|
|
@ -83,7 +83,7 @@ class AutoExportTracker(PropertyGroup):
|
||||||
print("last operators", ops)
|
print("last operators", ops)
|
||||||
for op in ops:
|
for op in ops:
|
||||||
print("operator", op)"""
|
print("operator", op)"""
|
||||||
active_operator = getattr(bpy.context.active_operator, 'active_operator' , None)
|
active_operator = getattr(bpy.context, 'active_operator' , None)
|
||||||
if active_operator is not None:
|
if active_operator is not None:
|
||||||
#print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
#print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
||||||
if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "gltf_auto_export":
|
if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "gltf_auto_export":
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import bpy
|
||||||
from blenvy.blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
from blenvy.blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
||||||
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
|
||||||
|
|
||||||
def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
def assets_to_fake_ron(list_like):
|
||||||
|
result = []
|
||||||
|
for item in list_like:
|
||||||
|
result.append(f"(name: \"{item['name']}\", path: \"{item['path']}\")")
|
||||||
|
return result#.join(", ")
|
||||||
|
|
||||||
|
|
||||||
|
def export_main_scene(scene, settings, blueprints_data):
|
||||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||||
assets_path_full = getattr(settings,"assets_path_full")
|
assets_path_full = getattr(settings,"assets_path_full")
|
||||||
levels_path_full = getattr(settings,"levels_path_full")
|
levels_path_full = getattr(settings,"levels_path_full")
|
||||||
|
@ -25,7 +37,52 @@ def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
||||||
if export_blueprints :
|
if export_blueprints :
|
||||||
gltf_output_path = os.path.join(levels_path_full, scene.name)
|
gltf_output_path = os.path.join(levels_path_full, scene.name)
|
||||||
|
|
||||||
#inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
||||||
|
print("main scene", scene)
|
||||||
|
for asset in scene.user_assets:
|
||||||
|
print(" user asset", asset.name, asset.path)
|
||||||
|
for asset in scene.generated_assets:
|
||||||
|
print(" generated asset", asset)
|
||||||
|
"""for blueprint in blueprints_data.blueprints_per_scenes[scene.name]:
|
||||||
|
print("BLUEPRINT", blueprint)"""
|
||||||
|
blueprint_instances_in_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, {}).keys()
|
||||||
|
blueprints_in_scene = [blueprints_data.blueprints_per_name[blueprint_name] for blueprint_name in blueprint_instances_in_scene]
|
||||||
|
#yala = [blueprint.collection.user_assets for blueprint in blueprints_in_scene]
|
||||||
|
#print("dsfsdf", yala)
|
||||||
|
auto_assets = []
|
||||||
|
|
||||||
|
all_assets = []
|
||||||
|
export_gltf_extension = getattr(settings.auto_export, "export_gltf_extension", ".glb")
|
||||||
|
|
||||||
|
blueprints_path = getattr(settings, "blueprints_path")
|
||||||
|
for blueprint in blueprints_in_scene:
|
||||||
|
if blueprint.local:
|
||||||
|
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
|
else:
|
||||||
|
# get the injected path of the external blueprints
|
||||||
|
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||||
|
if blueprint_exported_path is not None: # and not does_asset_exist(assets_list, blueprint_exported_path):
|
||||||
|
auto_assets.append({"name": blueprint.name, "path": blueprint_exported_path})#, "generated": True, "internal":blueprint.local, "parent": None})
|
||||||
|
|
||||||
|
# now also add the assets of the blueprints # TODO: wait no , these should not be a part of the (scene) local assets
|
||||||
|
for asset in blueprint.collection.user_assets:
|
||||||
|
print("adding assets of blueprint", asset.name)
|
||||||
|
all_assets.append({"name": asset.name, "path": asset.path})
|
||||||
|
|
||||||
|
"""for asset in auto_assets:
|
||||||
|
print(" generated asset", asset.name, asset.path)"""
|
||||||
|
|
||||||
|
materials_path = getattr(settings, "materials_path")
|
||||||
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
|
materials_library_name = f"{current_project_name}_materials"
|
||||||
|
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
|
material_assets = [{"name": materials_library_name, "path": materials_exported_path}] # we also add the material library as an asset
|
||||||
|
|
||||||
|
|
||||||
|
scene["local_assets"] = assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets)
|
||||||
|
scene["AllAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets)
|
||||||
|
|
||||||
|
|
||||||
if export_separate_dynamic_and_static_objects:
|
if export_separate_dynamic_and_static_objects:
|
||||||
#print("SPLIT STATIC AND DYNAMIC")
|
#print("SPLIT STATIC AND DYNAMIC")
|
||||||
# first export static objects
|
# first export static objects
|
||||||
|
@ -54,19 +111,21 @@ def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
||||||
generate_temporary_scene_and_export(
|
generate_temporary_scene_and_export(
|
||||||
settings,
|
settings,
|
||||||
temp_scene_name=TEMPSCENE_PREFIX,
|
temp_scene_name=TEMPSCENE_PREFIX,
|
||||||
|
additional_data = scene,
|
||||||
gltf_export_settings=gltf_export_settings,
|
gltf_export_settings=gltf_export_settings,
|
||||||
gltf_output_path=gltf_output_path,
|
gltf_output_path=gltf_output_path,
|
||||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
||||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
remove_blueprints_list_from_main_scene(scene)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
gltf_output_path = os.path.join(assets_path_full, scene.name)
|
gltf_output_path = os.path.join(assets_path_full, scene.name)
|
||||||
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
|
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
|
||||||
if settings.auto_export.dry_run == "DISABLED":
|
if settings.auto_export.dry_run == "DISABLED":
|
||||||
export_gltf(gltf_output_path, gltf_export_settings)
|
export_gltf(gltf_output_path, gltf_export_settings)
|
||||||
|
|
||||||
remove_blueprints_list_from_main_scene(scene)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import bpy
|
import bpy
|
||||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
|
||||||
from blenvy.blueprints.blueprint_helpers import check_if_blueprint_on_disk
|
from blenvy.blueprints.blueprint_helpers import check_if_blueprint_on_disk
|
||||||
|
|
||||||
# IF collection_instances_combine_mode is not 'split' check for each scene if any object in changes_per_scene has an instance in the scene
|
# IF collection_instances_combine_mode is not 'split' check for each scene if any object in changes_per_scene has an instance in the scene
|
||||||
|
@ -57,9 +56,8 @@ def should_level_be_exported(scene_name, changed_export_parameters, changes_per_
|
||||||
|
|
||||||
# this also takes the split/embed mode into account: if a collection instance changes AND embed is active, its container level/world should also be exported
|
# this also takes the split/embed mode into account: if a collection instance changes AND embed is active, its container level/world should also be exported
|
||||||
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
|
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
|
||||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
|
||||||
# determine list of main scenes to export
|
# determine list of main scenes to export
|
||||||
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
||||||
main_scenes_to_export = [scene_name for scene_name in main_scene_names if should_level_be_exported(scene_name, changed_export_parameters, changes_per_scene, blueprints_data, settings)]
|
main_scenes_to_export = [scene_name for scene_name in settings.main_scenes_names if should_level_be_exported(scene_name, changed_export_parameters, changes_per_scene, blueprints_data, settings)]
|
||||||
|
|
||||||
return (main_scenes_to_export)
|
return (main_scenes_to_export)
|
|
@ -101,13 +101,6 @@ class AutoExportSettings(PropertyGroup):
|
||||||
update=save_settings
|
update=save_settings
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
export_marked_assets: BoolProperty(
|
|
||||||
name='Auto export marked assets',
|
|
||||||
description='Collections that have been marked as assets will be systematically exported, even if not in use in another scene',
|
|
||||||
default=True,
|
|
||||||
update=save_settings
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
dry_run: EnumProperty(
|
dry_run: EnumProperty(
|
||||||
name="dry run",
|
name="dry run",
|
||||||
description="debug/ develop helper to enable everything but the actual exporting of files",
|
description="debug/ develop helper to enable everything but the actual exporting of files",
|
||||||
|
|
|
@ -51,7 +51,6 @@ def draw_settings_ui(layout, auto_export_settings):
|
||||||
|
|
||||||
# collections/blueprints
|
# collections/blueprints
|
||||||
section.prop(auto_export_settings, "collection_instances_combine_mode")
|
section.prop(auto_export_settings, "collection_instances_combine_mode")
|
||||||
section.prop(auto_export_settings, "export_marked_assets")
|
|
||||||
section.separator()
|
section.separator()
|
||||||
|
|
||||||
section.prop(auto_export_settings, "export_separate_dynamic_and_static_objects")
|
section.prop(auto_export_settings, "export_separate_dynamic_and_static_objects")
|
||||||
|
|
|
@ -4,11 +4,12 @@ from .assets_scan import get_main_scene_assets_tree
|
||||||
from .asset_helpers import get_user_assets, does_asset_exist
|
from .asset_helpers import get_user_assets, does_asset_exist
|
||||||
|
|
||||||
def draw_assets(layout, name, title, asset_registry, target_type, target_name, editable=True, user_assets= [], generated_assets = []):
|
def draw_assets(layout, name, title, asset_registry, target_type, target_name, editable=True, user_assets= [], generated_assets = []):
|
||||||
|
nesting_indent = 0.05
|
||||||
number_of_user_assets = len(user_assets)
|
number_of_user_assets = len(user_assets)
|
||||||
number_of_generated_assets = len(generated_assets)
|
number_of_generated_assets = len(generated_assets)
|
||||||
|
|
||||||
header, panel = layout.panel(f"assets{name}", default_closed=True)
|
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'
|
blueprint_assets = target_type == 'BLUEPRINT'
|
||||||
|
@ -19,8 +20,7 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
||||||
|
|
||||||
add_possible = does_asset_exist(target, {"path": asset_registry.asset_path_selector}) #"name": asset_registry.asset_name_selector,
|
add_possible = does_asset_exist(target, {"path": asset_registry.asset_path_selector}) #"name": asset_registry.asset_name_selector,
|
||||||
|
|
||||||
if header:
|
if header and editable:
|
||||||
|
|
||||||
row = header.row()
|
row = header.row()
|
||||||
row.alert = add_possible
|
row.alert = add_possible
|
||||||
|
|
||||||
|
@ -38,39 +38,21 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
||||||
add_asset.asset_type = asset_registry.asset_type_selector
|
add_asset.asset_type = asset_registry.asset_type_selector
|
||||||
add_asset.asset_path = asset_registry.asset_path_selector
|
add_asset.asset_path = asset_registry.asset_path_selector
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if panel:
|
if panel:
|
||||||
if editable:
|
if editable:
|
||||||
row = panel.row()
|
row = panel.row()
|
||||||
|
#panel.separator()
|
||||||
|
print("here", user_assets)
|
||||||
"""row.alert = add_possible
|
|
||||||
row.prop(asset_registry, "asset_name_selector", text="")
|
|
||||||
row.label(text=asset_registry.asset_path_selector)
|
|
||||||
asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER")
|
|
||||||
|
|
||||||
add_asset_layout = row.column()
|
|
||||||
add_asset_layout.enabled = not add_possible
|
|
||||||
|
|
||||||
add_asset = add_asset_layout.operator(operator="bevyassets.add", text="", icon="ADD")
|
|
||||||
add_asset.target_type = target_type
|
|
||||||
add_asset.target_name = target_name
|
|
||||||
add_asset.asset_name = asset_registry.asset_name_selector
|
|
||||||
add_asset.asset_type = asset_registry.asset_type_selector
|
|
||||||
add_asset.asset_path = asset_registry.asset_path_selector"""
|
|
||||||
|
|
||||||
panel.separator()
|
|
||||||
|
|
||||||
for asset in user_assets:
|
for asset in user_assets:
|
||||||
|
print("asset", asset)
|
||||||
row = panel.row()
|
row = panel.row()
|
||||||
split = row.split(factor=0.005)
|
split = row.split(factor=nesting_indent)
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.label(text=" ")
|
col.label(text=" ")
|
||||||
col = split.column()
|
col = split.column()
|
||||||
|
|
||||||
row = col.row()
|
row = col.row()
|
||||||
|
row.label(icon="ASSET_MANAGER")
|
||||||
row.prop(asset, "name", text="")
|
row.prop(asset, "name", text="")
|
||||||
row.label(text=asset.path)
|
row.label(text=asset.path)
|
||||||
asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER")
|
asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER")
|
||||||
|
@ -79,27 +61,6 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
||||||
remove_asset.target_type = target_type
|
remove_asset.target_type = target_type
|
||||||
remove_asset.target_name = target_name
|
remove_asset.target_name = target_name
|
||||||
remove_asset.asset_path = asset.path
|
remove_asset.asset_path = asset.path
|
||||||
|
|
||||||
for asset in generated_assets:
|
|
||||||
row = panel.row()
|
|
||||||
#row.label(text=asset.name)
|
|
||||||
#row.label(text=asset.path)
|
|
||||||
split = row.split(factor=0.005)
|
|
||||||
col = split.column()
|
|
||||||
col.label(text=" ")
|
|
||||||
col = split.column()
|
|
||||||
|
|
||||||
|
|
||||||
sub_header, sub_panel = col.panel(f"assets_sub{asset.name}", default_closed=False)
|
|
||||||
sub_header.label(text=f"{asset.name} ({asset.path})", icon="XRAY")
|
|
||||||
if sub_panel:
|
|
||||||
sub_panel.label(text=" some stuff")
|
|
||||||
"""remove_asset = row.operator(operator="bevyassets.remove", text="", icon="TRASH")
|
|
||||||
remove_asset.target_type = target_type
|
|
||||||
remove_asset.target_name = target_name
|
|
||||||
remove_asset.asset_path = asset.path"""
|
|
||||||
|
|
||||||
|
|
||||||
return panel
|
return panel
|
||||||
|
|
||||||
class Blenvy_assets(bpy.types.Panel):
|
class Blenvy_assets(bpy.types.Panel):
|
||||||
|
@ -133,9 +94,7 @@ class Blenvy_assets(bpy.types.Panel):
|
||||||
settings = SimpleNamespace(**settings)
|
settings = SimpleNamespace(**settings)
|
||||||
|
|
||||||
if panel:
|
if panel:
|
||||||
#print("dfs")
|
for scene in blenvy.main_scenes:
|
||||||
for scene_selector in blenvy.main_scenes:
|
|
||||||
scene = bpy.data.scenes[scene_selector.name]
|
|
||||||
user_assets = get_user_assets(scene)
|
user_assets = get_user_assets(scene)
|
||||||
|
|
||||||
row = panel.row()
|
row = panel.row()
|
||||||
|
|
|
@ -23,6 +23,8 @@ def check_if_blueprint_on_disk(scene_name, folder_path, extension):
|
||||||
def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_path, gltf_extension):
|
def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_path, gltf_extension):
|
||||||
for blueprint in internal_blueprints:
|
for blueprint in internal_blueprints:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
||||||
|
print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name)
|
||||||
|
|
||||||
blueprint.collection["export_path"] = blueprint_exported_path
|
blueprint.collection["export_path"] = blueprint_exported_path
|
||||||
|
|
||||||
def inject_blueprints_list_into_main_scene(scene, blueprints_data, settings):
|
def inject_blueprints_list_into_main_scene(scene, blueprints_data, settings):
|
||||||
|
|
|
@ -8,7 +8,6 @@ from bpy_types import (PropertyGroup)
|
||||||
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||||
|
|
||||||
from ..settings import load_settings
|
from ..settings import load_settings
|
||||||
from ..core.scene_helpers import get_main_and_library_scenes
|
|
||||||
from .blueprints_scan import blueprints_scan
|
from .blueprints_scan import blueprints_scan
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,7 +67,6 @@ class BlueprintsRegistry(PropertyGroup):
|
||||||
#print("titi", self)
|
#print("titi", self)
|
||||||
blenvy = bpy.context.window_manager.blenvy
|
blenvy = bpy.context.window_manager.blenvy
|
||||||
settings = blenvy
|
settings = blenvy
|
||||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
blueprints_data = blueprints_scan(settings.main_scenes, settings.library_scenes, settings)
|
||||||
blueprints_data = blueprints_scan(level_scenes, library_scenes, settings)
|
|
||||||
self.blueprints_data = blueprints_data
|
self.blueprints_data = blueprints_data
|
||||||
return blueprints_data
|
return blueprints_data
|
||||||
|
|
|
@ -8,8 +8,6 @@ from .blueprint import Blueprint
|
||||||
# - with the "auto_export" flag
|
# - with the "auto_export" flag
|
||||||
# https://blender.stackexchange.com/questions/167878/how-to-get-all-collections-of-the-current-scene
|
# https://blender.stackexchange.com/questions/167878/how-to-get-all-collections-of-the-current-scene
|
||||||
def blueprints_scan(main_scenes, library_scenes, settings):
|
def blueprints_scan(main_scenes, library_scenes, settings):
|
||||||
export_marked_assets = getattr(settings.auto_export, "export_marked_assets")
|
|
||||||
|
|
||||||
blueprints = {}
|
blueprints = {}
|
||||||
blueprints_from_objects = {}
|
blueprints_from_objects = {}
|
||||||
blueprint_name_from_instances = {}
|
blueprint_name_from_instances = {}
|
||||||
|
@ -84,12 +82,12 @@ def blueprints_scan(main_scenes, library_scenes, settings):
|
||||||
|
|
||||||
if (
|
if (
|
||||||
'AutoExport' in collection and collection['AutoExport'] == True # get marked collections
|
'AutoExport' in collection and collection['AutoExport'] == True # get marked collections
|
||||||
or export_marked_assets and collection.asset_data is not None # or if you have marked collections as assets you can auto export them too
|
or collection.asset_data is not None # or if you have marked collections as assets you can auto export them too
|
||||||
or collection.name in list(internal_collection_instances.keys()) # or if the collection has an instance in one of the main scenes
|
or collection.name in list(internal_collection_instances.keys()) # or if the collection has an instance in one of the main scenes
|
||||||
):
|
):
|
||||||
blueprint = Blueprint(collection.name)
|
blueprint = Blueprint(collection.name)
|
||||||
blueprint.local = True
|
blueprint.local = True
|
||||||
blueprint.marked = 'AutoExport' in collection and collection['AutoExport'] == True or export_marked_assets and collection.asset_data is not None
|
blueprint.marked = 'AutoExport' in collection and collection['AutoExport'] == True or collection.asset_data is not None
|
||||||
blueprint.objects = [object.name for object in collection.all_objects if not object.instance_type == 'COLLECTION'] # inneficient, double loop
|
blueprint.objects = [object.name for object in collection.all_objects if not object.instance_type == 'COLLECTION'] # inneficient, double loop
|
||||||
blueprint.nested_blueprints = [object.instance_collection.name for object in collection.all_objects if object.instance_type == 'COLLECTION'] # FIXME: not precise enough, aka "what is a blueprint"
|
blueprint.nested_blueprints = [object.instance_collection.name for object in collection.all_objects if object.instance_type == 'COLLECTION'] # FIXME: not precise enough, aka "what is a blueprint"
|
||||||
blueprint.collection = collection
|
blueprint.collection = collection
|
||||||
|
|
|
@ -5,6 +5,27 @@ from ..assets.asset_helpers import get_user_assets, get_generated_assets
|
||||||
|
|
||||||
from ..assets.ui import draw_assets
|
from ..assets.ui import draw_assets
|
||||||
|
|
||||||
|
|
||||||
|
def draw_blueprints(layout, name, title, generated_assets):
|
||||||
|
nesting_indent = 0.05
|
||||||
|
number_of_generated_assets = len(generated_assets)
|
||||||
|
|
||||||
|
header, panel = layout.panel(f"assets{name}", default_closed=True)
|
||||||
|
header.label(text=title + f"({number_of_generated_assets})", icon="XRAY")
|
||||||
|
|
||||||
|
if panel:
|
||||||
|
for asset in generated_assets:
|
||||||
|
row = panel.row()
|
||||||
|
split = row.split(factor=nesting_indent)
|
||||||
|
col = split.column()
|
||||||
|
col.label(text=" ")
|
||||||
|
col = split.column()
|
||||||
|
|
||||||
|
sub_header, sub_panel = col.panel(f"assets_sub{asset.name}", default_closed=False)
|
||||||
|
sub_header.label(text=f"{asset.name} ({asset.path})", icon="XRAY")
|
||||||
|
if sub_panel:
|
||||||
|
sub_panel.label(text=" some stuff")
|
||||||
|
|
||||||
class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
bl_region_type = 'UI'
|
bl_region_type = 'UI'
|
||||||
|
@ -56,4 +77,4 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
||||||
generated_assets = get_generated_assets(blueprint.collection)
|
generated_assets = get_generated_assets(blueprint.collection)
|
||||||
|
|
||||||
draw_assets(layout=col, name=blueprint.name, title="Assets", asset_registry=asset_registry, user_assets=user_assets, generated_assets=generated_assets, target_type="BLUEPRINT", target_name=blueprint.name, editable=False)
|
draw_assets(layout=col, name=blueprint.name, title="Assets", asset_registry=asset_registry, user_assets=user_assets, generated_assets=generated_assets, target_type="BLUEPRINT", target_name=blueprint.name, editable=False)
|
||||||
panel.label(text="External")
|
panel.label(text="External blueprint, assets are not editable")
|
||||||
|
|
|
@ -2,12 +2,12 @@ import os
|
||||||
import bpy
|
import bpy
|
||||||
from bpy_types import (PropertyGroup)
|
from bpy_types import (PropertyGroup)
|
||||||
from bpy.props import (BoolProperty, EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty)
|
from bpy.props import (BoolProperty, EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty)
|
||||||
from .scene_helpers import SceneSelector
|
|
||||||
from ..settings import upsert_settings, load_settings, generate_complete_settings_dict
|
from ..settings import upsert_settings, load_settings, generate_complete_settings_dict
|
||||||
import blenvy.add_ons.auto_export.settings as auto_export_settings
|
import blenvy.add_ons.auto_export.settings as auto_export_settings
|
||||||
import blenvy.add_ons.bevy_components.settings as component_settings
|
import blenvy.add_ons.bevy_components.settings as component_settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# list of settings we do NOT want to save
|
# list of settings we do NOT want to save
|
||||||
settings_black_list = ['settings_save_enabled', 'main_scene_selector', 'main_scenes', 'main_scenes_index', 'library_scene_selector', 'library_scenes', 'library_scenes_index',
|
settings_black_list = ['settings_save_enabled', 'main_scene_selector', 'main_scenes', 'main_scenes_index', 'library_scene_selector', 'library_scenes', 'library_scenes_index',
|
||||||
#'project_root_path_full', 'assets_path_full', ''
|
#'project_root_path_full', 'assets_path_full', ''
|
||||||
|
@ -35,7 +35,10 @@ def update_mode(blenvy, context):
|
||||||
|
|
||||||
def is_scene_already_in_use(self, scene):
|
def is_scene_already_in_use(self, scene):
|
||||||
try:
|
try:
|
||||||
return scene.name not in self.main_scenes and scene.name not in self.library_scenes
|
current_main_scene_names = list(map(lambda x: x.name, self.main_scenes))
|
||||||
|
current_library_scene_names = list(map(lambda x: x.name, self.library_scenes))
|
||||||
|
#print("scene ", scene.name, current_main_scene_names, current_library_scene_names)
|
||||||
|
return scene.name not in current_main_scene_names and scene.name not in current_library_scene_names
|
||||||
except:
|
except:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -117,14 +120,6 @@ class BlenvyManager(PropertyGroup):
|
||||||
get=lambda self: os.path.abspath(os.path.join(os.path.dirname(bpy.data.filepath), self.project_root_path, self.assets_path, self.materials_path))
|
get=lambda self: os.path.abspath(os.path.join(os.path.dirname(bpy.data.filepath), self.project_root_path, self.assets_path, self.materials_path))
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
main_scenes: CollectionProperty(name="main scenes", type=SceneSelector) # type: ignore
|
|
||||||
main_scenes_index: IntProperty(name = "Index for main scenes list", default = 0, update=update_scene_lists) # type: ignore
|
|
||||||
#main_scene_names = [] # FIXME: unsure
|
|
||||||
|
|
||||||
library_scenes: CollectionProperty(name="library scenes", type=SceneSelector) # type: ignore
|
|
||||||
library_scenes_index: IntProperty(name = "Index for library scenes list", default = 0, update=update_scene_lists) # type: ignore
|
|
||||||
#library_scene_names = [] # FIXME: unsure
|
|
||||||
|
|
||||||
# sub ones
|
# sub ones
|
||||||
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
||||||
components: PointerProperty(type=component_settings.ComponentsSettings) # type: ignore
|
components: PointerProperty(type=component_settings.ComponentsSettings) # type: ignore
|
||||||
|
@ -132,15 +127,37 @@ class BlenvyManager(PropertyGroup):
|
||||||
main_scene_selector: PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
main_scene_selector: PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
||||||
library_scene_selector: PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
library_scene_selector: PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
||||||
|
|
||||||
|
@property
|
||||||
|
def main_scenes(self):
|
||||||
|
return [scene for scene in bpy.data.scenes if scene.blenvy_scene_type == 'Level']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def main_scenes_names(self):
|
||||||
|
return [scene.name for scene in self.main_scenes]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def library_scenes(self):
|
||||||
|
return [scene for scene in bpy.data.scenes if scene.blenvy_scene_type == 'Library']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def library_scenes_names(self):
|
||||||
|
return [scene.name for scene in self.library_scenes]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.blenvy = PointerProperty(type=BlenvyManager)
|
bpy.types.WindowManager.blenvy = PointerProperty(type=BlenvyManager)
|
||||||
|
|
||||||
# unsure
|
# unsure
|
||||||
# you can add components to both objects & collections
|
|
||||||
#bpy.types.Object.components_meta = PointerProperty(type=ComponentsMeta)
|
|
||||||
bpy.types.Collection.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
bpy.types.Collection.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
||||||
bpy.types.Scene.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
bpy.types.Scene.always_export = BoolProperty(default=False, description="always export this blueprint, regardless of changed status") # FIXME: not sure about this one
|
||||||
|
bpy.types.Scene.blenvy_scene_type = EnumProperty(
|
||||||
|
items= (
|
||||||
|
('None', 'None', 'No blenvy type specified'),
|
||||||
|
('Level', 'Level','Main/ Level scene'),
|
||||||
|
('Library', 'Library', 'Library scene'),
|
||||||
|
),
|
||||||
|
default='None'
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
|
@ -148,6 +165,7 @@ class BlenvyManager(PropertyGroup):
|
||||||
|
|
||||||
del bpy.types.Collection.always_export
|
del bpy.types.Collection.always_export
|
||||||
del bpy.types.Scene.always_export
|
del bpy.types.Scene.always_export
|
||||||
|
del bpy.types.Scene.blenvy_scene_type
|
||||||
|
|
||||||
def load_settings(self):
|
def load_settings(self):
|
||||||
print("LOAD SETTINGS")
|
print("LOAD SETTINGS")
|
||||||
|
@ -155,14 +173,6 @@ class BlenvyManager(PropertyGroup):
|
||||||
if settings is not None:
|
if settings is not None:
|
||||||
if "mode" in settings:
|
if "mode" in settings:
|
||||||
self.mode = settings["mode"]
|
self.mode = settings["mode"]
|
||||||
if "main_scene_names" in settings:
|
|
||||||
for main_scene_name in settings["main_scene_names"]:
|
|
||||||
added = self.main_scenes.add()
|
|
||||||
added.name = main_scene_name
|
|
||||||
if "library_scene_names" in settings:
|
|
||||||
for main_scene_name in settings["library_scene_names"]:
|
|
||||||
added = self.library_scenes.add()
|
|
||||||
added.name = main_scene_name
|
|
||||||
|
|
||||||
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
||||||
for asset_path_name in asset_path_names:
|
for asset_path_name in asset_path_names:
|
||||||
|
|
|
@ -1,29 +1,7 @@
|
||||||
import bpy
|
import bpy
|
||||||
|
from bpy.props import (PointerProperty)
|
||||||
from .object_makers import make_empty
|
from .object_makers import make_empty
|
||||||
|
|
||||||
|
|
||||||
class SceneSelector(bpy.types.PropertyGroup):
|
|
||||||
name: bpy.props.StringProperty() # type: ignore
|
|
||||||
display: bpy.props.BoolProperty() # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
# convenience utility to get lists of scenes
|
|
||||||
def get_main_and_library_scenes(settings):
|
|
||||||
level_scene_names= getattr(settings, "main_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
|
|
||||||
library_scene_names = getattr(settings, "library_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
|
|
||||||
|
|
||||||
level_scene_names= list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
|
|
||||||
library_scene_names = list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
|
|
||||||
|
|
||||||
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
|
|
||||||
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
|
||||||
|
|
||||||
level_scenes = list(map(lambda name: bpy.data.scenes[name], level_scene_names))
|
|
||||||
library_scenes = list(map(lambda name: bpy.data.scenes[name], library_scene_names))
|
|
||||||
|
|
||||||
return [level_scene_names, level_scenes, library_scene_names, library_scenes]
|
|
||||||
|
|
||||||
|
|
||||||
def add_scene_property(scene, scene_component_name, property_data, limit_to=None):
|
def add_scene_property(scene, scene_component_name, property_data, limit_to=None):
|
||||||
root_collection = scene.collection
|
root_collection = scene.collection
|
||||||
scene_property = None
|
scene_property = None
|
||||||
|
|
|
@ -1,39 +1,6 @@
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
|
|
||||||
class SCENE_UL_Blenvy(bpy.types.UIList):
|
|
||||||
# The draw_item function is called for each item of the collection that is visible in the list.
|
|
||||||
# data is the RNA object containing the collection,
|
|
||||||
# item is the current drawn item of the collection,
|
|
||||||
# icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
|
|
||||||
# have custom icons ID, which are not available as enum items).
|
|
||||||
# active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
|
|
||||||
# active item of the collection).
|
|
||||||
# active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
|
|
||||||
# index is index of the current item in the collection.
|
|
||||||
# flt_flag is the result of the filtering process for this item.
|
|
||||||
# Note: as index and flt_flag are optional arguments, you do not have to use/declare them here if you don't
|
|
||||||
# need them.
|
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
|
||||||
ob = data
|
|
||||||
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
|
|
||||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
|
||||||
# You should always start your row layout by a label (icon + text), or a non-embossed text field,
|
|
||||||
# this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
|
|
||||||
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
|
|
||||||
# Note "data" names should never be translated!
|
|
||||||
#if ma:
|
|
||||||
# layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
|
|
||||||
#else:
|
|
||||||
# layout.label(text="", translate=False, icon_value=icon)
|
|
||||||
layout.label(text=item.name, icon_value=icon)
|
|
||||||
#layout.prop(item, "name", text="", emboss=False, icon_value=icon)
|
|
||||||
# 'GRID' layout type should be as compact as possible (typically a single icon!).
|
|
||||||
elif self.layout_type == 'GRID':
|
|
||||||
layout.alignment = 'CENTER'
|
|
||||||
layout.label(text="", icon_value=icon)
|
|
||||||
|
|
||||||
|
|
||||||
class SCENES_LIST_OT_actions(Operator):
|
class SCENES_LIST_OT_actions(Operator):
|
||||||
"""Move items up and down, add and remove"""
|
"""Move items up and down, add and remove"""
|
||||||
bl_idname = "scene_list.list_action"
|
bl_idname = "scene_list.list_action"
|
||||||
|
@ -55,65 +22,41 @@ class SCENES_LIST_OT_actions(Operator):
|
||||||
('LIBRARY', "Library", ""),
|
('LIBRARY', "Library", ""),
|
||||||
)
|
)
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
scene_name : bpy.props.StringProperty(name="scene_name")# type: ignore
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
source = context.window_manager.blenvy
|
if self.action == 'REMOVE':
|
||||||
target_name = "library_scenes"
|
bpy.data.scenes[self.scene_name].blenvy_scene_type = 'None'
|
||||||
target_index = "library_scenes_index"
|
"""info = 'Item "%s" removed from list' % (target[idx].name)
|
||||||
if self.scene_type == "LEVEL":
|
target.remove(idx)
|
||||||
target_name = "main_scenes"
|
|
||||||
target_index = "main_scenes_index"
|
|
||||||
|
|
||||||
target = getattr(source, target_name)
|
|
||||||
idx = getattr(source, target_index)
|
|
||||||
current_index = getattr(source, target_index)
|
|
||||||
|
|
||||||
try:
|
setattr(source, target_index, current_index -1 )
|
||||||
item = target[idx]
|
self.report({'INFO'}, info)"""
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if self.action == 'DOWN' and idx < len(target) - 1:
|
|
||||||
target.move(idx, idx + 1)
|
|
||||||
setattr(source, target_index, current_index +1 )
|
|
||||||
info = 'Item "%s" moved to position %d' % (item.name, current_index + 1)
|
|
||||||
self.report({'INFO'}, info)
|
|
||||||
|
|
||||||
elif self.action == 'UP' and idx >= 1:
|
|
||||||
target.move(idx, idx - 1)
|
|
||||||
setattr(source, target_index, current_index -1 )
|
|
||||||
info = 'Item "%s" moved to position %d' % (item.name, current_index + 1)
|
|
||||||
self.report({'INFO'}, info)
|
|
||||||
|
|
||||||
elif self.action == 'REMOVE':
|
|
||||||
info = 'Item "%s" removed from list' % (target[idx].name)
|
|
||||||
target.remove(idx)
|
|
||||||
|
|
||||||
setattr(source, target_index, current_index -1 )
|
|
||||||
self.report({'INFO'}, info)
|
|
||||||
|
|
||||||
if self.action == 'ADD':
|
if self.action == 'ADD':
|
||||||
new_scene_name = None
|
scene_to_add = None
|
||||||
if self.scene_type == "LEVEL":
|
if self.scene_type == "LEVEL":
|
||||||
if context.window_manager.blenvy.main_scene_selector:
|
if context.window_manager.blenvy.main_scene_selector:
|
||||||
new_scene_name = context.window_manager.blenvy.main_scene_selector.name
|
scene_to_add = context.window_manager.blenvy.main_scene_selector
|
||||||
|
scene_to_add.blenvy_scene_type = "Level"
|
||||||
else:
|
else:
|
||||||
if context.window_manager.blenvy.library_scene_selector:
|
if context.window_manager.blenvy.library_scene_selector:
|
||||||
new_scene_name = context.window_manager.blenvy.library_scene_selector.name
|
scene_to_add = context.window_manager.blenvy.library_scene_selector
|
||||||
if new_scene_name:
|
scene_to_add.blenvy_scene_type = "Library"
|
||||||
item = target.add()
|
|
||||||
item.name = new_scene_name
|
|
||||||
|
|
||||||
|
if scene_to_add is not None:
|
||||||
|
print("adding scene", scene_to_add)
|
||||||
|
|
||||||
if self.scene_type == "LEVEL":
|
if self.scene_type == "LEVEL":
|
||||||
context.window_manager.blenvy.main_scene_selector = None
|
context.window_manager.blenvy.main_scene_selector = None
|
||||||
else:
|
else:
|
||||||
context.window_manager.blenvy.library_scene_selector = None
|
context.window_manager.blenvy.library_scene_selector = None
|
||||||
|
|
||||||
setattr(source, target_index, len(target) - 1)
|
#setattr(source, target_index, len(target) - 1)
|
||||||
|
|
||||||
|
#info = '"%s" added to list' % (item.name)
|
||||||
|
#self.report({'INFO'}, info)
|
||||||
info = '"%s" added to list' % (item.name)
|
|
||||||
self.report({'INFO'}, info)
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
|
@ -109,44 +109,40 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||||
row = section.row()
|
row = section.row()
|
||||||
row.label(text="main scenes")
|
row.label(text="main scenes")
|
||||||
row.prop(blenvy, "main_scene_selector", text='')
|
row.prop(blenvy, "main_scene_selector", text='')
|
||||||
|
add_operator = row.operator("scene_list.list_action", icon='ADD', text="")
|
||||||
row = section.row()
|
|
||||||
row.template_list("SCENE_UL_Blenvy", "level scenes", blenvy, "main_scenes", blenvy, "main_scenes_index", rows=rows)
|
|
||||||
|
|
||||||
col = row.column(align=True)
|
|
||||||
sub_row = col.row()
|
|
||||||
add_operator = sub_row.operator("scene_list.list_action", icon='ADD', text="")
|
|
||||||
add_operator.action = 'ADD'
|
add_operator.action = 'ADD'
|
||||||
add_operator.scene_type = 'LEVEL'
|
add_operator.scene_type = 'LEVEL'
|
||||||
#add_operator.operator = operator
|
#sub_row.enabled = blenvy.main_scene_selector is not None
|
||||||
sub_row.enabled = blenvy.main_scene_selector is not None
|
|
||||||
|
row = section.row()
|
||||||
|
col = row.column()
|
||||||
|
for scene in blenvy.main_scenes:
|
||||||
|
sub_row = col.box().row()
|
||||||
|
sub_row.label(text=scene.name)
|
||||||
|
remove_operator = sub_row.operator("scene_list.list_action", icon='TRASH', text="")
|
||||||
|
remove_operator.action = 'REMOVE'
|
||||||
|
remove_operator.scene_type = 'LEVEL'
|
||||||
|
remove_operator.scene_name = scene.name
|
||||||
|
|
||||||
sub_row = col.row()
|
|
||||||
remove_operator = sub_row.operator("scene_list.list_action", icon='REMOVE', text="")
|
|
||||||
remove_operator.action = 'REMOVE'
|
|
||||||
remove_operator.scene_type = 'LEVEL'
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
# library scenes
|
# library scenes
|
||||||
row = section.row()
|
row = section.row()
|
||||||
row.label(text="library scenes")
|
row.label(text="library scenes")
|
||||||
row.prop(blenvy, "library_scene_selector", text='')
|
row.prop(blenvy, "library_scene_selector", text='')
|
||||||
|
add_operator = row.operator("scene_list.list_action", icon='ADD', text="")
|
||||||
row = section.row()
|
|
||||||
row.template_list("SCENE_UL_Blenvy", "library scenes", blenvy, "library_scenes", blenvy, "library_scenes_index", rows=rows)
|
|
||||||
|
|
||||||
col = row.column(align=True)
|
|
||||||
sub_row = col.row()
|
|
||||||
add_operator = sub_row.operator("scene_list.list_action", icon='ADD', text="")
|
|
||||||
add_operator.action = 'ADD'
|
add_operator.action = 'ADD'
|
||||||
add_operator.scene_type = 'LIBRARY'
|
add_operator.scene_type = 'LIBRARY'
|
||||||
sub_row.enabled = blenvy.library_scene_selector is not None
|
|
||||||
|
|
||||||
|
row = section.row()
|
||||||
sub_row = col.row()
|
col = row.column()
|
||||||
remove_operator = sub_row.operator("scene_list.list_action", icon='REMOVE', text="")
|
for scene in blenvy.library_scenes:
|
||||||
remove_operator.action = 'REMOVE'
|
sub_row = col.box().row()
|
||||||
remove_operator.scene_type = 'LIBRARY'
|
sub_row.label(text=scene.name)
|
||||||
|
remove_operator = sub_row.operator("scene_list.list_action", icon='TRASH', text="")
|
||||||
|
remove_operator.action = 'REMOVE'
|
||||||
|
remove_operator.scene_type = 'LEVEL'
|
||||||
|
remove_operator.scene_name = scene.name
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
header, panel = layout.panel("components", default_closed=False)
|
header, panel = layout.panel("components", default_closed=False)
|
||||||
|
|
|
@ -2,6 +2,7 @@ from types import SimpleNamespace
|
||||||
import bpy
|
import bpy
|
||||||
from ..assets.asset_helpers import get_generated_assets, get_user_assets
|
from ..assets.asset_helpers import get_generated_assets, get_user_assets
|
||||||
from ..assets.ui import draw_assets
|
from ..assets.ui import draw_assets
|
||||||
|
from ..blueprints.ui import draw_blueprints
|
||||||
|
|
||||||
class Blenvy_levels(bpy.types.Panel):
|
class Blenvy_levels(bpy.types.Panel):
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
|
@ -18,15 +19,14 @@ class Blenvy_levels(bpy.types.Panel):
|
||||||
layout.use_property_split = True
|
layout.use_property_split = True
|
||||||
layout.use_property_decorate = False # No animation.
|
layout.use_property_decorate = False # No animation.
|
||||||
blenvy = context.window_manager.blenvy
|
blenvy = context.window_manager.blenvy
|
||||||
layout.operator(operator="bevyassets.test")
|
layout.operator(operator="bevyassets.test", text="Generate")
|
||||||
|
|
||||||
asset_registry = context.window_manager.assets_registry
|
asset_registry = context.window_manager.assets_registry
|
||||||
blueprints_registry = context.window_manager.blueprints_registry
|
blueprints_registry = context.window_manager.blueprints_registry
|
||||||
#blueprints_registry.refresh_blueprints()
|
#blueprints_registry.refresh_blueprints()
|
||||||
blueprints_data = blueprints_registry.blueprints_data
|
blueprints_data = blueprints_registry.blueprints_data
|
||||||
|
|
||||||
for scene_selector in blenvy.main_scenes:
|
for scene in blenvy.main_scenes:
|
||||||
scene = bpy.data.scenes[scene_selector.name]
|
|
||||||
header, panel = layout.box().panel(f"level_assets{scene.name}", default_closed=False)
|
header, panel = layout.box().panel(f"level_assets{scene.name}", default_closed=False)
|
||||||
if header:
|
if header:
|
||||||
header.label(text=scene.name)#, icon="HIDE_OFF")
|
header.label(text=scene.name)#, icon="HIDE_OFF")
|
||||||
|
@ -54,7 +54,7 @@ class Blenvy_levels(bpy.types.Panel):
|
||||||
col = split.column()
|
col = split.column()
|
||||||
|
|
||||||
scene_assets_panel = draw_assets(layout=col, name=f"{scene.name}_assets", title=f"Assets", asset_registry=asset_registry, user_assets=user_assets, generated_assets=generated_assets, target_type="SCENE", target_name=scene.name)
|
scene_assets_panel = draw_assets(layout=col, name=f"{scene.name}_assets", title=f"Assets", asset_registry=asset_registry, user_assets=user_assets, generated_assets=generated_assets, target_type="SCENE", target_name=scene.name)
|
||||||
|
scene_blueprints_panel = draw_blueprints(layout=col, name=f"{scene.name}_blueprints", title=f"Blueprints", generated_assets=generated_assets, )
|
||||||
|
|
||||||
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||||
settings = SimpleNamespace(**settings)
|
settings = SimpleNamespace(**settings)
|
||||||
|
|
|
@ -4,32 +4,43 @@ from pathlib import Path
|
||||||
from ..core.helpers_collections import (traverse_tree)
|
from ..core.helpers_collections import (traverse_tree)
|
||||||
|
|
||||||
# get materials per object, and injects the materialInfo component
|
# get materials per object, and injects the materialInfo component
|
||||||
def get_materials(object):
|
def get_materials(object, materials_per_object):
|
||||||
material_slots = object.material_slots
|
material_slots = object.material_slots
|
||||||
used_materials_names = []
|
used_materials_names = []
|
||||||
#materials_per_object = {}
|
|
||||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
|
||||||
|
|
||||||
for m in material_slots:
|
for m in material_slots:
|
||||||
material = m.material
|
material = m.material
|
||||||
# print(" slot", m, "material", material)
|
# print(" slot", m, "material", material)
|
||||||
used_materials_names.append(material.name)
|
used_materials_names.append(material.name)
|
||||||
# TODO:, also respect slots & export multiple materials if applicable !
|
# TODO:, also respect slots & export multiple materials if applicable !
|
||||||
# TODO: do NOT modify objects like this !! do it in a different function
|
materials_per_object[object] = material
|
||||||
object['MaterialInfo'] = '(name: "'+material.name+'", source: "'+current_project_name + '")'
|
|
||||||
|
|
||||||
return used_materials_names
|
return used_materials_names
|
||||||
|
|
||||||
|
|
||||||
def get_all_materials(collection_names, library_scenes):
|
def get_all_materials(collection_names, library_scenes):
|
||||||
used_material_names = []
|
used_material_names = []
|
||||||
|
materials_per_object = {}
|
||||||
|
|
||||||
for scene in library_scenes:
|
for scene in library_scenes:
|
||||||
root_collection = scene.collection
|
root_collection = scene.collection
|
||||||
for cur_collection in traverse_tree(root_collection):
|
for cur_collection in traverse_tree(root_collection):
|
||||||
if cur_collection.name in collection_names:
|
if cur_collection.name in collection_names:
|
||||||
for object in cur_collection.all_objects:
|
for object in cur_collection.all_objects:
|
||||||
used_material_names = used_material_names + get_materials(object)
|
used_material_names = used_material_names + get_materials(object, materials_per_object)
|
||||||
|
|
||||||
# we only want unique names
|
# we only want unique names
|
||||||
used_material_names = list(set(used_material_names))
|
used_material_names = list(set(used_material_names))
|
||||||
return used_material_names
|
return (used_material_names, materials_per_object)
|
||||||
|
|
||||||
|
def add_material_info_to_objects(materials_per_object, settings):
|
||||||
|
materials_path = getattr(settings, "materials_path")
|
||||||
|
export_gltf_extension = getattr(settings.auto_export, "export_gltf_extension", ".glb")
|
||||||
|
|
||||||
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
|
materials_library_name = f"{current_project_name}_materials"
|
||||||
|
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
|
for object in materials_per_object.keys():
|
||||||
|
material = materials_per_object[object]
|
||||||
|
# TODO: switch to using actual components ?
|
||||||
|
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
|
object['MaterialInfo'] = f'(name: "{material.name}", path: "{materials_exported_path}")'
|
|
@ -9,7 +9,7 @@ import filecmp
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pixelmatch.contrib.PIL import pixelmatch
|
from pixelmatch.contrib.PIL import pixelmatch
|
||||||
|
|
||||||
from blenvy.auto_export.export.prepare_and_export import prepare_and_export
|
from blenvy.add_ons.auto_export.common.prepare_and_export import prepare_and_export
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_data(request):
|
def setup_data(request):
|
||||||
|
@ -59,7 +59,7 @@ def setup_data(request):
|
||||||
if os.path.exists(screenshot_observed_path):
|
if os.path.exists(screenshot_observed_path):
|
||||||
os.remove(screenshot_observed_path)
|
os.remove(screenshot_observed_path)
|
||||||
|
|
||||||
request.addfinalizer(finalizer)
|
#request.addfinalizer(finalizer)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -73,14 +73,11 @@ def setup_data(request):
|
||||||
"""
|
"""
|
||||||
def test_export_complex(setup_data):
|
def test_export_complex(setup_data):
|
||||||
root_path = setup_data["root_path"]
|
root_path = setup_data["root_path"]
|
||||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
|
||||||
|
|
||||||
# with change detection
|
# with change detection
|
||||||
# first, configure things
|
# first, configure things
|
||||||
# we use the global settings for that
|
# we use the global settings for that
|
||||||
export_props = {
|
export_props = {
|
||||||
"main_scene_names" : ['World'],
|
|
||||||
"library_scene_names": ['Library'],
|
|
||||||
}
|
}
|
||||||
gltf_settings = {
|
gltf_settings = {
|
||||||
"export_animations": True,
|
"export_animations": True,
|
||||||
|
@ -102,26 +99,35 @@ def test_export_complex(setup_data):
|
||||||
# move the cube in the library
|
# move the cube in the library
|
||||||
# TODO: add back bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
# TODO: add back bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
||||||
|
|
||||||
registry = bpy.context.window_manager.components_registry
|
|
||||||
blenvy = bpy.context.window_manager.blenvy
|
blenvy = bpy.context.window_manager.blenvy
|
||||||
main_scene = blenvy.main_scenes.add()
|
#blenvy.project_root_path =
|
||||||
main_scene.name = "World"
|
#blenvy.blueprints_path
|
||||||
blenvy.auto_export.auto_export = True
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# scene asset
|
||||||
|
user_asset = bpy.data.scenes['World'].user_assets.add()
|
||||||
|
user_asset.name = "test_asset"
|
||||||
|
user_asset.path = "audio/fake.mp3"
|
||||||
|
|
||||||
|
# blueprint asset
|
||||||
|
user_asset = bpy.data.collections['Blueprint4_nested'].user_assets.add()
|
||||||
|
user_asset.name = "yoho_audio"
|
||||||
|
user_asset.path = "audio/fake.mp3"
|
||||||
|
|
||||||
|
# we have to cheat, since we cannot rely on the data injected when saving the library file
|
||||||
|
bpy.data.collections["External_blueprint"]["export_path"] = "blueprints/External_blueprint.glb"
|
||||||
|
bpy.data.collections["External_blueprint2"]["export_path"] = "blueprints/External_blueprint2.glb"
|
||||||
|
bpy.data.collections["External_blueprint3"]["export_path"] = "blueprints/External_blueprint3.glb"
|
||||||
|
|
||||||
|
|
||||||
prepare_and_export()
|
prepare_and_export()
|
||||||
|
|
||||||
"""auto_export_operator(
|
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
|
||||||
project_root_path = os.path.abspath(root_path),
|
|
||||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
|
||||||
export_output_folder = os.path.join("assets", "models"), #"./models",
|
|
||||||
#levels_path = os.path.join("assets", "models"),
|
|
||||||
|
|
||||||
export_scene_settings=True,
|
|
||||||
export_blueprints=True,
|
|
||||||
export_materials_library=True
|
|
||||||
)"""
|
|
||||||
# blueprint1 => has an instance, got changed, should export
|
# blueprint1 => has an instance, got changed, should export
|
||||||
# blueprint2 => has NO instance, but marked as asset, should export
|
# blueprint2 => has NO instance, but marked as asset, should export
|
||||||
# blueprint3 => has NO instance, not marked as asset, used inside blueprint 4: should export
|
# blueprint3 => has NO instance, not marked as asset, used inside blueprint 4: should export
|
||||||
|
|
|
@ -2,6 +2,7 @@ import os
|
||||||
import json
|
import json
|
||||||
import pytest
|
import pytest
|
||||||
import bpy
|
import bpy
|
||||||
|
from blenvy.add_ons.auto_export.common.prepare_and_export import prepare_and_export
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_data(request):
|
def setup_data(request):
|
||||||
|
@ -25,14 +26,11 @@ def setup_data(request):
|
||||||
# this runs the external blueprints file
|
# this runs the external blueprints file
|
||||||
def test_export_external_blueprints(setup_data):
|
def test_export_external_blueprints(setup_data):
|
||||||
root_path = setup_data["root_path"]
|
root_path = setup_data["root_path"]
|
||||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
|
||||||
|
|
||||||
# with change detection
|
# with change detection
|
||||||
# first, configure things
|
# first, configure things
|
||||||
# we use the global settings for that
|
# we use the global settings for that
|
||||||
export_props = {
|
export_props = {
|
||||||
"main_scene_names" : [],
|
|
||||||
"library_scene_names": ['Library'],
|
|
||||||
}
|
}
|
||||||
gltf_settings = {
|
gltf_settings = {
|
||||||
"export_animations": True,
|
"export_animations": True,
|
||||||
|
@ -49,20 +47,20 @@ def test_export_external_blueprints(setup_data):
|
||||||
stored_gltf_settings.clear()
|
stored_gltf_settings.clear()
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||||
|
|
||||||
|
blenvy = bpy.context.window_manager.blenvy
|
||||||
|
#blenvy.project_root_path =
|
||||||
|
#blenvy.blueprints_path
|
||||||
|
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
|
||||||
|
|
||||||
auto_export_operator(
|
print("SCENES", bpy.data.scenes)
|
||||||
auto_export=True,
|
for scene in bpy.data.scenes:
|
||||||
direct_mode=True,
|
print("SCNE", scene)
|
||||||
project_root_path = os.path.abspath(root_path),
|
bpy.data.scenes['Library'].blenvy_scene_type = 'Library' # set scene as Library scene
|
||||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
# do the actual export
|
||||||
#export_output_folder = os.path.join("assets", "models"), #"./models",
|
prepare_and_export()
|
||||||
#levels_path = os.path.join("assets", "models"),
|
|
||||||
|
|
||||||
export_scene_settings=False,
|
|
||||||
export_blueprints=True,
|
|
||||||
export_materials_library=True,
|
|
||||||
export_marked_assets= True
|
|
||||||
)
|
|
||||||
|
|
||||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint.glb")) == True
|
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint.glb")) == True
|
||||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint2.glb")) == True
|
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint2.glb")) == True
|
||||||
|
|
|
@ -223,7 +223,6 @@ def test_export_do_not_export_marked_assets(setup_data):
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
export_blueprints=True,
|
export_blueprints=True,
|
||||||
export_marked_assets = False
|
|
||||||
)
|
)
|
||||||
assert os.path.exists(os.path.join(setup_data["levels_path"], "World.glb")) == True
|
assert os.path.exists(os.path.join(setup_data["levels_path"], "World.glb")) == True
|
||||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "Blueprint1.glb")) == True
|
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "Blueprint1.glb")) == True
|
||||||
|
|
Loading…
Reference in New Issue