import os import posixpath from ..core.helpers_collections import (traverse_tree) def find_materials_not_on_disk(materials, materials_path_full, extension): not_found_materials = [] for material in materials: gltf_output_path = os.path.join(materials_path_full, material.name + extension) # print("gltf_output_path", gltf_output_path) found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path) if not found: not_found_materials.append(material) return not_found_materials def check_if_material_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) return found # get materials per object, and injects the materialInfo component def get_materials(object, materials_per_object): material_slots = object.material_slots used_materials_names = [] if not hasattr(object, "data"): return used_materials_names if not hasattr(object.data,"materials"): return used_materials_names if len(object.data.materials) == 0: return used_materials_names # since we are scanning polygons to get the actually used materials, we do not get them in the correct order materials_per_object_unordered = [] """materials_count = len(material_slots) print("materials_count", materials_count) material_indices = np.empty(materials_count, dtype=np.int64) object.data.polygons.foreach_get("material_index", material_indices) #for material_index in object.data.polygons.foreach_get("material_index", storage): print("polygon material_indices", material_indices)""" # TODO: perhaps optimise it using foreach_get for polygon in object.data.polygons: slot = material_slots[polygon.material_index] material = slot.material if not material.name in used_materials_names: used_materials_names.append(material.name) materials_per_object_unordered.append((material, polygon.material_index)) if len(used_materials_names) == len(material_slots): # we found all materials, bail out break # now re-order the materials as per the object's material slots sorted_materials = sorted(materials_per_object_unordered, key=lambda tup: tup[1]) # and add them if not object in materials_per_object: materials_per_object[object] = [] materials_per_object[object] = [material[0] for material in sorted_materials]#.append(material) """for m in material_slots: material = m.material""" return used_materials_names def get_all_materials(collection_names, library_scenes): used_material_names = [] materials_per_object = {} for scene in library_scenes: root_collection = scene.collection for cur_collection in traverse_tree(root_collection): if cur_collection.name in collection_names: for object in cur_collection.all_objects: used_material_names = used_material_names + get_materials(object, materials_per_object) # we only want unique names used_material_names = list(set(used_material_names)) return (used_material_names, materials_per_object) def add_material_info_to_objects(materials_per_object, settings): materials_path = getattr(settings, "materials_path") export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb") for object in materials_per_object.keys(): material_infos = [] for material in materials_per_object[object]: materials_exported_path = posixpath.join(materials_path, f"{material.name}{export_gltf_extension}") material_info = f'(name: "{material.name}", path: "{materials_exported_path}")' material_infos.append(material_info) # 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 #bpy.ops.blenvy.component_add(target_item_name=object.name, target_item_type="OBJECT", component_type="blenvy::blueprints::materials::MaterialInfos", component_value=component_value) 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 def get_scene_materials(scene): used_material_names = [] materials_per_object = {} root_collection = scene.collection for cur_collection in traverse_tree(root_collection): for object in cur_collection.all_objects: used_material_names = used_material_names + get_materials(object, materials_per_object) # we only want unique names used_material_names = list(set(used_material_names)) return (used_material_names, materials_per_object) # get all the materials of all objects used by a given blueprint def get_blueprint_materials(blueprint): materials_per_object = {} used_material_names = [] for object in blueprint.collection.all_objects: used_material_names = used_material_names + get_materials(object, materials_per_object) # we only want unique names used_material_names = list(set(used_material_names)) return (used_material_names, materials_per_object)