Compare commits

..

1 Commits

Author SHA1 Message Date
Mark Moissette aba2a4f5e5
Merge 4a72ed68bf into 9b50d77790 2024-07-21 22:51:54 +00:00
6 changed files with 22 additions and 83 deletions

View File

@ -222,9 +222,7 @@ Blender side:
- [ ] materials fixes & upgrades - [ ] materials fixes & upgrades
- [x] materials do not get exported again if the files are missing, until you change a material - [x] materials do not get exported again if the files are missing, until you change a material
- [x] materials do not get exported when a material is added ? - [x] materials do not get exported when a material is added ?
- [ ] if material library is toggled, then changes to materials should not change the blueprints that are using them ?
- [ ] material assets seem to be added to list regardless of whether material exports are enabled or not - [ ] material assets seem to be added to list regardless of whether material exports are enabled or not
- [ ] review & upgrade overall logic of material libraries, their names & output path
- [ ] persist exported materials path in blueprints so that it can be read from library file users - [ ] 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 - [ ] just like "export_path" write it into each blueprint's collection
- [ ] scan for used materials per blueprint ! - [ ] scan for used materials per blueprint !

View File

@ -49,14 +49,16 @@ impl Default for BluePrintBundle {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// Plugin for gltf blueprints /// Plugin for gltf blueprints
pub struct BlueprintsPlugin {} pub struct BlueprintsPlugin {
}
impl Default for BlueprintsPlugin { impl Default for BlueprintsPlugin {
fn default() -> Self { fn default() -> Self {
Self {} Self { }
} }
} }
fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool { fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
// println!("hot reload ? {}", watching_for_changes.0); // println!("hot reload ? {}", watching_for_changes.0);
watching_for_changes.0 watching_for_changes.0
@ -108,8 +110,6 @@ impl Plugin for BlueprintsPlugin {
.register_type::<Vec<String>>() .register_type::<Vec<String>>()
.register_type::<BlueprintAssets>() .register_type::<BlueprintAssets>()
.register_type::<HashMap<String, Vec<String>>>() .register_type::<HashMap<String, Vec<String>>>()
.init_asset::<RawGltfAsset>()
.init_asset_loader::<RawGltfAssetLoader>()
.configure_sets( .configure_sets(
Update, Update,
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn) (GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
@ -119,7 +119,6 @@ impl Plugin for BlueprintsPlugin {
.add_systems( .add_systems(
Update, Update,
( (
load_raw_gltf,
blueprints_prepare_spawn, blueprints_prepare_spawn,
blueprints_check_assets_loading, blueprints_check_assets_loading,
blueprints_assets_loaded, blueprints_assets_loaded,
@ -133,14 +132,16 @@ impl Plugin for BlueprintsPlugin {
.chain() .chain()
.in_set(GltfBlueprintsSet::Spawn), .in_set(GltfBlueprintsSet::Spawn),
) )
// animation // animation
.add_systems( .add_systems(
Update, Update,
( (
trigger_blueprint_animation_markers_events, trigger_blueprint_animation_markers_events,
trigger_instance_animation_markers_events, trigger_instance_animation_markers_events
), ),
) )
// hot reload // hot reload
.add_systems(Update, react_to_asset_changes.run_if(hot_reload)); .add_systems(Update, react_to_asset_changes.run_if(hot_reload));
} }

View File

@ -1,12 +1,6 @@
use std::path::Path; use std::path::Path;
use bevy::{ use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashMap};
asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
gltf::Gltf,
prelude::*,
scene::SceneInstance,
utils::hashbrown::HashMap,
};
use serde_json::Value; use serde_json::Value;
use crate::{ use crate::{
@ -121,59 +115,17 @@ Overview of the Blueprint Spawning process
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ?? => distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
*/ */
#[derive(Asset, TypePath, Debug)] pub(crate) fn blueprints_prepare_spawn(
pub struct RawGltfAsset(pub RawGltf);
#[derive(Default)]
pub(super) struct RawGltfAssetLoader;
impl AssetLoader for RawGltfAssetLoader {
type Asset = RawGltfAsset;
type Settings = ();
type Error = gltf::Error;
async fn load<'a>(
&'a self,
reader: &'a mut Reader<'_>,
_settings: &'a (),
_load_context: &'a mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let gltf = RawGltf::from_slice_without_validation(&bytes)?;
Ok(RawGltfAsset(gltf))
}
}
#[derive(Debug, Component, Deref, DerefMut)]
#[component(storage = "SparseSet")]
pub(super) struct AssociatedRawGltfHandle(Handle<RawGltfAsset>);
pub(super) fn load_raw_gltf(
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added<SpawnBlueprint>>, blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added<SpawnBlueprint>>,
asset_server: Res<AssetServer>,
mut commands: Commands,
) {
for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() {
let gltf_handle: Handle<RawGltfAsset> = asset_server.load(&blueprint_info.path);
commands
.entity(entity)
.insert(AssociatedRawGltfHandle(gltf_handle));
}
}
pub(super) fn blueprints_prepare_spawn(
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo, &AssociatedRawGltfHandle)>,
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
// for hot reload // for hot reload
watching_for_changes: Res<WatchingForChanges>, watching_for_changes: Res<WatchingForChanges>,
mut assets_to_blueprint_instances: ResMut<AssetToBlueprintInstancesMapper>, mut assets_to_blueprint_instances: ResMut<AssetToBlueprintInstancesMapper>,
raw_gltf_assets: Res<Assets<RawGltfAsset>>,
// for debug // for debug
// all_names: Query<&Name> // all_names: Query<&Name>
) { ) {
for (entity, blueprint_info, raw_gltf_handle) in blueprint_instances_to_spawn.iter() { for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() {
info!( info!(
"BLUEPRINT: to spawn detected: {:?} path:{:?}", "BLUEPRINT: to spawn detected: {:?} path:{:?}",
blueprint_info.name, blueprint_info.path blueprint_info.name, blueprint_info.path
@ -197,9 +149,7 @@ pub(super) fn blueprints_prepare_spawn(
// and we also add all its assets // and we also add all its assets
/* prefetch attempt */ /* prefetch attempt */
let Some(RawGltfAsset(gltf)) = raw_gltf_assets.get(&raw_gltf_handle.0) else { let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap();
continue;
};
for scene in gltf.scenes() { for scene in gltf.scenes() {
if let Some(scene_extras) = scene.extras().clone() { if let Some(scene_extras) = scene.extras().clone() {
let lookup: HashMap<String, Value> = let lookup: HashMap<String, Value> =
@ -304,10 +254,7 @@ pub(super) fn blueprints_prepare_spawn(
.entity(entity) .entity(entity)
.insert(bevy::prelude::Name::from(blueprint_info.name.clone())); .insert(bevy::prelude::Name::from(blueprint_info.name.clone()));
// add the blueprint spawning marker // add the blueprint spawning marker
commands commands.entity(entity).insert(BlueprintSpawning);
.entity(entity)
.insert(BlueprintSpawning)
.remove::<AssociatedRawGltfHandle>();
} }
} }

View File

@ -13340,11 +13340,11 @@
"type": "object", "type": "object",
"typeInfo": "Struct" "typeInfo": "Struct"
}, },
"blenvy::blueprints::animation::InstanceAnimations": { "blenvy::blueprints::animation::SceneAnimations": {
"additionalProperties": false, "additionalProperties": false,
"isComponent": true, "isComponent": true,
"isResource": false, "isResource": false,
"long_name": "blenvy::blueprints::animation::InstanceAnimations", "long_name": "blenvy::blueprints::animation::SceneAnimations",
"properties": { "properties": {
"graph": { "graph": {
"type": { "type": {
@ -13367,7 +13367,7 @@
"named_indices", "named_indices",
"graph" "graph"
], ],
"short_name": "InstanceAnimations", "short_name": "SceneAnimations",
"type": "object", "type": "object",
"typeInfo": "Struct" "typeInfo": "Struct"
}, },

View File

@ -12,9 +12,11 @@ def get_materials_to_export(changes_per_material, changed_export_parameters, blu
all_materials = bpy.data.materials all_materials = bpy.data.materials
local_materials = [material for material in all_materials if material.library is None] local_materials = [material for material in all_materials if material.library is None]
#and (changed_export_parameters or len(changes_per_material.keys()) > 0 )
materials_to_export = [] materials_to_export = []
if change_detection and not changed_export_parameters: if change_detection and not changed_export_parameters:
changed_materials = [bpy.data.materials[material_name] for material_name in list(changes_per_material.keys())] changed_materials = []
# first check if all materials have already been exported before (if this is the first time the exporter is run # first check if all materials have already been exported before (if this is the first time the exporter is run
# in your current Blender session for example) # in your current Blender session for example)
@ -25,4 +27,5 @@ def get_materials_to_export(changes_per_material, changed_export_parameters, blu
materials_always_export = [] materials_always_export = []
materials_to_export = list(set(changed_materials + materials_not_on_disk + materials_always_export)) materials_to_export = list(set(changed_materials + materials_not_on_disk + materials_always_export))
return materials_to_export return materials_to_export

View File

@ -4,24 +4,14 @@ import bpy
from pathlib import Path from pathlib import Path
from ..core.helpers_collections import (traverse_tree) from ..core.helpers_collections import (traverse_tree)
def find_materials_not_on_disk(materials, materials_path_full, extension): def find_materials_not_on_disk(materials, folder_path, extension):
not_found_materials = [] not_found_materials = []
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_full, f"{materials_library_name}{extension}")
found = os.path.exists(materials_exported_path) and os.path.isfile(materials_exported_path)
for material in materials: for material in materials:
if not found: gltf_output_path = os.path.join(folder_path, material.name + extension)
not_found_materials.append(material)
"""for material in materials:
gltf_output_path = os.path.join(materials_path_full, material.name + extension)
# print("gltf_output_path", gltf_output_path) # print("gltf_output_path", gltf_output_path)
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path) found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
if not found: if not found:
not_found_materials.append(material)""" not_found_materials.append(material)
return not_found_materials return not_found_materials
def check_if_material_on_disk(scene_name, folder_path, extension): def check_if_material_on_disk(scene_name, folder_path, extension):