diff --git a/crates/blenvy/src/blueprints/materials.rs b/crates/blenvy/src/blueprints/materials.rs index d91a213..1a4c9eb 100644 --- a/crates/blenvy/src/blueprints/materials.rs +++ b/crates/blenvy/src/blueprints/materials.rs @@ -10,14 +10,18 @@ pub struct MaterialInfo { pub path: String, } +#[derive(Component, Reflect, Default, Debug)] +#[reflect(Component)] +pub struct MaterialInfos(Vec); + #[derive(Component, Default, Debug)] pub struct MaterialProcessed; /// system that injects / replaces materials from material library pub(crate) fn inject_materials( mut blenvy_config: ResMut, - material_infos: Query< - (Entity, &MaterialInfo, &Children), + material_infos_query: Query< + (Entity, &MaterialInfos, &Children), Without, // (With) /*( Added, @@ -37,57 +41,65 @@ pub(crate) fn inject_materials( mut commands: Commands, ) { - for (entity, material_info, children) in material_infos.iter() { - let material_full_path = format!("{}#{}", material_info.path, material_info.name); - let mut material_found: Option<&Handle> = None; - - if blenvy_config - .materials_cache - .contains_key(&material_full_path) - { - debug!("material is cached, retrieving"); - let material = blenvy_config + for (entity, material_infos, children) in material_infos_query.iter() { + for (material_index, material_info) in material_infos.0.iter().enumerate() { + let material_full_path = format!("{}#{}", material_info.path, material_info.name); + let mut material_found: Option<&Handle> = None; + + if blenvy_config .materials_cache - .get(&material_full_path) - .expect("we should have the material available"); - material_found = Some(material); - } else { - let model_handle: Handle = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now - let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| { - panic!( - "materials file {} should have been preloaded", - material_info.path - ) - }); - if mat_gltf - .named_materials - .contains_key(&material_info.name as &str) + .contains_key(&material_full_path) { - let material = mat_gltf - .named_materials - .get(&material_info.name as &str) - .expect("this material should have been loaded at this stage, please make sure you are correctly preloading them"); - blenvy_config + debug!("material is cached, retrieving"); + let material = blenvy_config .materials_cache - .insert(material_full_path, material.clone()); + .get(&material_full_path) + .expect("we should have the material available"); material_found = Some(material); + } else { + let model_handle: Handle = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now + let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| { + panic!( + "materials file {} should have been preloaded", + material_info.path + ) + }); + if mat_gltf + .named_materials + .contains_key(&material_info.name as &str) + { + let material = mat_gltf + .named_materials + .get(&material_info.name as &str) + .expect("this material should have been loaded at this stage, please make sure you are correctly preloading them"); + blenvy_config + .materials_cache + .insert(material_full_path, material.clone()); + material_found = Some(material); + } } - } - commands.entity(entity).insert(MaterialProcessed); - - if let Some(material) = material_found { - for child in children.iter() { - if with_materials_and_meshes.contains(*child) { - info!( - "injecting material {}, path: {:?}", - material_info.name, - material_info.path.clone() - ); - - commands.entity(*child).insert(material.clone()); + if let Some(material) = material_found { + for (child_index, child) in children.iter().enumerate() { + if child_index == material_index { + if with_materials_and_meshes.contains(*child) { + info!( + "injecting material {}, path: {:?}", + material_info.name, + material_info.path.clone() + ); + + commands.entity(*child).insert(material.clone()); + } + } + } } } + + + commands.entity(entity).insert(MaterialProcessed); + + } } diff --git a/crates/blenvy/src/blueprints/mod.rs b/crates/blenvy/src/blueprints/mod.rs index 2d1ade6..278a5dc 100644 --- a/crates/blenvy/src/blueprints/mod.rs +++ b/crates/blenvy/src/blueprints/mod.rs @@ -91,6 +91,8 @@ impl Plugin for BlueprintsPlugin { .add_event::() .register_type::() .register_type::() + .register_type::() + .register_type::() .register_type::() .register_type::() diff --git a/tools/blenvy.zip b/tools/blenvy.zip new file mode 100644 index 0000000..a570a43 Binary files /dev/null and b/tools/blenvy.zip differ diff --git a/tools/blenvy/add_ons/auto_export/common/auto_export.py b/tools/blenvy/add_ons/auto_export/common/auto_export.py index 4fad23b..2f9c98e 100644 --- a/tools/blenvy/add_ons/auto_export/common/auto_export.py +++ b/tools/blenvy/add_ons/auto_export/common/auto_export.py @@ -102,7 +102,7 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material, old_selections = bpy.context.selected_objects # deal with materials - if export_materials_library: + if export_materials_library and len(materials_to_export) > 0: print("export MATERIALS") export_materials(materials_to_export, settings, blueprints_data) diff --git a/tools/blenvy/add_ons/auto_export/common/export_gltf.py b/tools/blenvy/add_ons/auto_export/common/export_gltf.py index fc72ce0..131ab4f 100644 --- a/tools/blenvy/add_ons/auto_export/common/export_gltf.py +++ b/tools/blenvy/add_ons/auto_export/common/export_gltf.py @@ -73,7 +73,7 @@ def generate_gltf_export_settings(settings): if str(key) not in constant_keys: gltf_export_settings[key] = standard_gltf_exporter_settings.get(key) - print("GLTF EXPORT SETTINGS", gltf_export_settings) + #print("GLTF EXPORT SETTINGS", gltf_export_settings) return gltf_export_settings diff --git a/tools/blenvy/add_ons/auto_export/materials/export_materials.py b/tools/blenvy/add_ons/auto_export/materials/export_materials.py index 866b499..606fbe4 100644 --- a/tools/blenvy/add_ons/auto_export/materials/export_materials.py +++ b/tools/blenvy/add_ons/auto_export/materials/export_materials.py @@ -46,6 +46,13 @@ def generate_materials_scene_content(root_collection, used_material_names): make_material_object("Material_"+material_name, [index * 0.2,0,0], material=material, collection=root_collection) return {} +# generates a scene for a given material +def generate_material_scene_content(root_collection, material_name): + material = bpy.data.materials[material_name] + make_material_object(f"Material_{material_name}", [0,0,0], material=material, collection=root_collection) + return {} + + def clear_materials_scene(temp_scene): root_collection = temp_scene.collection scene_objects = [o for o in root_collection.objects] @@ -83,9 +90,23 @@ def export_materials(materials_to_export, settings, blueprints_data): 'export_apply':True } + + + for material in materials_to_export: + print("exporting material", material.name) + gltf_output_path = os.path.join(materials_path_full, material.name) + + generate_temporary_scene_and_export( + settings=settings, + gltf_export_settings=gltf_export_settings, + temp_scene_name="__materials_scene", + gltf_output_path=gltf_output_path, + tempScene_filler= lambda temp_collection: generate_material_scene_content(temp_collection, material.name), + tempScene_cleaner= lambda temp_scene, params: clear_materials_scene(temp_scene=temp_scene) + ) + 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") generate_temporary_scene_and_export( diff --git a/tools/blenvy/add_ons/auto_export/materials/get_materials_to_export.py b/tools/blenvy/add_ons/auto_export/materials/get_materials_to_export.py index 0a660c1..84ed4b6 100644 --- a/tools/blenvy/add_ons/auto_export/materials/get_materials_to_export.py +++ b/tools/blenvy/add_ons/auto_export/materials/get_materials_to_export.py @@ -8,21 +8,26 @@ def get_materials_to_export(changes_per_material, changed_export_parameters, blu materials_path_full = getattr(settings,"materials_path_full", "") change_detection = getattr(settings.auto_export, "change_detection") + export_materials_library = getattr(settings.auto_export, "export_materials_library") collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode") all_materials = bpy.data.materials local_materials = [material for material in all_materials if material.library is None] materials_to_export = [] - if change_detection and not changed_export_parameters: - changed_materials = [bpy.data.materials[material_name] for material_name in list(changes_per_material.keys())] - # 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) - materials_not_on_disk = find_materials_not_on_disk(local_materials, materials_path_full, export_gltf_extension) + if export_materials_library and change_detection: + if changed_export_parameters: + materials_to_export = [bpy.data.materials[material_name] for material_name in list(changes_per_material.keys())] # TODO: should be based on the list of materials in use + else : + changed_materials = [bpy.data.materials[material_name] for material_name in list(changes_per_material.keys())] - # also deal with blueprints that are always marked as "always_export" - #materials_always_export = [material for material in internal_materials if is_material_always_export(material)] - materials_always_export = [] - materials_to_export = list(set(changed_materials + materials_not_on_disk + materials_always_export)) + # 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) + materials_not_on_disk = find_materials_not_on_disk(local_materials, materials_path_full, export_gltf_extension) + # also deal with blueprints that are always marked as "always_export" + #materials_always_export = [material for material in internal_materials if is_material_always_export(material)] + materials_always_export = [] + materials_to_export = list(set(changed_materials + materials_not_on_disk + materials_always_export)) + print("materials_to_export", materials_to_export, local_materials) return materials_to_export diff --git a/tools/blenvy/materials/materials_helpers.py b/tools/blenvy/materials/materials_helpers.py index 39478ac..e5162de 100644 --- a/tools/blenvy/materials/materials_helpers.py +++ b/tools/blenvy/materials/materials_helpers.py @@ -40,7 +40,9 @@ def get_materials(object, materials_per_object): # print(" slot", m, "material", material) used_materials_names.append(material.name) # TODO:, also respect slots & export multiple materials if applicable ! - materials_per_object[object] = material + if not object in materials_per_object: + materials_per_object[object] = [] + materials_per_object[object].append(material) return used_materials_names @@ -68,16 +70,18 @@ def add_material_info_to_objects(materials_per_object, settings): materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}") #print("ADDING MAERIAL INFOS") for object in materials_per_object.keys(): - material = materials_per_object[object] + material_infos = [] + for material in materials_per_object[object]: + # problem with using actual components: you NEED the type registry/component infos, so if there is none , or it is not loaded yet, it does not work + # for a few components we could hardcode this + material_info = f'(name: "{material.name}", path: "{materials_exported_path}")' + #bpy.ops.blenvy.component_add(target_item_name=object.name, target_item_type="OBJECT", component_type="blenvy::blueprints::materials::MaterialInfo", component_value=component_value) - # problem with using actual components: you NEED the type registry/component infos, so if there is none , or it is not loaded yet, it does not work - # for a few components we could hardcode this - component_value = f'(name: "{material.name}", path: "{materials_exported_path}")' - #bpy.ops.blenvy.component_add(target_item_name=object.name, target_item_type="OBJECT", component_type="blenvy::blueprints::materials::MaterialInfo", component_value=component_value) - - materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}") - object['MaterialInfo'] = component_value - print("adding materialInfo to object", object, "material info", component_value) + materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}") + #object['MaterialInfo'] = component_value + material_infos.append(material_info) + object['MaterialInfos'] = f"({material_infos})".replace("'","") + print("adding materialInfos to object", object, "material infos", material_infos) # get all the materials of all objects in a given scene