mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 11:50:53 +00:00
Compare commits
2 Commits
ee5c74aa9e
...
959951bca4
Author | SHA1 | Date | |
---|---|---|---|
|
959951bca4 | ||
|
31f6a0f122 |
@ -20,7 +20,7 @@ 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 BlenvyAssets(pub Vec<MyAsset>);
|
||||
pub struct BlueprintAssets(pub Vec<MyAsset>);
|
||||
|
||||
|
||||
|
||||
|
@ -123,7 +123,7 @@ impl Plugin for BlueprintsPlugin {
|
||||
.register_type::<Vec<MyAsset>>()
|
||||
.register_type::<Vec<String>>()
|
||||
.register_type::<LocalAssets>()
|
||||
.register_type::<BlenvyAssets>()
|
||||
.register_type::<BlueprintAssets>()
|
||||
|
||||
|
||||
.register_type::<HashMap<String, Vec<String>>>()
|
||||
|
@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
||||
|
||||
use crate::{BlenvyAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
use crate::{BlueprintAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
|
||||
/// this is a flag component for our levels/game world
|
||||
#[derive(Component)]
|
||||
@ -76,9 +76,9 @@ pub(crate) fn test_thingy(
|
||||
&BlueprintPath,
|
||||
Option<&Parent>,*/
|
||||
Option<&Name>,
|
||||
Option<&BlenvyAssets>,
|
||||
Option<&BlueprintAssets>,
|
||||
),
|
||||
(Added<BlenvyAssets>), // Added<BlenvyAssets>
|
||||
(Added<BlueprintAssets>), // Added<BlueprintAssets>
|
||||
>,
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ license = "MIT OR Apache-2.0"
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
||||
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf", "file_watcher"] }
|
||||
serde = "1.0.188"
|
||||
ron = "0.8.1"
|
||||
serde_json = "1.0.108"
|
||||
|
@ -16,7 +16,7 @@ pub struct MyAsset{
|
||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||
#[derive(Component, Reflect, Default, Debug, Deserialize)]
|
||||
#[reflect(Component)]
|
||||
pub struct BlenvyAssets {
|
||||
pub struct BlueprintAssets {
|
||||
/// only this field should get filled in from the Blender side
|
||||
pub assets: Vec<MyAsset>,
|
||||
/// set to default when deserializing
|
||||
@ -49,13 +49,13 @@ pub(crate) struct BlueprintAssetsNotLoaded;
|
||||
pub(crate) struct AssetLoadTracker {
|
||||
#[allow(dead_code)]
|
||||
pub name: String,
|
||||
pub path: 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 BlenvyAssetsLoadState {
|
||||
|
@ -64,6 +64,7 @@ pub(crate) fn materials_inject(
|
||||
|
||||
let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
||||
name: material_info.name.clone(),
|
||||
path: material_info.path.clone(),
|
||||
id: material_file_id,
|
||||
loaded: false,
|
||||
handle: material_file_handle.clone(),
|
||||
|
@ -89,7 +89,7 @@ impl Plugin for BlueprintsPlugin {
|
||||
.register_type::<MyAsset>()
|
||||
.register_type::<Vec<MyAsset>>()
|
||||
.register_type::<Vec<String>>()
|
||||
.register_type::<BlenvyAssets>()
|
||||
.register_type::<BlueprintAssets>()
|
||||
|
||||
.add_event::<BlueprintEvent>()
|
||||
|
||||
@ -143,6 +143,8 @@ impl Plugin for BlueprintsPlugin {
|
||||
trigger_blueprint_animation_markers_events,
|
||||
),
|
||||
)*/
|
||||
|
||||
.add_systems(Update, react_to_asset_changes)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
|
||||
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{BlenvyAssets, AssetsToLoad, AssetLoadTracker, BlenvyConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
use crate::{BlueprintAssets, AssetsToLoad, AssetLoadTracker, BlenvyConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
|
||||
/// this is a flag component for our levels/game world
|
||||
#[derive(Component)]
|
||||
@ -103,9 +103,9 @@ pub(crate) fn blueprints_prepare_spawn(
|
||||
&BlueprintPath,
|
||||
Option<&Parent>,*/
|
||||
Option<&Name>,
|
||||
Option<&BlenvyAssets>,
|
||||
Option<&BlueprintAssets>,
|
||||
),
|
||||
(Added<BlenvyAssets>), // Added<BlenvyAssets>
|
||||
(Added<BlueprintAssets>), // Added<BlueprintAssets>
|
||||
>,
|
||||
|
||||
|
||||
@ -115,7 +115,7 @@ pub(crate) fn blueprints_prepare_spawn(
|
||||
&BlueprintName,
|
||||
&BlueprintPath,
|
||||
Option<&Parent>,
|
||||
Option<&BlenvyAssets>,
|
||||
Option<&BlueprintAssets>,
|
||||
),(Added<BlueprintPath>)
|
||||
>,
|
||||
mut commands: Commands,
|
||||
@ -150,10 +150,10 @@ asset_server: Res<AssetServer>,
|
||||
println!("{} / {}", key, value);
|
||||
}
|
||||
|
||||
if lookup.contains_key("BlenvyAssets"){
|
||||
let assets_raw = &lookup["BlenvyAssets"];
|
||||
if lookup.contains_key("BlueprintAssets"){
|
||||
let assets_raw = &lookup["BlueprintAssets"];
|
||||
println!("ASSETS RAW {}", assets_raw);
|
||||
let x: BlenvyAssets = ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
||||
let x: BlueprintAssets = ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
||||
println!("YAHA {:?}", x);
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
||||
use bevy::{asset::LoadedUntypedAsset, gltf::Gltf, prelude::*, scene::SceneInstance, transform::commands, utils::hashbrown::HashMap};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{BlenvyAssets, BlenvyAssetsLoadState, AssetLoadTracker, BlenvyConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
use crate::{BlueprintAssets, BlenvyAssetsLoadState, AssetLoadTracker, BlenvyConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||
|
||||
/// this is a flag component for our levels/game world
|
||||
#[derive(Component)]
|
||||
@ -19,7 +19,6 @@ pub struct BlueprintInfo {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
|
||||
/// flag component needed to signify the intent to spawn a Blueprint
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
@ -94,17 +93,15 @@ pub(crate) fn blueprints_prepare_spawn(
|
||||
Entity,
|
||||
&BlueprintInfo,
|
||||
Option<&Parent>,
|
||||
Option<&BlenvyAssets>,
|
||||
),(Added<BlueprintInfo>)
|
||||
Option<&BlueprintAssets>,
|
||||
),(Added<SpawnHere>)
|
||||
>,
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
||||
|
||||
) {
|
||||
|
||||
for (entity, blueprint_info, parent, all_assets) in blueprint_instances_to_spawn.iter() {
|
||||
println!("Detected blueprint to spawn {:?} {:?}", blueprint_info.name, blueprint_info.path);
|
||||
println!("Detected blueprint to spawn: {:?} path:{:?}", blueprint_info.name, blueprint_info.path);
|
||||
println!("all assets {:?}", all_assets);
|
||||
//////////////
|
||||
|
||||
@ -118,6 +115,7 @@ asset_server: Res<AssetServer>,
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: blueprint_info.name.clone(),
|
||||
path: blueprint_info.path.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: untyped_handle.clone(),
|
||||
@ -135,10 +133,10 @@ asset_server: Res<AssetServer>,
|
||||
println!("{} / {}", key, value);
|
||||
}*/
|
||||
|
||||
if lookup.contains_key("BlenvyAssets"){
|
||||
let assets_raw = &lookup["BlenvyAssets"];
|
||||
if lookup.contains_key("BlueprintAssets"){
|
||||
let assets_raw = &lookup["BlueprintAssets"];
|
||||
//println!("ASSETS RAW {}", assets_raw);
|
||||
let all_assets: BlenvyAssets = ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
||||
let all_assets: BlueprintAssets = ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
||||
println!("all_assets {:?}", all_assets);
|
||||
|
||||
for asset in all_assets.assets.iter() {
|
||||
@ -152,6 +150,7 @@ asset_server: Res<AssetServer>,
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: asset.name.clone(),
|
||||
path: asset.path.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: untyped_handle.clone(),
|
||||
@ -223,7 +222,7 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||
.entity(entity)
|
||||
.insert(BlueprintAssetsLoaded)
|
||||
.remove::<BlueprintAssetsNotLoaded>()
|
||||
.remove::<BlenvyAssetsLoadState>()
|
||||
//.remove::<BlenvyAssetsLoadState>() //REMOVE it in release mode/ when hot reload is off, keep it for dev/hot reload
|
||||
;
|
||||
}else {
|
||||
println!("LOADING: done for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
||||
@ -231,6 +230,142 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub(crate) fn hot_reload_asset_check(
|
||||
mut blueprint_assets: Query<
|
||||
(Entity, Option<&Name>, &BlueprintInfo, &mut BlenvyAssetsLoadState)>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
){
|
||||
for (entity, entity_name, blueprint_info, mut assets_to_load) in blueprint_assets.iter_mut() {
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
let asset_id = tracker.id;
|
||||
asset_server.is_changed()
|
||||
if asset_server.load_state(asset_id) == bevy::asset::LoadState::
|
||||
match asset_server.load_state(asset_id) {
|
||||
bevy::asset::LoadState::Failed(_) => {
|
||||
failed = true
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
//AssetEvent::Modified`
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
use bevy::asset::AssetEvent;
|
||||
|
||||
pub(crate) fn react_to_asset_changes(
|
||||
mut gltf_events: EventReader<AssetEvent<Gltf>>,
|
||||
mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
||||
mut blueprint_assets: Query<(Entity, Option<&Name>, &BlueprintInfo, &mut BlenvyAssetsLoadState, Option<&Children>)>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
|
||||
) {
|
||||
|
||||
for event in untyped_events.read() {
|
||||
for (entity, entity_name, blueprint_info, mut assets_to_load, c) in blueprint_assets.iter_mut() {
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
let asset_id = tracker.id;
|
||||
|
||||
println!("changed {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_modified(asset_id));
|
||||
}
|
||||
}
|
||||
|
||||
match event {
|
||||
AssetEvent::Added { id } => {
|
||||
// React to the image being created
|
||||
println!("Added untyped {:?}", asset_server.get_path(*id))
|
||||
}
|
||||
AssetEvent::LoadedWithDependencies { id } => {
|
||||
// React to the image being loaded
|
||||
// after all dependencies
|
||||
println!("Loaded with deps untyped {:?}", asset_server.get_path(*id))
|
||||
}
|
||||
AssetEvent::Modified { id } => {
|
||||
// React to the image being modified
|
||||
println!("Modified untyped {:?}", asset_server.get_path(*id))
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
// React to the image being removed
|
||||
println!("Removed untyped {:?}", asset_server.get_path(*id))
|
||||
},
|
||||
AssetEvent::Unused { id } => {
|
||||
// React to the last strong handle for the asset being dropped
|
||||
println!("unused untyped {:?}", asset_server.get_path(*id))
|
||||
}
|
||||
}
|
||||
}
|
||||
for event in gltf_events.read() {
|
||||
// LoadedUntypedAsset
|
||||
|
||||
/*for (entity, entity_name, blueprint_info, mut assets_to_load) in blueprint_assets.iter_mut() {
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
let asset_id = tracker.id;
|
||||
if blueprint_info.path.ends_with("glb") || blueprint_info.path.ends_with("gltf") {
|
||||
// let typed_asset_id = asset_server.get_handle(blueprint_info.path);
|
||||
let foo: Handle<Gltf> = asset_server.load(blueprint_info.path.clone());
|
||||
//println!("changed {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_modified(foo.id()));
|
||||
println!("changed {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_modified(foo.id()));
|
||||
println!("added {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_added(foo.id()));
|
||||
println!("removed {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_removed(foo.id()));
|
||||
println!("loaded with deps {:?} (blueprint {}) {}", entity_name, blueprint_info.path, event.is_loaded_with_dependencies(foo.id()));
|
||||
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
match event {
|
||||
AssetEvent::Added { id } => {
|
||||
// React to the image being created
|
||||
println!("Added gltf, path {:?}", asset_server.get_path(*id));
|
||||
|
||||
}
|
||||
AssetEvent::LoadedWithDependencies { id } => {
|
||||
// React to the image being loaded
|
||||
// after all dependencies
|
||||
println!("Loaded gltf with deps{:?}", asset_server.get_path(*id))
|
||||
}
|
||||
AssetEvent::Modified { id } => {
|
||||
// React to the image being modified
|
||||
println!("Modified gltf {:?}", asset_server.get_path(*id));
|
||||
|
||||
for (entity, entity_name, blueprint_info, mut assets_to_load, children) in blueprint_assets.iter_mut() {
|
||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||
if tracker.path == asset_server.get_path(*id).unwrap().to_string() {
|
||||
println!("HOLY MOLY IT DETECTS !!, now respawn {:?}", entity_name);
|
||||
if children.is_some() {
|
||||
for child in children.unwrap().iter(){
|
||||
commands.entity(*child).despawn_recursive();
|
||||
|
||||
}
|
||||
}
|
||||
commands.entity(entity)
|
||||
.remove::<BlueprintAssetsLoaded>()
|
||||
.remove::<SceneInstance>()
|
||||
.remove::<BlenvyAssetsLoadState>()
|
||||
.insert(SpawnHere);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
// React to the image being removed
|
||||
println!("Removed gltf {:?}", asset_server.get_path(*id))
|
||||
},
|
||||
AssetEvent::Unused { id } => {
|
||||
// React to the last strong handle for the asset being dropped
|
||||
println!("unused gltf {:?}", asset_server.get_path(*id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn blueprints_spawn(
|
||||
|
@ -8,7 +8,7 @@ use bevy::scene::SceneInstance;
|
||||
use crate::{BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo};
|
||||
use crate::{SpawnHere, Spawned};
|
||||
use crate::{
|
||||
BlenvyAssetsLoadState, BlueprintAssetsLoaded, BlueprintEvent, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren
|
||||
BlueprintEvent, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren
|
||||
};
|
||||
|
||||
|
||||
|
@ -153,7 +153,6 @@ fn process_colorgrading(
|
||||
|
||||
for entity in cameras.iter(){
|
||||
for blender_colorgrading in blender_colorgradings.iter(){
|
||||
println!("COLOR GRADING");
|
||||
commands.entity(entity).insert(
|
||||
ColorGrading{
|
||||
global: ColorGradingGlobal{
|
||||
|
@ -13231,21 +13231,36 @@
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::assets::BlenvyAssets": {
|
||||
"blenvy::blueprints::assets::BlueprintAssets": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"items": false,
|
||||
"long_name": "blenvy::blueprints::assets::BlenvyAssets",
|
||||
"prefixItems": [
|
||||
{
|
||||
"long_name": "blenvy::blueprints::assets::BlueprintAssets",
|
||||
"properties": {
|
||||
"assets": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/alloc::vec::Vec<blenvy::blueprints::assets::MyAsset>"
|
||||
}
|
||||
},
|
||||
"loaded": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/bool"
|
||||
}
|
||||
},
|
||||
"progress": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/f32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"assets",
|
||||
"loaded",
|
||||
"progress"
|
||||
],
|
||||
"short_name": "BlenvyAssets",
|
||||
"type": "array",
|
||||
"typeInfo": "TupleStruct"
|
||||
"short_name": "BlueprintAssets",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::assets::MyAsset": {
|
||||
"additionalProperties": false,
|
||||
@ -13297,37 +13312,30 @@
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::BlueprintName": {
|
||||
"blenvy::blueprints::spawn_from_blueprints::BlueprintInfo": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"items": false,
|
||||
"long_name": "blenvy::blueprints::spawn_from_blueprints::BlueprintName",
|
||||
"prefixItems": [
|
||||
{
|
||||
"long_name": "blenvy::blueprints::spawn_from_blueprints::BlueprintInfo",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/alloc::string::String"
|
||||
}
|
||||
}
|
||||
],
|
||||
"short_name": "BlueprintName",
|
||||
"type": "array",
|
||||
"typeInfo": "TupleStruct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::BlueprintPath": {
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"items": false,
|
||||
"long_name": "blenvy::blueprints::spawn_from_blueprints::BlueprintPath",
|
||||
"prefixItems": [
|
||||
{
|
||||
"path": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/alloc::string::String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path"
|
||||
],
|
||||
"short_name": "BlueprintPath",
|
||||
"type": "array",
|
||||
"typeInfo": "TupleStruct"
|
||||
"short_name": "BlueprintInfo",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::SpawnHere": {
|
||||
"additionalProperties": false,
|
||||
@ -13376,6 +13384,31 @@
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::components::blender_settings::lighting::BlenderColorGrading": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::components::blender_settings::lighting::BlenderColorGrading",
|
||||
"properties": {
|
||||
"exposure": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/f32"
|
||||
}
|
||||
},
|
||||
"gamma": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/f32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"exposure",
|
||||
"gamma"
|
||||
],
|
||||
"short_name": "BlenderColorGrading",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::components::blender_settings::lighting::BlenderLightShadows": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
@ -13420,6 +13453,19 @@
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::components::blender_settings::lighting::BlenderToneMapping": {
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::components::blender_settings::lighting::BlenderToneMapping",
|
||||
"oneOf": [
|
||||
"None",
|
||||
"AgX",
|
||||
"Filmic"
|
||||
],
|
||||
"short_name": "BlenderToneMapping",
|
||||
"type": "string",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"bool": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
|
@ -7,7 +7,7 @@ pub use animation::*;
|
||||
use std::{collections::HashMap, fs, time::Duration};
|
||||
|
||||
use blenvy::{
|
||||
BlenvyAssets, BlueprintAnimationPlayerLink, BlueprintEvent, BlueprintInfo, GltfBlueprintsSet, SceneAnimations
|
||||
BlueprintAssets, BlueprintAnimationPlayerLink, BlueprintEvent, BlueprintInfo, GltfBlueprintsSet, SceneAnimations
|
||||
};
|
||||
|
||||
use bevy::{
|
||||
@ -39,7 +39,7 @@ fn validate_export(
|
||||
scene_animations: Query<(Entity, &SceneAnimations)>,
|
||||
empties_candidates: Query<(Entity, &Name, &GlobalTransform)>,
|
||||
|
||||
assets_list: Query<(Entity, &BlenvyAssets)>,
|
||||
assets_list: Query<(Entity, &BlueprintAssets)>,
|
||||
root: Query<(Entity, &Name, &Children), (Without<Parent>, With<Children>)>,
|
||||
) {
|
||||
let animations_found =
|
||||
|
@ -1,5 +1,5 @@
|
||||
use bevy::{gltf::{GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras}, prelude::*};
|
||||
use blenvy::{BlenvyAssets, BlueprintInstanceReady};
|
||||
use blenvy::{BlueprintAssets, BlueprintInstanceReady};
|
||||
|
||||
use crate::BasicTest;
|
||||
|
||||
@ -32,7 +32,7 @@ pub fn get_descendants(
|
||||
all_children: &Query<&Children>,
|
||||
all_names:&Query<&Name>, root: &Entity,
|
||||
nesting: usize,
|
||||
to_check: &Query<&BasicTest>//&Query<(&BlueprintInstanceReady, &BlenvyAssets)>,
|
||||
to_check: &Query<&BasicTest>//&Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
||||
)
|
||||
-> String
|
||||
{
|
||||
@ -67,7 +67,7 @@ pub fn draw_hierarchy_debug(
|
||||
all_children: Query<&Children>,
|
||||
all_names:Query<&Name>,
|
||||
|
||||
to_check: Query<&BasicTest>,//Query<(&BlueprintInstanceReady, &BlenvyAssets)>,
|
||||
to_check: Query<&BasicTest>,//Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
||||
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||
){
|
||||
let mut hierarchy_display: Vec<String> = vec![];
|
||||
|
@ -139,29 +139,53 @@ General issues:
|
||||
- [x] overall cleanup
|
||||
- [x] object.add_bevy_component => blenvy.component_add
|
||||
|
||||
|
||||
Blender side:
|
||||
- [x] force overwrite of settings files instead of partial updates ?
|
||||
- [x] prevent loop when loading/setting/saving settings
|
||||
- [x] fix asset changes not being detected as a scene change
|
||||
- [x] fix scene setting changes not being detected as a scene change
|
||||
- [x] add back lighting_components
|
||||
- [x] check if scene components are being deleted through our scene re-orgs in the spawn post process
|
||||
- [x] fix unreliable project hashing between sessions: (note, it is due to the use of hash() : https://stackoverflow.com/questions/27522626/hash-function-in-python-3-3-returns-different-results-between-sessions)
|
||||
- [x] figure out why there are still changes per session (it is due to object pointer being present in the generated "hash")
|
||||
- materials & modifiers, both using the same underlying logic
|
||||
- [x] filter out components_meta
|
||||
- [x] filter out xxx_ui propgroups
|
||||
- [x] fix missing main/lib scene names in blenvy_common_settings
|
||||
- [x] fix incorect updating of main/lib scenes list in settings
|
||||
- [ ] and what about scene renames ?? perhaps tigger a forced "save settings" before doing the export ?
|
||||
- [x] should we write the previous _xxx data only AFTER a sucessfull export only ?
|
||||
- [x] finer grained control of setting changes to trigger a re-export:
|
||||
- [x] common: any of them should trigger
|
||||
- [x] components: none
|
||||
- [x] auto_export:
|
||||
- auto_export: yes
|
||||
- gltf settings: yes
|
||||
- change detection: no ?
|
||||
- export blueprints: YES
|
||||
- export split dynamic/static: YES
|
||||
- export merge mode : YES
|
||||
- materials: YES
|
||||
- [ ] inject_export_path_into_internal_blueprints should be called on every asset/blueprint scan !! Not just on export
|
||||
- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this
|
||||
- [ ] handle scene renames between saves (breaks diffing) => very hard to achieve
|
||||
- [ ] force overwrite of settings files instead of partial updates ?
|
||||
- [ ] add tests for disabled components
|
||||
- [ ] should we write the previous _xxx data only AFTER a sucessfull export only ?
|
||||
- [ ] find a solution for the new color handling
|
||||
- [ ] hidden objects/collections not respected at export !!!
|
||||
- [ ] add option to 'split out' meshes from blueprints ?
|
||||
- [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs
|
||||
- [ ] 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 ?)
|
||||
- [ ] find a solution for the new color handling
|
||||
- [x] add back lighting_components
|
||||
- [x] check if scene components are being deleted through our scene re-orgs in the spawn post process
|
||||
- [ ] should "blueprint spawned" only be triggered after all its sub blueprints have spawned ?
|
||||
|
||||
Bevy Side:
|
||||
- [x] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead
|
||||
- [ ] should "blueprint spawned" only be triggered after all its sub blueprints have spawned ?
|
||||
- [ ] simplify testing example:
|
||||
- [x] remove use of rapier physics (or even the whole common boilerplate ?)
|
||||
- [ ] remove/replace bevy editor pls with some native ui to display hierarchies
|
||||
- [ ] try out hot reloading
|
||||
|
||||
- [x] try out hot reloading
|
||||
- [ ] simplify examples:
|
||||
- [ ] a full fledged demo (including physics & co)
|
||||
- [ ] other examples without interactions or physics
|
||||
@ -170,12 +194,9 @@ General issues:
|
||||
- [ ] replace all references to the old 2 add-ons with those to Blenvy
|
||||
- [ ] rename repo to "Blenvy"
|
||||
- [ ] do a deprecation release of all bevy_gltf_xxx crates to point at the new Blenvy crate
|
||||
- [ ] hidden objects/collections not respected at export !!!
|
||||
- [ ] add a way of overriding assets for collection instances
|
||||
- [ ] add a way of visualizing per blueprint instances
|
||||
- [ ] cleanup all the spurious debug messages
|
||||
- [ ] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead
|
||||
- [ ] fix animation handling
|
||||
|
||||
|
||||
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
|
@ -11,7 +11,7 @@ def cleanup_file():
|
||||
os.remove(gltf_filepath)
|
||||
return None
|
||||
else:
|
||||
return 1
|
||||
return 1.0
|
||||
|
||||
def gltf_post_export_callback(data):
|
||||
#print("post_export", data)
|
||||
|
@ -36,14 +36,9 @@ def export_blueprints(blueprints, settings, blueprints_data):
|
||||
|
||||
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["BlenvyAssets"] = assets_to_fake_ron([]) #assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets) #all_assets + [{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets)
|
||||
collection["BlueprintAssets"] = assets_to_fake_ron([]) #assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets) #all_assets + [{"name": asset.name, "path": asset.path} for asset in collection.user_assets] + auto_assets)
|
||||
|
||||
|
||||
# do the actual export
|
||||
|
@ -51,7 +51,6 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
for blueprint in blueprints_data.blueprints:
|
||||
bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint)
|
||||
#bpy.context.window_manager.blueprints_registry.refresh_blueprints()
|
||||
print("YO YO")
|
||||
|
||||
if export_scene_settings:
|
||||
# inject/ update scene components
|
||||
|
@ -90,7 +90,7 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
||||
original_name = object.name
|
||||
blueprint_name = original_collection.name
|
||||
# FIXME: blueprint path is WRONG !
|
||||
print("BLUEPRINT PATH", original_collection.get('export_path', None))
|
||||
# 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 !!
|
||||
|
||||
|
||||
|
@ -19,7 +19,6 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out
|
||||
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
|
||||
temp_root_collection = temp_scene.collection
|
||||
|
||||
print("additional_dataAAAAAAAAAAAAAAAH", additional_data)
|
||||
properties_black_list = ['glTF2ExportSettings', 'assets', 'user_assets', 'components_meta', 'Components_meta', 'Generated_assets', 'generated_assets']
|
||||
if additional_data is not None: # FIXME not a fan of having this here
|
||||
for entry in dict(additional_data):
|
||||
|
@ -3,6 +3,7 @@ import bpy
|
||||
from .project_diff import get_changes_per_scene
|
||||
from .auto_export import auto_export
|
||||
from .settings_diff import get_setting_changes
|
||||
from blenvy.settings import load_settings, upsert_settings
|
||||
|
||||
# prepare export by gather the changes to the scenes & settings
|
||||
def prepare_and_export():
|
||||
@ -13,17 +14,28 @@ def prepare_and_export():
|
||||
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled
|
||||
|
||||
# determine changed objects
|
||||
per_scene_changes = get_changes_per_scene(settings=blenvy)
|
||||
per_scene_changes, project_hash = get_changes_per_scene(settings=blenvy)
|
||||
# determine changed parameters
|
||||
setting_changes = get_setting_changes()
|
||||
print("setting_changes", setting_changes)
|
||||
setting_changes, current_common_settings, current_export_settings, current_gltf_settings = get_setting_changes()
|
||||
print("changes: settings:", setting_changes)
|
||||
print("changes: scenes:", per_scene_changes)
|
||||
|
||||
print("project_hash", project_hash)
|
||||
# do the actual export
|
||||
# blenvy.auto_export.dry_run = 'NO_EXPORT'#'DISABLED'#
|
||||
auto_export(per_scene_changes, setting_changes, blenvy)
|
||||
|
||||
# -------------------------------------
|
||||
# now that this point is reached, the export should have run correctly, so we can save all the current state to the "previous one"
|
||||
# save the current project hash as previous
|
||||
upsert_settings(".blenvy.project_serialized_previous", project_hash, overwrite=True)
|
||||
# write the new settings to the old settings
|
||||
upsert_settings(".blenvy_common_settings_previous", current_common_settings, overwrite=True)
|
||||
upsert_settings(".blenvy_export_settings_previous", current_export_settings, overwrite=True)
|
||||
upsert_settings(".blenvy_gltf_settings_previous", current_gltf_settings, overwrite=True)
|
||||
|
||||
# cleanup
|
||||
# TODO: these are likely obsolete
|
||||
# reset the list of changes in the tracker
|
||||
#bpy.context.window_manager.auto_export_tracker.clear_changes()
|
||||
print("AUTO EXPORT DONE")
|
||||
#bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=0.1)
|
||||
|
@ -22,6 +22,7 @@ def serialize_current(settings):
|
||||
current_scene = bpy.context.window.scene
|
||||
bpy.context.window.scene = bpy.data.scenes[0]
|
||||
#serialize scene at frame 0
|
||||
# TODO: add back
|
||||
"""with bpy.context.temp_override(scene=bpy.data.scenes[1]):
|
||||
bpy.context.scene.frame_set(0)"""
|
||||
|
||||
@ -38,7 +39,6 @@ def get_changes_per_scene(settings):
|
||||
previous = load_settings(".blenvy.project_serialized_previous")
|
||||
current = serialize_current(settings)
|
||||
|
||||
|
||||
# determine changes
|
||||
changes_per_scene = {}
|
||||
try:
|
||||
@ -46,11 +46,7 @@ def get_changes_per_scene(settings):
|
||||
except Exception as error:
|
||||
print("failed to compare current serialized scenes to previous ones", error)
|
||||
|
||||
# save the current project as previous
|
||||
upsert_settings(".blenvy.project_serialized_previous", current, overwrite=True)
|
||||
|
||||
print("changes per scene", changes_per_scene)
|
||||
return changes_per_scene
|
||||
return changes_per_scene, current
|
||||
|
||||
|
||||
def project_diff(previous, current, settings):
|
||||
@ -58,17 +54,13 @@ def project_diff(previous, current, settings):
|
||||
print("current", current)"""
|
||||
if previous is None or current is None:
|
||||
return {}
|
||||
print("Settings", settings,"current", current, "previous", previous)
|
||||
|
||||
changes_per_scene = {}
|
||||
|
||||
# TODO : how do we deal with changed scene names ???
|
||||
# possible ? on each save, inject an id into each scene, that cannot be copied over
|
||||
|
||||
print('TEST SCENE', bpy.data.scenes.get("ULTRA LEVEL2"), None)
|
||||
|
||||
for scene in current:
|
||||
print("SCENE", scene)
|
||||
current_object_names =list(current[scene].keys())
|
||||
|
||||
if scene in previous: # we can only compare scenes that are in both previous and current data
|
||||
|
@ -7,13 +7,23 @@ import numpy as np
|
||||
import bpy
|
||||
from ..constants import TEMPSCENE_PREFIX
|
||||
|
||||
import hashlib
|
||||
|
||||
# horrible and uneficient
|
||||
def h1_hash(w):
|
||||
try:
|
||||
w = w.encode('utf-8')
|
||||
except: pass
|
||||
return hashlib.md5(w).hexdigest()
|
||||
|
||||
fields_to_ignore_generic = [
|
||||
"tag", "type", "update_tag", "use_extra_user", "use_fake_user", "user_clear", "user_of_id", "user_remap", "users",
|
||||
'animation_data_clear', 'animation_data_create', 'asset_clear', 'asset_data', 'asset_generate_preview', 'asset_mark', 'bl_rna', 'evaluated_get',
|
||||
'library', 'library_weak_reference', 'make_local','name', 'name_full', 'original',
|
||||
'override_create', 'override_hierarchy_create', 'override_library', 'preview', 'preview_ensure', 'rna_type',
|
||||
'session_uid', 'copy', 'id_type', 'is_embedded_data', 'is_evaluated', 'is_library_indirect', 'is_missing', 'is_runtime_data'
|
||||
'session_uid', 'copy', 'id_type', 'is_embedded_data', 'is_evaluated', 'is_library_indirect', 'is_missing', 'is_runtime_data',
|
||||
|
||||
'components_meta', 'cycles'
|
||||
]
|
||||
|
||||
|
||||
@ -40,9 +50,7 @@ def _lookup_array2(data):
|
||||
return peel_value(data)
|
||||
|
||||
def _lookup_prop_group(data):
|
||||
bla = generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||
print("PROPGROUP", bla)
|
||||
return bla
|
||||
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||
|
||||
def _lookup_collection(data):
|
||||
return [generic_fields_hasher_evolved(item, fields_to_ignore=fields_to_ignore_generic) for item in data]
|
||||
@ -50,9 +58,16 @@ def _lookup_collection(data):
|
||||
def _lookup_materialLineArt(data):
|
||||
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||
|
||||
def _lookup_object(data):
|
||||
return data.name
|
||||
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||
|
||||
def _lookup_generic(data):
|
||||
return generic_fields_hasher_evolved(data, fields_to_ignore=fields_to_ignore_generic)
|
||||
|
||||
# used for various node trees: shaders, modifiers etc
|
||||
def node_tree(node_tree):
|
||||
print("SCANNING NODE TREE", node_tree)
|
||||
#print("SCANNING NODE TREE", node_tree)
|
||||
|
||||
# storage for hashing
|
||||
links_hashes = []
|
||||
@ -99,18 +114,19 @@ def node_tree(node_tree):
|
||||
links_hashes.append(link_hash)
|
||||
|
||||
#print("node hashes",nodes_hashes, "links_hashes", links_hashes)
|
||||
print("root_inputs", root_inputs)
|
||||
return f"{str(root_inputs)}_{str(nodes_hashes)}_{str(links_hashes)}"
|
||||
|
||||
|
||||
type_lookups = {
|
||||
Color: _lookup_color,#lambda input: print("dsf")',
|
||||
bpy.types.Object: _lookup_object,
|
||||
bpy.types.FloatVectorAttribute: _lookup_array2,
|
||||
bpy.types.bpy_prop_array: _lookup_array,
|
||||
bpy.types.PropertyGroup: _lookup_prop_group,
|
||||
bpy.types.bpy_prop_collection: _lookup_collection,
|
||||
bpy.types.MaterialLineArt: _lookup_materialLineArt,
|
||||
bpy.types.NodeTree: node_tree,
|
||||
bpy.types.CurveProfile: _lookup_generic
|
||||
}
|
||||
|
||||
def convert_field(raw_value, field_name="", scan_node_tree=True):
|
||||
@ -122,6 +138,7 @@ def convert_field(raw_value, field_name="", scan_node_tree=True):
|
||||
conversion_lookup = None # type_lookups.get(type(raw_value), None)
|
||||
all_types = inspect.getmro(type(raw_value))
|
||||
for s_type in all_types:
|
||||
#print(" stype", s_type)
|
||||
if type_lookups.get(s_type, None) is not None:
|
||||
conversion_lookup = type_lookups[s_type]
|
||||
break
|
||||
@ -132,6 +149,9 @@ def convert_field(raw_value, field_name="", scan_node_tree=True):
|
||||
#print("field_name",field_name,"conv value", field_value)
|
||||
else:
|
||||
#print("field_name",field_name,"raw value", raw_value)
|
||||
"""try:
|
||||
field_value=_lookup_generic(raw_value)
|
||||
except:pass"""
|
||||
field_value = raw_value
|
||||
|
||||
return field_value
|
||||
@ -146,6 +166,7 @@ def obj_to_dict(object):
|
||||
# TODO: replace the first one with this once if its done
|
||||
def generic_fields_hasher_evolved(data, fields_to_ignore, scan_node_tree=True):
|
||||
dict_data = obj_to_dict(data) # in some cases, some data is in the key/value pairs of the object
|
||||
dict_data = {key: dict_data[key] for key in dict_data.keys() if key not in fields_to_ignore}# we need to filter out fields here too
|
||||
all_field_names = dir(data)
|
||||
field_values = []
|
||||
for field_name in all_field_names:
|
||||
@ -153,6 +174,8 @@ def generic_fields_hasher_evolved(data, fields_to_ignore, scan_node_tree=True):
|
||||
raw_value = getattr(data, field_name, None)
|
||||
#print("raw value", raw_value, "type", type(raw_value), isinstance(raw_value, Color), isinstance(raw_value, bpy.types.bpy_prop_array))
|
||||
field_value = convert_field(raw_value, field_name, scan_node_tree)
|
||||
#print("field name", field_name, "raw", raw_value, "converted", field_value)
|
||||
|
||||
field_values.append(str(field_value))
|
||||
|
||||
return str(dict_data) + str(field_values)
|
||||
@ -163,7 +186,7 @@ def mesh_hash(obj):
|
||||
vertex_count = len(obj.data.vertices)
|
||||
vertices_np = np.empty(vertex_count * 3, dtype=np.float32)
|
||||
obj.data.vertices.foreach_get("co", vertices_np)
|
||||
h = str(hash(vertices_np.tobytes()))
|
||||
h = str(h1_hash(vertices_np.tobytes()))
|
||||
return h
|
||||
|
||||
# TODO: redo this one, this is essentially modifiec copy & pasted data, not fitting
|
||||
@ -202,7 +225,7 @@ def animation_hash(obj):
|
||||
markers_per_animation[animation_name][marker.frame] = []
|
||||
markers_per_animation[animation_name][marker.frame].append(marker.name)
|
||||
|
||||
compact_result = hash(str((blender_actions, blender_tracks, markers_per_animation, animations_infos)))
|
||||
compact_result = h1_hash(str((blender_actions, blender_tracks, markers_per_animation, animations_infos)))
|
||||
return compact_result
|
||||
|
||||
|
||||
@ -213,7 +236,7 @@ def custom_properties_hash(obj):
|
||||
for property_name in obj.keys():
|
||||
if property_name not in '_RNA_UI' and property_name != 'components_meta':
|
||||
custom_properties[property_name] = obj[property_name]
|
||||
return str(hash(str(custom_properties)))
|
||||
return str(h1_hash(str(custom_properties)))
|
||||
|
||||
def camera_hash(obj):
|
||||
camera_data = obj.data
|
||||
@ -233,7 +256,7 @@ def bones_hash(bones):
|
||||
fields = [getattr(bone, prop, None) for prop in all_field_names if not prop.startswith("__") and not prop in fields_to_ignore and not prop.startswith("show_")]
|
||||
bones_result.append(fields)
|
||||
#print("fields of bone", bones_result)
|
||||
return str(hash(str(bones_result)))
|
||||
return str(h1_hash(str(bones_result)))
|
||||
|
||||
# fixme: not good enough ?
|
||||
def armature_hash(obj):
|
||||
@ -250,8 +273,10 @@ def armature_hash(obj):
|
||||
|
||||
def material_hash(material, settings):
|
||||
scan_node_tree = settings.auto_export.materials_in_depth_scan
|
||||
hashed_material_except_node_tree = generic_fields_hasher_evolved(material, fields_to_ignore_generic, scan_node_tree=scan_node_tree)
|
||||
return str(hashed_material_except_node_tree)
|
||||
#print("HASHING MATERIAL", material.name)
|
||||
hashed_material = generic_fields_hasher_evolved(material, fields_to_ignore_generic, scan_node_tree=scan_node_tree)
|
||||
#print("HASHED MATERIAL", hashed_material)
|
||||
return str(hashed_material)
|
||||
|
||||
# TODO: this is partially taken from export_materials utilities, perhaps we could avoid having to fetch things multiple times ?
|
||||
def materials_hash(obj, cache, settings):
|
||||
@ -271,21 +296,23 @@ def materials_hash(obj, cache, settings):
|
||||
cache['materials'][material.name] = mat
|
||||
materials.append(mat)
|
||||
|
||||
return str(hash(str(materials)))
|
||||
return str(h1_hash(str(materials)))
|
||||
|
||||
def modifier_hash(modifier_data, settings):
|
||||
scan_node_tree = settings.auto_export.modifiers_in_depth_scan
|
||||
#print("HASHING MODIFIER", modifier_data.name)
|
||||
hashed_modifier = generic_fields_hasher_evolved(modifier_data, fields_to_ignore_generic, scan_node_tree=scan_node_tree)
|
||||
#print("modifier", modifier_data.name, "hashed", hashed_modifier)
|
||||
return str(hashed_modifier)
|
||||
|
||||
|
||||
def modifiers_hash(object, settings):
|
||||
modifiers = []
|
||||
for modifier in object.modifiers:
|
||||
print("modifier", modifier )# modifier.node_group)
|
||||
#print("modifier", modifier )# modifier.node_group)
|
||||
modifiers.append(modifier_hash(modifier, settings))
|
||||
print(" ")
|
||||
return str(hash(str(modifiers)))
|
||||
#print(" ")
|
||||
return str(h1_hash(str(modifiers)))
|
||||
|
||||
def serialize_scene(settings):
|
||||
cache = {"materials":{}}
|
||||
@ -309,16 +336,15 @@ def serialize_scene(settings):
|
||||
"custom_properties": custom_properties,
|
||||
"eevee": eevee_settings
|
||||
}
|
||||
print("SCENE WORLD", scene.world, dir(scene.eevee))
|
||||
#generic_fields_hasher_evolved(scene.eevee, fields_to_ignore=fields_to_ignore_generic)
|
||||
data[scene.name]["____scene_settings"] = str(hash(str(scene_field_hashes)))
|
||||
# FIXME: how to deal with this cleanly
|
||||
print("SCENE CUSTOM PROPS", custom_properties)
|
||||
data[scene.name]["____scene_settings"] = str(h1_hash(str(scene_field_hashes)))
|
||||
|
||||
|
||||
for object in scene.objects:
|
||||
object = bpy.data.objects[object.name]
|
||||
|
||||
#loc, rot, scale = bpy.context.object.matrix_world.decompose()
|
||||
|
||||
transform = str((object.location, object.rotation_euler, object.scale)) #str((object.matrix_world.to_translation(), object.matrix_world.to_euler('XYZ'), object.matrix_world.to_quaternion()))#
|
||||
visibility = object.visible_get()
|
||||
custom_properties = custom_properties_hash(object) if len(object.keys()) > 0 else None
|
||||
@ -332,7 +358,6 @@ def serialize_scene(settings):
|
||||
materials = materials_hash(object, cache, settings) if len(object.material_slots) > 0 else None
|
||||
modifiers = modifiers_hash(object, settings) if len(object.modifiers) > 0 else None
|
||||
|
||||
|
||||
object_field_hashes = {
|
||||
"name": object.name,
|
||||
"transforms": transform,
|
||||
@ -348,8 +373,9 @@ def serialize_scene(settings):
|
||||
"materials": materials,
|
||||
"modifiers":modifiers
|
||||
}
|
||||
|
||||
object_field_hashes_filtered = {key: object_field_hashes[key] for key in object_field_hashes.keys() if object_field_hashes[key] is not None}
|
||||
objectHash = str(hash(str(object_field_hashes_filtered)))
|
||||
objectHash = str(h1_hash(str(object_field_hashes_filtered)))
|
||||
data[scene.name][object.name] = objectHash
|
||||
|
||||
"""print("data", data)
|
||||
|
@ -1,56 +0,0 @@
|
||||
#print("THIS IS A GEOMETRY NODE")
|
||||
|
||||
# storage for hashing
|
||||
links_hashes = []
|
||||
nodes_hashes = []
|
||||
modifier_inputs = dict(modifier_data)
|
||||
|
||||
for node in node_group.nodes:
|
||||
#print("node", node, node.type, node.name, node.label)
|
||||
#print("node info", dir(node))
|
||||
|
||||
input_hashes = []
|
||||
for input in node.inputs:
|
||||
#print(" input", input, "label", input.label, "name", input.name)
|
||||
input_hash = f"{getattr(input, 'default_value', None)}"
|
||||
input_hashes.append(input_hash)
|
||||
"""if hasattr(input, "default_value"):
|
||||
print("YOHO", dict(input), input.default_value)"""
|
||||
|
||||
output_hashes = []
|
||||
# IF the node itself is a group input, its outputs are the inputs of the geometry node (yes, not easy)
|
||||
node_in_use = True
|
||||
for (index, output) in enumerate(node.outputs):
|
||||
# print(" output", output, "label", output.label, "name", output.name, "generated name", f"Socket_{index+1}")
|
||||
output_hash = f"{getattr(output, 'default_value', None)}"
|
||||
output_hashes.append(output_hash)
|
||||
"""if hasattr(output, "default_value"):
|
||||
print("YOHO", output.default_value)"""
|
||||
node_in_use = node_in_use and hasattr(output, "default_value")
|
||||
#print("NODE IN USE", node_in_use)
|
||||
|
||||
node_fields_to_ignore = fields_to_ignore_generic + ['internal_links', 'inputs', 'outputs']
|
||||
|
||||
node_hash = f"{generic_fields_hasher(node, node_fields_to_ignore)}_{str(input_hashes)}_{str(output_hashes)}"
|
||||
#print("node hash", node_hash)
|
||||
nodes_hashes.append(node_hash)
|
||||
#print(" ")
|
||||
|
||||
for link in node_group.links:
|
||||
"""print("LINK", link) #dir(link)
|
||||
print("FROM", link.from_node, link.from_socket)
|
||||
print("TO", link.to_node, link.to_socket)"""
|
||||
|
||||
from_socket_default = link.from_socket.default_value if hasattr(link.from_socket, "default_value") else None
|
||||
to_socket_default = link.to_socket.default_value if hasattr(link.to_socket, "default_value") else None
|
||||
link_hash = f"{link.from_node.name}_{link.from_socket.name}_{from_socket_default}+{link.to_node.name}_{link.to_socket.name}_{to_socket_default}"
|
||||
|
||||
"""if hasattr(link.from_socket, "default_value"):
|
||||
print("[FROM SOCKET]", link.from_socket.default_value)
|
||||
if hasattr(link.to_socket, "default_value"):
|
||||
print("[TO SOCKET]", link.to_socket.default_value)"""
|
||||
|
||||
links_hashes.append(link_hash)
|
||||
#print("link_hash", link_hash)
|
||||
|
||||
return f"{str(modifier_inputs)}_{str(nodes_hashes)}_{str(links_hashes)}"
|
@ -1,8 +1,8 @@
|
||||
import bpy
|
||||
|
||||
from blenvy.settings import are_settings_identical, load_settings, upsert_settings
|
||||
from blenvy.settings import are_settings_identical, load_settings, changed_settings
|
||||
|
||||
# which settings are specific to auto_export # TODO: can we infer this ?
|
||||
# which common settings changes should trigger a re-export
|
||||
parameter_names_whitelist_common = [
|
||||
# blenvy core
|
||||
'project_root_path',
|
||||
@ -14,6 +14,7 @@ parameter_names_whitelist_common = [
|
||||
'library_scene_names',
|
||||
]
|
||||
|
||||
# which auto export settings changes should trigger a re-export
|
||||
parameter_names_whitelist_auto_export = [
|
||||
# auto export
|
||||
'export_scene_settings',
|
||||
@ -24,34 +25,29 @@ parameter_names_whitelist_auto_export = [
|
||||
]
|
||||
|
||||
def get_setting_changes():
|
||||
print("get setting changes")
|
||||
|
||||
previous_common_settings = load_settings(".blenvy_common_settings_previous")
|
||||
current_common_settings = load_settings(".blenvy_common_settings")
|
||||
common_settings_changed = not are_settings_identical(previous_common_settings, current_common_settings, white_list=parameter_names_whitelist_common)
|
||||
changed_common_settings_fields = changed_settings(previous_common_settings, current_common_settings, white_list=parameter_names_whitelist_common)
|
||||
common_settings_changed = len(changed_common_settings_fields) > 0
|
||||
|
||||
previous_export_settings = load_settings(".blenvy_export_settings_previous")
|
||||
current_export_settings = load_settings(".blenvy_export_settings")
|
||||
export_settings_changed = not are_settings_identical(previous_export_settings, current_export_settings, white_list=parameter_names_whitelist_auto_export)
|
||||
changed_export_settings_fields = changed_settings(previous_export_settings, current_export_settings, white_list=parameter_names_whitelist_auto_export)
|
||||
export_settings_changed = len(changed_export_settings_fields) > 0
|
||||
|
||||
previous_gltf_settings = load_settings(".blenvy_gltf_settings_previous")
|
||||
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)
|
||||
|
||||
# write the new settings to the old settings
|
||||
upsert_settings(".blenvy_common_settings_previous", current_common_settings, overwrite=True)
|
||||
upsert_settings(".blenvy_export_settings_previous", current_export_settings, overwrite=True)
|
||||
upsert_settings(".blenvy_gltf_settings_previous", current_gltf_settings, overwrite=True)
|
||||
|
||||
print("common_settings_changed", common_settings_changed,"export_settings_changed", export_settings_changed, "gltf_settings_changed", gltf_settings_changed, )
|
||||
settings_changed = common_settings_changed or gltf_settings_changed or export_settings_changed
|
||||
|
||||
# if there were no setting before, it is new, we need export # TODO: do we even need this ? I guess in the case where both the previous & the new one are both none ? very unlikely, but still
|
||||
if previous_common_settings is None:
|
||||
return True
|
||||
settings_changed = True
|
||||
if previous_export_settings is None:
|
||||
return True
|
||||
settings_changed = True
|
||||
if previous_gltf_settings is None:
|
||||
return True
|
||||
settings_changed = True
|
||||
|
||||
return common_settings_changed or gltf_settings_changed or export_settings_changed
|
||||
|
||||
return settings_changed, current_common_settings, current_export_settings, current_gltf_settings
|
||||
|
@ -41,11 +41,11 @@ def export_main_scene(scene, settings, blueprints_data):
|
||||
gltf_output_path = os.path.join(levels_path_full, scene.name)
|
||||
|
||||
inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
||||
print("main scene", scene)
|
||||
"""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)
|
||||
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()
|
||||
@ -69,7 +69,7 @@ def export_main_scene(scene, settings, blueprints_data):
|
||||
|
||||
# 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)
|
||||
#print("adding assets of blueprint", asset.name)
|
||||
all_assets.append({"name": asset.name, "path": asset.path})
|
||||
|
||||
"""for asset in auto_assets:
|
||||
@ -81,8 +81,8 @@ def export_main_scene(scene, settings, blueprints_data):
|
||||
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["BlenvyAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets)
|
||||
#scene["BlenvyAssets"] = assets_to_fake_ron([{'name':'foo', 'path':'bar'}])
|
||||
scene["BlueprintAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets)
|
||||
#scene["BlueprintAssets"] = assets_to_fake_ron([{'name':'foo', 'path':'bar'}])
|
||||
|
||||
if export_separate_dynamic_and_static_objects:
|
||||
#print("SPLIT STATIC AND DYNAMIC")
|
||||
|
@ -9,13 +9,12 @@ settings_black_list = ['settings_save_enabled', 'dry_run']
|
||||
def save_settings(settings, context):
|
||||
if settings.settings_save_enabled:
|
||||
settings_dict = generate_complete_settings_dict(settings, AutoExportSettings, [])
|
||||
print("save settings", settings, context, settings_dict)
|
||||
upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list}, overwrite=True)
|
||||
|
||||
class AutoExportSettings(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_export_settings" # where to store data in bpy.texts
|
||||
settings_save_enabled = BoolProperty(name="settings save enabled", default=True)
|
||||
settings_save_enabled: BoolProperty(name="settings save enabled", default=True) # type: ignore
|
||||
|
||||
auto_export: BoolProperty(
|
||||
name='Auto export',
|
||||
@ -119,7 +118,6 @@ class AutoExportSettings(PropertyGroup):
|
||||
self.settings_save_enabled = False # we disable auto_saving of our settings
|
||||
try:
|
||||
for setting in settings:
|
||||
print("setting", setting, settings[setting])
|
||||
setattr(self, setting, settings[setting])
|
||||
except: pass
|
||||
# TODO: remove setting if there was a failure
|
||||
|
@ -1,7 +1,7 @@
|
||||
import os
|
||||
import bpy
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, FloatProperty)
|
||||
from blenvy.settings import load_settings, upsert_settings, generate_complete_settings_dict
|
||||
from .propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
from .components.metadata import ensure_metadata_for_all_items
|
||||
@ -18,7 +18,6 @@ def save_settings(settings, context):
|
||||
|
||||
# helper function to deal with timer
|
||||
def toggle_watcher(self, context):
|
||||
#print("toggling watcher", self.watcher_enabled, watch_schema, self, bpy.app.timers)
|
||||
if not self.watcher_enabled:
|
||||
try:
|
||||
bpy.app.timers.unregister(watch_schema)
|
||||
@ -76,12 +75,12 @@ class ComponentsSettings(PropertyGroup):
|
||||
watcher_enabled: BoolProperty(name="Watcher_enabled", default=True, update=toggle_watcher)# type: ignore
|
||||
watcher_active: BoolProperty(name = "Flag for watcher status", default = False)# type: ignore
|
||||
|
||||
watcher_poll_frequency: IntProperty(
|
||||
watcher_poll_frequency: FloatProperty(
|
||||
name="watcher poll frequency",
|
||||
description="frequency (s) at wich to poll for changes to the registry file",
|
||||
min=1,
|
||||
max=10,
|
||||
default=1,
|
||||
min=1.0,
|
||||
max=10.0,
|
||||
default=1.0,
|
||||
update=save_settings
|
||||
)# type: ignore
|
||||
|
||||
@ -134,7 +133,6 @@ class ComponentsSettings(PropertyGroup):
|
||||
self.settings_save_enabled = False # we disable auto_saving of our settings
|
||||
try:
|
||||
for setting in settings:
|
||||
print("setting", setting, settings[setting])
|
||||
setattr(self, setting, settings[setting])
|
||||
except:pass
|
||||
try:
|
||||
|
@ -19,14 +19,13 @@ def scan_assets(scene, blueprints_data, settings):
|
||||
for blueprint_name in blueprint_instance_names_for_scene:
|
||||
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||
if blueprint is not None:
|
||||
print("BLUEPRINT", blueprint)
|
||||
#print("BLUEPRINT", blueprint)
|
||||
blueprint_exported_path = None
|
||||
if blueprint.local:
|
||||
blueprint_exported_path = os.path.join(relative_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
|
||||
print("foo", dict(blueprint.collection))
|
||||
if blueprint_exported_path is not None:
|
||||
blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path})
|
||||
|
||||
@ -45,7 +44,7 @@ def scan_assets(scene, blueprints_data, settings):
|
||||
assets_list_name = f"assets_{scene.name}"
|
||||
assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]}
|
||||
|
||||
print("blueprint assets", blueprint_assets_list)
|
||||
#print("blueprint assets", blueprint_assets_list)
|
||||
|
||||
|
||||
def get_userTextures():
|
||||
|
@ -42,9 +42,7 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
||||
if editable:
|
||||
row = panel.row()
|
||||
#panel.separator()
|
||||
print("here", user_assets)
|
||||
for asset in user_assets:
|
||||
print("asset", asset)
|
||||
row = panel.row()
|
||||
split = row.split(factor=nesting_indent)
|
||||
col = split.column()
|
||||
|
@ -17,13 +17,12 @@ def find_blueprints_not_on_disk(blueprints, folder_path, extension):
|
||||
def check_if_blueprint_on_disk(scene_name, folder_path, extension):
|
||||
gltf_output_path = os.path.join(folder_path, scene_name + extension)
|
||||
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
|
||||
print("level", scene_name, "found", found, "path", gltf_output_path)
|
||||
return found
|
||||
|
||||
def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_path, gltf_extension):
|
||||
for blueprint in internal_blueprints:
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
||||
print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name)
|
||||
# print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name)
|
||||
|
||||
blueprint.collection["export_path"] = blueprint_exported_path
|
||||
|
||||
@ -44,14 +43,14 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, settings):
|
||||
for blueprint_name in blueprint_instance_names_for_scene:
|
||||
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
|
||||
if blueprint is not None:
|
||||
print("BLUEPRINT", blueprint)
|
||||
#print("BLUEPRINT", blueprint)
|
||||
blueprint_exported_path = None
|
||||
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
|
||||
print("foo", dict(blueprint.collection))
|
||||
#print("foo", dict(blueprint.collection))
|
||||
if blueprint_exported_path is not None:
|
||||
blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "internal": True})
|
||||
|
||||
@ -61,9 +60,7 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, settings):
|
||||
assets_list_name = f"assets_{scene.name}"
|
||||
scene["assets"] = json.dumps(blueprint_assets_list)
|
||||
|
||||
print("blueprint assets", blueprint_assets_list)
|
||||
"""add_scene_property(scene, assets_list_name, assets_list_data)
|
||||
"""
|
||||
#print("blueprint assets", blueprint_assets_list)
|
||||
|
||||
def remove_blueprints_list_from_main_scene(scene):
|
||||
assets_list = None
|
||||
|
@ -7,31 +7,25 @@ import blenvy.add_ons.auto_export.settings as auto_export_settings
|
||||
import blenvy.add_ons.bevy_components.settings as component_settings
|
||||
|
||||
|
||||
|
||||
# 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',
|
||||
#'project_root_path_full', 'assets_path_full', ''
|
||||
]
|
||||
settings_black_list = ['settings_save_enabled', 'main_scene_selector', 'library_scene_selector']
|
||||
|
||||
def save_settings(settings, context):
|
||||
if settings.settings_save_enabled:
|
||||
settings_dict = generate_complete_settings_dict(settings, BlenvyManager, [])
|
||||
print("save settings", settings, context, settings_dict)
|
||||
# upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list})
|
||||
raw_settings = {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list}
|
||||
# we need to inject the main & library scene names as they are computed properties, not blender ones
|
||||
raw_settings['main_scenes_names'] = settings.main_scenes_names
|
||||
raw_settings['library_scenes_names'] = settings.library_scenes_names
|
||||
upsert_settings(settings.settings_save_path, raw_settings, overwrite=True)
|
||||
|
||||
def update_scene_lists(blenvy, context):
|
||||
blenvy.main_scene_names = [scene.name for scene in blenvy.main_scenes] # FIXME: unsure
|
||||
blenvy.library_scene_names = [scene.name for scene in blenvy.library_scenes] # FIXME: unsure
|
||||
upsert_settings(blenvy.settings_save_path, {"main_scene_names": [scene.name for scene in blenvy.main_scenes]})
|
||||
upsert_settings(blenvy.settings_save_path, {"library_scene_names": [scene.name for scene in blenvy.library_scenes]})
|
||||
|
||||
def update_asset_folders(blenvy, context):
|
||||
def update_asset_folders(settings, context):
|
||||
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
||||
for asset_path_name in asset_path_names:
|
||||
upsert_settings(blenvy.settings_save_path, {asset_path_name: getattr(blenvy, asset_path_name)})
|
||||
upsert_settings(settings.settings_save_path, {asset_path_name: getattr(settings, asset_path_name)})
|
||||
settings_dict = generate_complete_settings_dict(settings, BlenvyManager, [])
|
||||
upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list}, overwrite=True)
|
||||
|
||||
def update_mode(blenvy, context):
|
||||
upsert_settings(blenvy.settings_save_path, {"mode": blenvy.mode })
|
||||
|
||||
def is_scene_already_in_use(self, scene):
|
||||
try:
|
||||
@ -45,7 +39,7 @@ def is_scene_already_in_use(self, scene):
|
||||
class BlenvyManager(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_common_settings" # where to store data in bpy.texts
|
||||
settings_save_enabled = BoolProperty(name="settings save enabled", default=True)
|
||||
settings_save_enabled: BoolProperty(name="settings save enabled", default=True) # type: ignore
|
||||
|
||||
mode: EnumProperty(
|
||||
items=(
|
||||
@ -56,14 +50,15 @@ class BlenvyManager(PropertyGroup):
|
||||
('SETTINGS', "Settings", ""),
|
||||
('TOOLS', "Tools", ""),
|
||||
),
|
||||
update=update_mode
|
||||
default="SETTINGS",
|
||||
update=save_settings
|
||||
) # type: ignore
|
||||
|
||||
project_root_path: StringProperty(
|
||||
name = "Project Root Path",
|
||||
description="The root folder of your (Bevy) project (not assets!)",
|
||||
default='../',
|
||||
update= update_asset_folders
|
||||
update= save_settings
|
||||
) # type: ignore
|
||||
|
||||
# computed property for the absolute path of assets
|
||||
@ -76,7 +71,7 @@ class BlenvyManager(PropertyGroup):
|
||||
description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ',
|
||||
default='./assets',
|
||||
options={'HIDDEN'},
|
||||
update= update_asset_folders
|
||||
update= save_settings
|
||||
) # type: ignore
|
||||
|
||||
# computed property for the absolute path of assets
|
||||
@ -88,7 +83,7 @@ class BlenvyManager(PropertyGroup):
|
||||
name='Blueprints path',
|
||||
description='path to export the blueprints to (relative to the assets folder)',
|
||||
default='blueprints',
|
||||
update= update_asset_folders
|
||||
update= save_settings
|
||||
) # type: ignore
|
||||
|
||||
# computed property for the absolute path of blueprints
|
||||
@ -100,7 +95,7 @@ class BlenvyManager(PropertyGroup):
|
||||
name='Levels path',
|
||||
description='path to export the levels (main scenes) to (relative to the assets folder)',
|
||||
default='levels',
|
||||
update= update_asset_folders
|
||||
update= save_settings
|
||||
) # type: ignore
|
||||
|
||||
# computed property for the absolute path of blueprints
|
||||
@ -112,7 +107,7 @@ class BlenvyManager(PropertyGroup):
|
||||
name='Materials path',
|
||||
description='path to export the materials libraries to (relative to the assets folder)',
|
||||
default='materials',
|
||||
update= update_asset_folders
|
||||
update= save_settings
|
||||
) # type: ignore
|
||||
|
||||
# computed property for the absolute path of blueprints
|
||||
@ -124,8 +119,8 @@ class BlenvyManager(PropertyGroup):
|
||||
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
||||
components: PointerProperty(type=component_settings.ComponentsSettings) # 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
|
||||
main_scene_selector: PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=is_scene_already_in_use, update=save_settings)# type: ignore
|
||||
library_scene_selector: PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=is_scene_already_in_use, update=save_settings)# type: ignore
|
||||
|
||||
@property
|
||||
def main_scenes(self):
|
||||
@ -171,13 +166,21 @@ class BlenvyManager(PropertyGroup):
|
||||
print("LOAD SETTINGS")
|
||||
settings = load_settings(self.settings_save_path)
|
||||
if settings is not None:
|
||||
if "mode" in settings:
|
||||
self.settings_save_enabled = False # we disable auto_saving of our settings
|
||||
try:
|
||||
for setting in settings:
|
||||
print("setting", setting, settings[setting])
|
||||
setattr(self, setting, settings[setting])
|
||||
except:pass
|
||||
"""if "mode" in settings:
|
||||
self.mode = settings["mode"]
|
||||
|
||||
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
||||
for asset_path_name in asset_path_names:
|
||||
if asset_path_name in settings:
|
||||
setattr(self, asset_path_name, settings[asset_path_name])
|
||||
setattr(self, asset_path_name, settings[asset_path_name])"""
|
||||
|
||||
self.settings_save_enabled = True
|
||||
|
||||
# now load auto_export settings
|
||||
self.auto_export.load_settings()
|
||||
|
@ -28,6 +28,8 @@ class BLENVY_OT_scenes_list_actions(Operator):
|
||||
def invoke(self, context, event):
|
||||
if self.action == 'REMOVE':
|
||||
bpy.data.scenes[self.scene_name].blenvy_scene_type = 'None'
|
||||
context.window_manager.blenvy.main_scene_selector = None # we use these to force update/save the list of main/library scenes
|
||||
context.window_manager.blenvy.library_scene_selector = None # we use these to force update/save the list of main/library scenes
|
||||
"""info = 'Item "%s" removed from list' % (target[idx].name)
|
||||
target.remove(idx)
|
||||
|
||||
@ -49,9 +51,9 @@ class BLENVY_OT_scenes_list_actions(Operator):
|
||||
print("adding scene", scene_to_add)
|
||||
|
||||
if self.scene_type == "LEVEL":
|
||||
context.window_manager.blenvy.main_scene_selector = None
|
||||
context.window_manager.blenvy.main_scene_selector = None # we use these to force update/save the list of main/library scenes
|
||||
else:
|
||||
context.window_manager.blenvy.library_scene_selector = None
|
||||
context.window_manager.blenvy.library_scene_selector = None # we use these to force update/save the list of main/library scenes
|
||||
|
||||
#setattr(source, target_index, len(target) - 1)
|
||||
|
||||
|
@ -70,7 +70,6 @@ def are_settings_identical(old, new, white_list=None):
|
||||
if old is not None and new is None:
|
||||
return False
|
||||
|
||||
#print("TUTU", old_items, new_items)
|
||||
old_items = sorted(old.items())
|
||||
new_items = sorted(new.items())
|
||||
|
||||
@ -86,3 +85,33 @@ def are_settings_identical(old, new, white_list=None):
|
||||
new_items = sorted(new_items_override.items())
|
||||
|
||||
return old_items == new_items
|
||||
|
||||
|
||||
# if one of the changed settings is not in the white list, it gets discarded
|
||||
def changed_settings(old, new, white_list=[]):
|
||||
if old is None and new is None:
|
||||
return []
|
||||
if old is None and new is not None:
|
||||
return new.keys()
|
||||
if old is not None and new is None:
|
||||
return []
|
||||
|
||||
old_items = sorted(old.items())
|
||||
new_items = sorted(new.items())
|
||||
|
||||
result = []
|
||||
old_keys = list(old.keys())
|
||||
new_keys =list(new.keys())
|
||||
added = list(set(new_keys) - set(old_keys))
|
||||
removed = list(set(old_keys) - set(new_keys))
|
||||
|
||||
result += added
|
||||
result += removed
|
||||
for key in new.keys():
|
||||
if key in old:
|
||||
if new[key] != old[key]:
|
||||
result.append(key)
|
||||
|
||||
|
||||
|
||||
return [key for key in list(set(result)) if key in white_list]
|
||||
|
@ -121,9 +121,9 @@ def test_export_complex(setup_data):
|
||||
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"
|
||||
#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()
|
||||
|
Loading…
Reference in New Issue
Block a user