diff --git a/TODO.md b/TODO.md index bd72c32..fe53d45 100644 --- a/TODO.md +++ b/TODO.md @@ -226,10 +226,13 @@ Blender side: - [ ] materials_path custom property should be ignored both in the list of fixable component AND on export - [ ] if we want to add material_infos & others as normal components they should not be editable, so we need another attribute, and adapt the UI for that - - [ ] if material library is toggled, then changes to materials should not change the blueprints that are using them => not really: as the name & co might change + - [x] if material library is toggled, then changes to materials should not change the blueprints that are using them => not really: as the name & co might change - [ ] 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 + - [x] review & upgrade overall logic of material libraries, their names & output path + - [x] change materials logic to work with multiple materials per mesh + - [x] the index of the generated gltf files is reliable, and can be used both in Blender & Bevy + - [x] change MaterialInfo to MaterialInfos & turn it into a vec/list & updated logic both on Blender & Bevy side + - [ ] persist exported materials paths 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 ?) @@ -323,7 +326,7 @@ Bevy Side: - [x] fix "remove component" operator from the rename/fix/update components panel - [ ] replace string in BlueprintInfo path with PathBuf ? -- [ ] update main docs +- [x] update main docs - [x] rename project to Blenvy - [x] replace all references to the old 2 add-ons with those to Blenvy - [x] rename repo to "Blenvy" diff --git a/crates/blenvy/src/blueprints/materials.rs b/crates/blenvy/src/blueprints/materials.rs index 1a4c9eb..eacaa94 100644 --- a/crates/blenvy/src/blueprints/materials.rs +++ b/crates/blenvy/src/blueprints/materials.rs @@ -2,8 +2,7 @@ use bevy::prelude::*; use crate::BlenvyConfig; -#[derive(Component, Reflect, Default, Debug)] -#[reflect(Component)] +#[derive(Reflect, Default, Debug)] /// struct containing the name & path of the material to apply pub struct MaterialInfo { pub name: String, @@ -12,6 +11,7 @@ pub struct MaterialInfo { #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] +/// component containing the full list of MaterialInfos for a given entity/object pub struct MaterialInfos(Vec); #[derive(Component, Default, Debug)] @@ -45,7 +45,6 @@ pub(crate) fn inject_materials( 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 .contains_key(&material_full_path) diff --git a/tools/blenvy.zip b/tools/blenvy.zip deleted file mode 100644 index a570a43..0000000 Binary files a/tools/blenvy.zip and /dev/null differ diff --git a/tools/blenvy/add_ons/auto_export/constants.py b/tools/blenvy/add_ons/auto_export/constants.py index 88fa5f6..9732bab 100644 --- a/tools/blenvy/add_ons/auto_export/constants.py +++ b/tools/blenvy/add_ons/auto_export/constants.py @@ -8,4 +8,4 @@ custom_properties_to_filter_out = [ '_combine', 'template', 'Blenvy_scene_type', 'blenvy_scene_type', 'materials_path', 'export_path', - ] +] diff --git a/tools/blenvy/add_ons/auto_export/levels/export_levels.py b/tools/blenvy/add_ons/auto_export/levels/export_levels.py index cda7886..0ce9c5c 100644 --- a/tools/blenvy/add_ons/auto_export/levels/export_levels.py +++ b/tools/blenvy/add_ons/auto_export/levels/export_levels.py @@ -1,5 +1,4 @@ import os -from blenvy.blueprints.blueprint_helpers import inject_blueprints_list_into_level_scene, remove_blueprints_list_from_level_scene from ..constants import TEMPSCENE_PREFIX from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene from ..common.export_gltf import (generate_gltf_export_settings, export_gltf) @@ -26,8 +25,8 @@ def export_level_scene(scene, settings, blueprints_data): if export_blueprints : gltf_output_path = os.path.join(levels_path_full, scene.name) - - inject_blueprints_list_into_level_scene(scene, blueprints_data, settings) + # we inject assets into the scene before it gets exported + # TODO: this should be done in the temporary scene ! upsert_scene_assets(scene, blueprints_data=blueprints_data, settings=settings) if export_separate_dynamic_and_static_objects: @@ -67,8 +66,6 @@ def export_level_scene(scene, settings, blueprints_data): tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params) ) - remove_blueprints_list_from_level_scene(scene) - else: gltf_output_path = os.path.join(assets_path_full, scene.name) print(" exporting gltf to", gltf_output_path, ".gltf/glb") 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 606fbe4..61d45df 100644 --- a/tools/blenvy/add_ons/auto_export/materials/export_materials.py +++ b/tools/blenvy/add_ons/auto_export/materials/export_materials.py @@ -90,8 +90,6 @@ 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) @@ -105,22 +103,7 @@ def export_materials(materials_to_export, settings, blueprints_data): 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( - 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_materials_scene_content(temp_collection, used_material_names), - tempScene_cleaner= lambda temp_scene, params: clear_materials_scene(temp_scene=temp_scene) - ) - - - def cleanup_materials(collections, library_scenes): # remove temporary components clear_material_info(collections, library_scenes) \ No newline at end of file diff --git a/tools/blenvy/add_ons/auto_export/utils.py b/tools/blenvy/add_ons/auto_export/utils.py index 8bd4779..661aae2 100644 --- a/tools/blenvy/add_ons/auto_export/utils.py +++ b/tools/blenvy/add_ons/auto_export/utils.py @@ -24,63 +24,14 @@ def assets_to_fake_ron(list_like): # TODO : move to assets def upsert_scene_assets(scene, blueprints_data, settings): - """print("level scene", scene) - for asset in scene.user_assets: - print(" user asset", asset.name, asset.path) - for asset in scene.generated_assets: - print(" generated asset", asset)""" - """for blueprint in blueprints_data.blueprints_per_scenes[scene.name]: - print("BLUEPRINT", blueprint)""" - blueprint_instances_in_scene = blueprints_data.blueprint_instances_per_level_scene.get(scene.name, {}).keys() - blueprints_in_scene = [blueprints_data.blueprints_per_name[blueprint_name] for blueprint_name in blueprint_instances_in_scene] - #yala = [blueprint.collection.user_assets for blueprint in blueprints_in_scene] - #print("dsfsdf", yala) - level_assets = [] all_assets = [] - export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb") - - blueprints_path = getattr(settings, "blueprints_path") - for blueprint in blueprints_in_scene: - if blueprint.local: - blueprint_exported_path = posixpath.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 - # add their material path - materials_exported_path = blueprint.collection['materials_path'] if 'materials_path' in blueprint.collection else None - level_assets.append({"name": blueprint.name+"_material", "path": materials_exported_path})#, "generated": True, "internal":blueprint.local, "parent": None}) - - - if blueprint_exported_path is not None: # and not does_asset_exist(assets_list, blueprint_exported_path): - level_assets.append({"name": blueprint.name, "path": blueprint_exported_path})#, "generated": True, "internal":blueprint.local, "parent": None}) - - # now also add the assets of the blueprints # TODO: wait no , these should not be a part of the (scene) local assets - for asset in blueprint.collection.user_assets: - #print("adding assets of blueprint", asset.name) - all_assets.append({"name": asset.name, "path": asset.path}) - - """for asset in level_assets: - print(" generated asset", asset.name, asset.path)""" - - materials_path = getattr(settings, "materials_path") - current_project_name = Path(bpy.context.blend_data.filepath).stem - materials_library_name = f"{current_project_name}_materials" - materials_exported_path = posixpath.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 - print("material_assets", material_assets, "extension", export_gltf_extension) - - all_assets_raw = get_level_scene_assets_tree2(level_scene=scene, blueprints_data=blueprints_data, settings=settings) local_assets = [{"name": asset["name"], "path": asset["path"]} for asset in all_assets_raw if asset['parent'] is None and asset["path"] != "" ] all_assets = [{"name": asset["name"], "path": asset["path"]} for asset in all_assets_raw if asset["path"] != "" ] print("all_assets_raw", all_assets_raw) print("all_assets", all_assets) - print("local assets", local_assets + material_assets) - scene["BlueprintAssets"] = assets_to_fake_ron(local_assets + material_assets) - - - #scene["BlueprintAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + level_assets + material_assets) - #scene["BlueprintAssets"] = assets_to_fake_ron([{'name':'foo', 'path':'bar'}]) + print("local assets", local_assets) + scene["BlueprintAssets"] = assets_to_fake_ron(all_assets) #local_assets def upsert_blueprint_assets(blueprint, blueprints_data, settings): all_assets_raw = get_blueprint_asset_tree(blueprint=blueprint, blueprints_data=blueprints_data, settings=settings) diff --git a/tools/blenvy/assets/assets_scan.py b/tools/blenvy/assets/assets_scan.py index d24f64b..a95a463 100644 --- a/tools/blenvy/assets/assets_scan.py +++ b/tools/blenvy/assets/assets_scan.py @@ -3,6 +3,7 @@ import json import posixpath import bpy +from ..materials.materials_helpers import get_blueprint_materials from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list def scan_assets(scene, blueprints_data, settings): @@ -62,6 +63,7 @@ def get_userTextures(): print("textures", textures) def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings): + print("blueprint", blueprint.name) blueprints_path = getattr(settings, "blueprints_path") export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb") assets_list = [] @@ -88,6 +90,15 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings): asset["parent"] = parent asset["internal"] = blueprint.local assets_list += direct_assets + + # now get materials used by this blueprint + (blueprint_materials_names, materials_per_object) = get_blueprint_materials(blueprint=blueprint) + print("blueprint_materials", blueprint_materials_names) + for material_name in blueprint_materials_names: + materials_path = getattr(settings, "materials_path") + materials_exported_path = posixpath.join(materials_path, f"{material_name}{export_gltf_extension}") + assets_list.append({"name": material_name, "path": materials_exported_path, "type": "MATERIAL", "generated": True,"internal":blueprint.local, "parent": blueprint.name}) + return assets_list def get_level_scene_assets_tree(level_scene, blueprints_data, settings): diff --git a/tools/blenvy/assets/operators.py b/tools/blenvy/assets/operators.py index 35ed9b9..cc01474 100644 --- a/tools/blenvy/assets/operators.py +++ b/tools/blenvy/assets/operators.py @@ -70,11 +70,6 @@ class BLENVY_OT_assets_add(Operator): context.window_manager.assets_registry.asset_type_selector = "MODEL" context.window_manager.assets_registry.asset_path_selector = "" - """if blueprint_assets: - bpy.data.collections[self.target_name]["assets"] = json.dumps(assets) - else: - bpy.data.scenes[self.target_name]["assets"] = json.dumps(assets)""" - return {'FINISHED'} diff --git a/tools/blenvy/blueprints/blueprint_helpers.py b/tools/blenvy/blueprints/blueprint_helpers.py index 92e2f3a..9fdb280 100644 --- a/tools/blenvy/blueprints/blueprint_helpers.py +++ b/tools/blenvy/blueprints/blueprint_helpers.py @@ -5,8 +5,6 @@ import bpy from pathlib import Path import posixpath -from ..core.scene_helpers import add_scene_property - def find_blueprints_not_on_disk(blueprints, folder_path, extension): not_found_blueprints = [] for blueprint in blueprints: @@ -23,64 +21,9 @@ def check_if_blueprint_on_disk(scene_name, folder_path, extension): return found def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_path, gltf_extension, settings): - export_materials_library = getattr(settings.auto_export, "export_materials_library") - # FIXME: duplicate of materials stuff - export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb") - materials_path = getattr(settings, "materials_path") - current_project_name = Path(bpy.context.blend_data.filepath).stem - materials_library_name = f"{current_project_name}_materials" - materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}") - for blueprint in internal_blueprints: blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{gltf_extension}") # print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name) blueprint.collection["export_path"] = blueprint_exported_path - if export_materials_library: - blueprint.collection["materials_path"] = materials_exported_path - - -def inject_blueprints_list_into_level_scene(scene, blueprints_data, settings): - project_root_path = getattr(settings, "project_root_path") - assets_path = getattr(settings,"assets_path") - levels_path = getattr(settings,"levels_path") - blueprints_path = getattr(settings, "blueprints_path") - export_gltf_extension = getattr(settings, "export_gltf_extension") - - # print("injecting assets/blueprints data into scene") - assets_list_name = f"assets_list_{scene.name}_components" - assets_list_data = {} - - blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_level_scene.get(scene.name, None) - blueprint_assets_list = [] - if blueprint_instance_names_for_scene: - 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) - blueprint_exported_path = None - if blueprint.local: - blueprint_exported_path = posixpath.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)) - if blueprint_exported_path is not None: - blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "internal": True}) - - - - - assets_list_name = f"assets_{scene.name}" - scene["assets"] = json.dumps(blueprint_assets_list) - - #print("blueprint assets", blueprint_assets_list) - -def remove_blueprints_list_from_level_scene(scene): - assets_list = None - assets_list_name = f"assets_list_{scene.name}_components" - - for object in scene.objects: - if object.name == assets_list_name: - assets_list = object - if assets_list is not None: - bpy.data.objects.remove(assets_list, do_unlink=True) + """if export_materials_library: + blueprint.collection["materials_path"] = materials_exported_path""" diff --git a/tools/blenvy/materials/materials_helpers.py b/tools/blenvy/materials/materials_helpers.py index e5162de..df618dd 100644 --- a/tools/blenvy/materials/materials_helpers.py +++ b/tools/blenvy/materials/materials_helpers.py @@ -1,28 +1,15 @@ import os import posixpath -import bpy -from pathlib import Path - from ..core.helpers_collections import (traverse_tree) def find_materials_not_on_disk(materials, materials_path_full, extension): 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: - if not found: - 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) found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path) if not found: - not_found_materials.append(material)""" + not_found_materials.append(material) return not_found_materials def check_if_material_on_disk(scene_name, folder_path, extension): @@ -64,22 +51,15 @@ def get_all_materials(collection_names, library_scenes): 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") - - current_project_name = Path(bpy.context.blend_data.filepath).stem - materials_library_name = f"{current_project_name}_materials" - 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_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 + materials_exported_path = posixpath.join(materials_path, f"{material.name}{export_gltf_extension}") 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) - - materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}") - #object['MaterialInfo'] = component_value 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)