From d0bc05fb96edc9dfcf6cb9846bb9edc038729994 Mon Sep 17 00:00:00 2001 From: "kaosat.dev" Date: Wed, 15 May 2024 13:25:30 +0200 Subject: [PATCH] feat(blenvy): * added correct injection of assets + export path to blueprints * moved a few common elements to "core" for better reuse * more tweaks/ experiments with paths handling * moved & overhauled a few of the blueprint & assets tools * lots of minor tweaks & changes --- tools/blenvy/TODO.md | 39 ++++- tools/blenvy/__init__.py | 7 +- tools/blenvy/assets/asset_helpers.py | 5 + tools/blenvy/assets/operators.py | 6 +- tools/blenvy/assets/ui.py | 51 +++--- tools/blenvy/bevy_components/helpers.py | 19 -- tools/blenvy/blueprints/blueprint.py | 18 ++ tools/blenvy/blueprints/blueprint_helpers.py | 98 +++++++++++ .../blenvy/blueprints/blueprints_registry.py | 2 - .../blueprints_scan.py} | 162 +----------------- tools/blenvy/blueprints/ui.py | 11 +- tools/blenvy/core/blenvy_manager.py | 34 +++- .../helpers => core}/object_makers.py | 25 ++- tools/blenvy/core/path_helpers.py | 11 ++ .../helpers => core}/ping_depsgraph_update.py | 0 tools/blenvy/core/scene_helpers.py | 27 +++ tools/blenvy/core/ui.py | 29 ++++ .../auto_export/auto_export.py | 34 ++-- .../auto_export/export_blueprints.py | 3 +- .../auto_export/export_main_scenes.py | 2 +- .../auto_export/get_blueprints_to_export.py | 2 +- .../auto_export/get_levels_to_export.py | 2 +- .../helpers/helpers_scenes.py | 11 +- .../modules/bevy_scene_components.py | 2 +- .../modules/export_materials.py | 11 +- tools/blenvy/gltf_auto_export/ui/main.py | 21 --- tools/blenvy/gltf_auto_export/ui/operators.py | 10 +- tools/gltf_auto_export/TODO.md | 4 - .../helpers/helpers_blueprints.py | 4 +- 29 files changed, 357 insertions(+), 293 deletions(-) create mode 100644 tools/blenvy/assets/asset_helpers.py delete mode 100644 tools/blenvy/bevy_components/helpers.py create mode 100644 tools/blenvy/blueprints/blueprint.py create mode 100644 tools/blenvy/blueprints/blueprint_helpers.py rename tools/blenvy/{gltf_auto_export/helpers/helpers_blueprints.py => blueprints/blueprints_scan.py} (64%) rename tools/blenvy/{gltf_auto_export/helpers => core}/object_makers.py (68%) create mode 100644 tools/blenvy/core/path_helpers.py rename tools/blenvy/{gltf_auto_export/helpers => core}/ping_depsgraph_update.py (100%) create mode 100644 tools/blenvy/core/scene_helpers.py diff --git a/tools/blenvy/TODO.md b/tools/blenvy/TODO.md index 0aac70d..8113f8c 100644 --- a/tools/blenvy/TODO.md +++ b/tools/blenvy/TODO.md @@ -1,11 +1,44 @@ Auto export - - [ ] the original blueprints & levels path are now left as is, and there is an auto injection of xxxpath_full for absolute paths - - [ ] replace all uses of the paths with the correct ones above + - [x] the original blueprints & levels path are now left as is, and there is an auto injection of xxxpath_full for absolute paths + - [x] replace all uses of the paths with the correct ones above - [x] levels - [x] blueprints - - [ ] materials + - [x] materials - [x] move out the UI for "assets" folder out of "blueprints condition" - [ ] fix asset path calculations - root path => relative to blend file path - asset path => relative to root path - blueprints/levels/blueprints path => relative to assets path + + +- move out some parameters from auto export to a higher level (as they are now used in multiple places) + - [ ] main/ library scene names + - [ ] paths + +Data storage: + - for scenes (main scenes) + - at scene level + - for blueprints + - at collection level + - Note: these should be COPIED to the scene level when exporting, into the temp_scene's properties + + > NOTE: UP until we manage to create a PR for Bevy to directly support the scene level gltf_extras, the auto exporter should automatically create (& remove) + an additional object with scene__components to copy that data to + +Assets: + - blueprint assets should be auto_generated & inserted into the list of assets : these assets are NOT removable by the user + - should not change the list of manually added assets + - [x] store assets + - [x] per main scene for level/world assets + - [x] per blueprint for blueprint in lib scene + - [ ] UI: + - [x] we need to display all direct assets (stored in the scene) + - [ ] indirect assets: + - [ ] the assets of local blueprints + + +Blueprints: + - [x] on save: write IN THE COLLECTION PROPERTIES + - list of assets + - export path + - [ ] blueprint selection for nested blueprints is broken \ No newline at end of file diff --git a/tools/blenvy/__init__.py b/tools/blenvy/__init__.py index fa0c716..093122e 100644 --- a/tools/blenvy/__init__.py +++ b/tools/blenvy/__init__.py @@ -33,7 +33,6 @@ from .bevy_components.components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel) from .gltf_auto_export import gltf_post_export_callback from .gltf_auto_export.auto_export.operators import AutoExportGLTF from .gltf_auto_export.auto_export.tracker import AutoExportTracker -from .gltf_auto_export.auto_export.preferences import (AutoExportGltfAddonPreferences) from .gltf_auto_export.auto_export.internals import (SceneLink, SceneLinks, @@ -41,7 +40,7 @@ from .gltf_auto_export.auto_export.internals import (SceneLink, BlueprintsToExport, CUSTOM_PG_sceneName ) -from .gltf_auto_export.ui.main import (GLTF_PT_auto_export_change_detection, GLTF_PT_auto_export_changes_list, GLTF_PT_auto_export_main, +from .gltf_auto_export.ui.main import (GLTF_PT_auto_export_change_detection, GLTF_PT_auto_export_main, GLTF_PT_auto_export_root, GLTF_PT_auto_export_general, GLTF_PT_auto_export_scenes, @@ -53,7 +52,7 @@ from .gltf_auto_export.ui.main import (GLTF_PT_auto_export_change_detection, GLT from .gltf_auto_export.ui.operators import (OT_OpenFolderbrowser, SCENES_LIST_OT_actions) # asset management -from .assets.ui import GLTF_PT_auto_export_assets +from .assets.ui import Blenvy_assets from .assets.assets_registry import AssetsRegistry from .assets.operators import OT_Add_asset_filebrowser, OT_add_bevy_asset, OT_remove_bevy_asset @@ -151,7 +150,7 @@ classes = [ OT_add_bevy_asset, OT_remove_bevy_asset, OT_Add_asset_filebrowser, - GLTF_PT_auto_export_assets, + Blenvy_assets, BlueprintsRegistry, OT_select_blueprint, diff --git a/tools/blenvy/assets/asset_helpers.py b/tools/blenvy/assets/asset_helpers.py new file mode 100644 index 0000000..157d8b9 --- /dev/null +++ b/tools/blenvy/assets/asset_helpers.py @@ -0,0 +1,5 @@ +import json + +def get_assets(scene_or_collection): + assets = json.loads(scene_or_collection.get('assets')) if 'assets' in scene_or_collection else [] + return assets diff --git a/tools/blenvy/assets/operators.py b/tools/blenvy/assets/operators.py index bbe5052..8188254 100644 --- a/tools/blenvy/assets/operators.py +++ b/tools/blenvy/assets/operators.py @@ -4,6 +4,7 @@ import bpy from bpy_types import (Operator) from bpy.props import (BoolProperty, StringProperty, EnumProperty) +from ..core.path_helpers import absolute_path_from_blend_file from ..settings import load_settings class OT_add_bevy_asset(Operator): @@ -148,9 +149,10 @@ class OT_Add_asset_filebrowser(Operator, ImportHelper): export_assets_path = current_auto_settings.get("export_assets_path", "assets") # FIXME: not sure print("export_root_path", export_root_path, "export_assets_path", export_assets_path) - export_assets_path_absolute = os.path.join(export_root_path, export_assets_path) - asset_path = os.path.relpath(self.filepath, export_assets_path_absolute) + export_assets_path_absolute = absolute_path_from_blend_file(os.path.join(export_root_path, export_assets_path)) + asset_path = os.path.relpath(self.filepath, export_assets_path_absolute) + print("asset path", asset_path) assets_registry = context.window_manager.assets_registry assets_registry.asset_path_selector = asset_path diff --git a/tools/blenvy/assets/ui.py b/tools/blenvy/assets/ui.py index 6550016..eb1b705 100644 --- a/tools/blenvy/assets/ui.py +++ b/tools/blenvy/assets/ui.py @@ -1,31 +1,32 @@ import bpy -import json +from .asset_helpers import get_assets -def draw_assets(layout, name, title, asset_registry, assets, target_type, target_name): +def draw_assets(layout, name, title, asset_registry, assets, target_type, target_name, editable=True): header, panel = layout.box().panel(f"assets{name}", default_closed=False) header.label(text=title) if panel: - row = panel.row() - row.prop(asset_registry, "asset_name_selector", text="") - row.prop(asset_registry, "asset_type_selector", text="") - asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER") - - if asset_registry.asset_type_selector == 'IMAGE': - asset_selector.filter_glob = '*.jpg;*.jpeg;*.png;*.bmp' - if asset_registry.asset_type_selector == 'MODEL': - asset_selector.filter_glob="*.glb;*.gltf" - if asset_registry.asset_type_selector == 'TEXT': - asset_selector.filter_glob="*.txt;*.md;*.ron;*.json" - if asset_registry.asset_type_selector == 'AUDIO': - asset_selector.filter_glob="*.mp3;*.wav;*.flac" + if editable: + row = panel.row() + row.prop(asset_registry, "asset_name_selector", text="") + row.prop(asset_registry, "asset_type_selector", text="") + asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER") + + if asset_registry.asset_type_selector == 'IMAGE': + asset_selector.filter_glob = '*.jpg;*.jpeg;*.png;*.bmp' + if asset_registry.asset_type_selector == 'MODEL': + asset_selector.filter_glob="*.glb;*.gltf" + if asset_registry.asset_type_selector == 'TEXT': + asset_selector.filter_glob="*.txt;*.md;*.ron;*.json" + if asset_registry.asset_type_selector == 'AUDIO': + asset_selector.filter_glob="*.mp3;*.wav;*.flac" - add_asset = row.operator(operator="bevyassets.add", text="", icon="ADD") - add_asset.target_type = target_type - add_asset.target_name = target_name - add_asset.asset_name = asset_registry.asset_name_selector - add_asset.asset_type = asset_registry.asset_type_selector - add_asset.asset_path = asset_registry.asset_path_selector + add_asset = row.operator(operator="bevyassets.add", text="", icon="ADD") + add_asset.target_type = target_type + add_asset.target_name = target_name + add_asset.asset_name = asset_registry.asset_name_selector + add_asset.asset_type = asset_registry.asset_type_selector + add_asset.asset_path = asset_registry.asset_path_selector #assets = json.loads(blueprint.collection["assets"]) if "assets" in blueprint.collection else [] for asset in assets: @@ -33,7 +34,7 @@ def draw_assets(layout, name, title, asset_registry, assets, target_type, target row.label(text=asset["name"]) row.label(text=asset["type"]) row.label(text=asset["path"]) - if not asset["internal"]: + if not asset["internal"] and editable: remove_asset = row.operator(operator="bevyassets.remove", text="", icon="TRASH") remove_asset.target_type = target_type remove_asset.target_name = target_name @@ -41,7 +42,7 @@ def draw_assets(layout, name, title, asset_registry, assets, target_type, target else: row.label(text="") -class GLTF_PT_auto_export_assets(bpy.types.Panel): +class Blenvy_assets(bpy.types.Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_label = "" @@ -74,6 +75,6 @@ class GLTF_PT_auto_export_assets(bpy.types.Panel): if panel: for scene in bpy.data.scenes: if scene.name != "Library": # FIXME: hack for testing - assets = json.loads(scene.get('assets')) if 'assets' in scene else [] + direct_assets = get_assets(scene) row = panel.row() - draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, assets=assets, target_type="SCENE", target_name=scene.name) + draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, assets=direct_assets, target_type="SCENE", target_name=scene.name) diff --git a/tools/blenvy/bevy_components/helpers.py b/tools/blenvy/bevy_components/helpers.py deleted file mode 100644 index f4cd411..0000000 --- a/tools/blenvy/bevy_components/helpers.py +++ /dev/null @@ -1,19 +0,0 @@ -import bpy -import json - -# Makes an empty, at the specified location, rotation, scale stores it in existing collection, from https://blender.stackexchange.com/questions/51290/how-to-add-empty-object-not-using-bpy-ops -def make_empty(name, location, rotation, scale, collection): - object_data = None - empty_obj = bpy.data.objects.new( name, object_data ) - - empty_obj.empty_display_size = 2 - empty_obj.empty_display_type = 'PLAIN_AXES' - - empty_obj.name = name - empty_obj.location = location - empty_obj.scale = scale - empty_obj.rotation_euler = rotation - - collection.objects.link( empty_obj ) - #bpy.context.view_layer.update() - return empty_obj diff --git a/tools/blenvy/blueprints/blueprint.py b/tools/blenvy/blueprints/blueprint.py new file mode 100644 index 0000000..98462c6 --- /dev/null +++ b/tools/blenvy/blueprints/blueprint.py @@ -0,0 +1,18 @@ +class Blueprint: + def __init__(self, name): + self.name = name + self.local = True + self.marked = False # If marked as asset or with auto_export flag, always export if changed + self.scene = None # Not sure, could be usefull for tracking + + self.instances = [] + self.objects = [] + self.nested_blueprints = [] + + self.collection = None # should we just sublclass ? + + def __repr__(self): + return f'Name: {self.name} Local: {self.local}, Scene: {self.scene}, Instances: {self.instances}, Objects: {self.objects}, nested_blueprints: {self.nested_blueprints}' + + def __str__(self): + return f'Name: "{self.name}", Local: {self.local}, Scene: {self.scene}, Instances: {self.instances}, Objects: {self.objects}, nested_blueprints: {self.nested_blueprints}' diff --git a/tools/blenvy/blueprints/blueprint_helpers.py b/tools/blenvy/blueprints/blueprint_helpers.py new file mode 100644 index 0000000..26bc51a --- /dev/null +++ b/tools/blenvy/blueprints/blueprint_helpers.py @@ -0,0 +1,98 @@ + +import os +import json +import bpy +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: + gltf_output_path = os.path.join(folder_path, blueprint.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_blueprints.append(blueprint) + return not_found_blueprints + +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, export_blueprints_path, gltf_extension): + for blueprint in internal_blueprints: + blueprint_exported_path = os.path.join(export_blueprints_path, f"{blueprint.name}{gltf_extension}") + blueprint.collection["export_path"] = blueprint_exported_path + +def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs): + export_root_path = getattr(addon_prefs, "export_root_path") + export_assets_path = getattr(addon_prefs,"export_assets_path") + export_levels_path = getattr(addon_prefs,"export_levels_path") + export_blueprints_path = getattr(addon_prefs, "export_blueprints_path") + export_gltf_extension = getattr(addon_prefs, "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_main_scene.get(scene.name, None) + # find all blueprints used in a scene + blueprints_in_scene = [] + if blueprint_instance_names_for_scene: # what are the blueprints used in this scene, inject those into the assets list component + children_per_blueprint = {} + for blueprint_name in blueprint_instance_names_for_scene: + blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None) + if blueprint: + children_per_blueprint[blueprint_name] = blueprint.nested_blueprints + blueprints_in_scene += blueprint.nested_blueprints + assets_list_data["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})" + print(blueprint_instance_names_for_scene) + # add_scene_property(scene, assets_list_name, assets_list_data) + + 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 = os.path.join(export_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}) + + + # fetch images/textures + # see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image + textures = [] + for ob in bpy.data.objects: + if ob.type == "MESH": + for mat_slot in ob.material_slots: + if mat_slot.material: + if mat_slot.material.node_tree: + textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE']) + print("textures", textures) + + assets_list_name = f"assets_{scene.name}" + assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]} + scene["assets"] = json.dumps(blueprint_assets_list) + + print("blueprint assets", blueprint_assets_list) + add_scene_property(scene, assets_list_name, assets_list_data) + for blueprint in blueprint_assets_list: + bpy.context.window_manager.assets_registry.add_asset(**blueprint) + +def remove_blueprints_list_from_main_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) diff --git a/tools/blenvy/blueprints/blueprints_registry.py b/tools/blenvy/blueprints/blueprints_registry.py index f042ed0..2fb423d 100644 --- a/tools/blenvy/blueprints/blueprints_registry.py +++ b/tools/blenvy/blueprints/blueprints_registry.py @@ -6,9 +6,7 @@ from pathlib import Path from bpy_types import (PropertyGroup) from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty) - # this is where we store the information for all available Blueprints -# class BlueprintsRegistry(PropertyGroup): blueprints_data = {} blueprints_list = [] diff --git a/tools/blenvy/gltf_auto_export/helpers/helpers_blueprints.py b/tools/blenvy/blueprints/blueprints_scan.py similarity index 64% rename from tools/blenvy/gltf_auto_export/helpers/helpers_blueprints.py rename to tools/blenvy/blueprints/blueprints_scan.py index e7ea4e2..5ddd0d3 100644 --- a/tools/blenvy/gltf_auto_export/helpers/helpers_blueprints.py +++ b/tools/blenvy/blueprints/blueprints_scan.py @@ -1,43 +1,6 @@ - -import os from types import SimpleNamespace import bpy - -class Blueprint: - def __init__(self, name): - self.name = name - self.local = True - self.marked = False # If marked as asset or with auto_export flag, always export if changed - self.scene = None # Not sure, could be usefull for tracking - - self.instances = [] - self.objects = [] - self.nested_blueprints = [] - - self.collection = None # should we just sublclass ? - - def __repr__(self): - return f'Name: {self.name} Local: {self.local}, Scene: {self.scene}, Instances: {self.instances}, Objects: {self.objects}, nested_blueprints: {self.nested_blueprints}' - - def __str__(self): - return f'Name: "{self.name}", Local: {self.local}, Scene: {self.scene}, Instances: {self.instances}, Objects: {self.objects}, nested_blueprints: {self.nested_blueprints}' - - -def find_blueprints_not_on_disk(blueprints, folder_path, extension): - not_found_blueprints = [] - for blueprint in blueprints: - gltf_output_path = os.path.join(folder_path, blueprint.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_blueprints.append(blueprint) - return not_found_blueprints - -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 +from .blueprint import Blueprint # blueprints: any collection with either # - an instance @@ -276,126 +239,3 @@ def blueprints_scan(main_scenes, library_scenes, addon_prefs): } return SimpleNamespace(**data) - - -import json -from .object_makers import (make_empty) - - -def add_scene_property(scene, property_name, property_data): - root_collection = scene.collection - scene_property = None - for object in scene.objects: - if object.name == property_name: - scene_property = object - break - - if scene_property is None: - scene_property = make_empty(property_name, [0,0,0], [0,0,0], [0,0,0], root_collection) - - for key in property_data.keys(): - scene_property[key] = property_data[key] - - -def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs): - export_root_path = getattr(addon_prefs, "export_root_path") - export_assets_path = getattr(addon_prefs,"export_assets_path") - export_levels_path = getattr(addon_prefs,"export_levels_path") - export_blueprints_path = getattr(addon_prefs, "export_blueprints_path") - export_gltf_extension = getattr(addon_prefs, "export_gltf_extension") - - # print("injecting assets/blueprints data into scene") - assets_list_name = f"assets_list_{scene.name}_components" - assets_list_data = {} - - - # FIXME: temporary hack - for blueprint in blueprints_data.blueprints: - bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint) - - blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None) - # find all blueprints used in a scene - blueprints_in_scene = [] - if blueprint_instance_names_for_scene: # what are the blueprints used in this scene, inject those into the assets list component - children_per_blueprint = {} - for blueprint_name in blueprint_instance_names_for_scene: - blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None) - if blueprint: - children_per_blueprint[blueprint_name] = blueprint.nested_blueprints - blueprints_in_scene += blueprint.nested_blueprints - assets_list_data["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})" - print(blueprint_instance_names_for_scene) - add_scene_property(scene, assets_list_name, assets_list_data) - - - blueprints_path_full = os.path.join(export_assets_path, export_blueprints_path) - relative_blueprints_path = os.path.relpath(export_blueprints_path, export_root_path) - - 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 = os.path.join(export_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}) - - - # fetch images/textures - # see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image - textures = [] - for ob in bpy.data.objects: - if ob.type == "MESH": - for mat_slot in ob.material_slots: - if mat_slot.material: - if mat_slot.material.node_tree: - textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE']) - print("textures", textures) - - assets_list_name = f"assets_{scene.name}" - assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]} - scene["assets"] = json.dumps(blueprint_assets_list) - - print("blueprint assets", blueprint_assets_list) - add_scene_property(scene, assets_list_name, assets_list_data) - for blueprint in blueprint_assets_list: - bpy.context.window_manager.assets_registry.add_asset(**blueprint) - - - '''root_collection = scene.collection - - assets_list = None - for object in scene.objects: - if object.name == assets_list_name: - assets_list = object - break - - if assets_list is None: - assets_list = make_empty(assets_list_name, [0,0,0], [0,0,0], [0,0,0], root_collection) - - blueprint_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None) - # find all blueprints used in a scene - if blueprint_names_for_scene: # what are the blueprints used in this scene, inject those into the assets list component - children_per_blueprint = {} - for blueprint_name in blueprint_names_for_scene: - blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None) - if blueprint: - children_per_blueprint[blueprint_name] = blueprint.nested_blueprints - assets_list["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})"''' - -def remove_blueprints_list_from_main_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) diff --git a/tools/blenvy/blueprints/ui.py b/tools/blenvy/blueprints/ui.py index 30cf58b..57082c1 100644 --- a/tools/blenvy/blueprints/ui.py +++ b/tools/blenvy/blueprints/ui.py @@ -26,8 +26,11 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel): row.label(text=blueprint.name) if blueprint.local: + select_blueprint = row.operator(operator="blueprint.select", text="", icon="RESTRICT_SELECT_OFF") - select_blueprint.blueprint_collection_name = blueprint.collection.name + + if blueprint.collection and blueprint.collection.name: + select_blueprint.blueprint_collection_name = blueprint.collection.name select_blueprint.blueprint_scene_name = blueprint.scene.name assets = json.loads(blueprint.collection["assets"]) if "assets" in blueprint.collection else [] @@ -35,8 +38,6 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel): draw_assets(layout=layout, name=blueprint.name, title="Assets", asset_registry=asset_registry, assets=assets, target_type="BLUEPRINT", target_name=blueprint.name) else: + assets = json.loads(blueprint.collection["assets"]) if "assets" in blueprint.collection else [] + draw_assets(layout=layout, name=blueprint.name, title="Assets", asset_registry=asset_registry, assets=assets, target_type="BLUEPRINT", target_name=blueprint.name, editable=False) row.label(text="External") - - for collection in bpy.context.window_manager.exportedCollections: - row = layout.row() - row.label(text=collection.name) \ No newline at end of file diff --git a/tools/blenvy/core/blenvy_manager.py b/tools/blenvy/core/blenvy_manager.py index 91ab24e..58c4562 100644 --- a/tools/blenvy/core/blenvy_manager.py +++ b/tools/blenvy/core/blenvy_manager.py @@ -1,6 +1,6 @@ import bpy from bpy_types import (PropertyGroup) -from bpy.props import (EnumProperty, PointerProperty) +from bpy.props import (EnumProperty, PointerProperty, StringProperty) class BlenvyManager(PropertyGroup): @@ -14,6 +14,38 @@ class BlenvyManager(PropertyGroup): ('TOOLS', "Tools", ""), ) ) # type: ignore + + + export_root_path: StringProperty( + name = "Project Root Path", + description="The root folder of your (Bevy) project (not assets!)", + default='../' + ) # type: ignore + + export_assets_path: StringProperty( + name='Export folder', + description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ', + default='./assets', + options={'HIDDEN'} + ) # type: ignore + + export_blueprints_path: StringProperty( + name='Blueprints path', + description='path to export the blueprints to (relative to the assets folder)', + default='blueprints', + ) # type: ignore + + export_levels_path: StringProperty( + name='Levels path', + description='path to export the levels (main scenes) to (relative to the assets folder)', + default='levels', + ) # type: ignore + + export_materials_path: StringProperty( + name='Materials path', + description='path to export the materials libraries to (relative to the assets folder)', + default='materials', + ) # type: ignore @classmethod def register(cls): diff --git a/tools/blenvy/gltf_auto_export/helpers/object_makers.py b/tools/blenvy/core/object_makers.py similarity index 68% rename from tools/blenvy/gltf_auto_export/helpers/object_makers.py rename to tools/blenvy/core/object_makers.py index 50827b5..54ff1a1 100644 --- a/tools/blenvy/gltf_auto_export/helpers/object_makers.py +++ b/tools/blenvy/core/object_makers.py @@ -44,4 +44,27 @@ def make_cube(name, location=[0,0,0], rotation=[0,0,0], scale=[1,1,1], collectio if collection != None: collection.objects.link( new_object ) - return new_object \ No newline at end of file + return new_object + + + +"""import bpy +import json + +# Makes an empty, at the specified location, rotation, scale stores it in existing collection, from https://blender.stackexchange.com/questions/51290/how-to-add-empty-object-not-using-bpy-ops +def make_empty(name, location, rotation, scale, collection): + object_data = None + empty_obj = bpy.data.objects.new( name, object_data ) + + empty_obj.empty_display_size = 2 + empty_obj.empty_display_type = 'PLAIN_AXES' + + empty_obj.name = name + empty_obj.location = location + empty_obj.scale = scale + empty_obj.rotation_euler = rotation + + collection.objects.link( empty_obj ) + #bpy.context.view_layer.update() + return empty_obj +""" \ No newline at end of file diff --git a/tools/blenvy/core/path_helpers.py b/tools/blenvy/core/path_helpers.py new file mode 100644 index 0000000..ea2fb89 --- /dev/null +++ b/tools/blenvy/core/path_helpers.py @@ -0,0 +1,11 @@ +import bpy +import os + +def absolute_path_from_blend_file(path): + # path to the current blend file + blend_file_path = bpy.data.filepath + # Get the folder + blend_file_folder_path = os.path.dirname(blend_file_path) + + # absolute path + return os.path.join(blend_file_folder_path, path) diff --git a/tools/blenvy/gltf_auto_export/helpers/ping_depsgraph_update.py b/tools/blenvy/core/ping_depsgraph_update.py similarity index 100% rename from tools/blenvy/gltf_auto_export/helpers/ping_depsgraph_update.py rename to tools/blenvy/core/ping_depsgraph_update.py diff --git a/tools/blenvy/core/scene_helpers.py b/tools/blenvy/core/scene_helpers.py new file mode 100644 index 0000000..360b2f6 --- /dev/null +++ b/tools/blenvy/core/scene_helpers.py @@ -0,0 +1,27 @@ +def add_scene_property(scene, scene_component_name, property_data, limit_to=None): + root_collection = scene.collection + scene_property = None + for object in scene.objects: + if object.name == scene_component_name: + scene_property = object + break + + if scene_property is None: + scene_property = make_empty(scene_component_name, [0,0,0], [0,0,0], [0,0,0], root_collection) + + for key in property_data.keys(): + if limit_to is not None: + if key in limit_to: + scene_property[key] = property_data[key] + else: + scene_property[key] = property_data[key] + + +# compatibility helper until we land gltf_extras at the scene level for Bevy +# it copies a custom property into an __components object's properties +def copy_scene_or_collection_property_to_object_component(scene, property_name, target_object_name): + property_value = scene.get(property_name, None) + if property_value is not None: + property_data = {} + property_data[property_name] = property_value + add_scene_property(scene=scene, scene_component_name=target_object_name, property_data=property_data) \ No newline at end of file diff --git a/tools/blenvy/core/ui.py b/tools/blenvy/core/ui.py index 26a573d..bd6d5b2 100644 --- a/tools/blenvy/core/ui.py +++ b/tools/blenvy/core/ui.py @@ -3,6 +3,20 @@ from ..settings import load_settings ###################################################### ## ui logic & co +def draw_folder_browser(layout, label, prop_origin, target_property): + row = layout.row() + row.label(text=label) + + '''box = row.box() + box.scale_y = 0.5 + box.label(text=value)''' + + col = row.column() + col.enabled = False + col.prop(prop_origin, target_property, text="") + + folder_selector = row.operator("generic.open_folderbrowser", icon="FILE_FOLDER", text="") + folder_selector.target_property = target_property #"export_root_path" # side panel class BLENVY_PT_SidePanel(bpy.types.Panel): @@ -66,6 +80,21 @@ class BLENVY_PT_SidePanel(bpy.types.Panel): layout.label(text="Library scene active: "+ str(library_scene_active)) layout.label(text=blenvy.mode)""" + + if blenvy.mode == "SETTINGS": + header, panel = layout.panel("auto_export", default_closed=False) + header.label(text="Common") + if panel: + row = panel.row() + draw_folder_browser(layout=row, label="Root Folder", prop_origin=blenvy, target_property="export_root_path") + row = panel.row() + draw_folder_browser(layout=row, label="Assets Folder", prop_origin=blenvy, target_property="export_assets_path") + row = panel.row() + draw_folder_browser(layout=row, label="Blueprints Folder", prop_origin=blenvy, target_property="export_blueprints_path") + row = panel.row() + draw_folder_browser(layout=row, label="Levels Folder", prop_origin=blenvy, target_property="export_levels_path") + row = panel.row() + draw_folder_browser(layout=row, label="Materials Folder", prop_origin=blenvy, target_property="export_materials_path") """if blenvy.mode == "SETTINGS": header, panel = layout.panel("auto_export", default_closed=False) header.label(text="Auto Export") diff --git a/tools/blenvy/gltf_auto_export/auto_export/auto_export.py b/tools/blenvy/gltf_auto_export/auto_export/auto_export.py index ba4efa2..0c25a54 100644 --- a/tools/blenvy/gltf_auto_export/auto_export/auto_export.py +++ b/tools/blenvy/gltf_auto_export/auto_export/auto_export.py @@ -1,12 +1,9 @@ -import copy -import json + import os -from types import SimpleNamespace import bpy import traceback - -from .preferences import AutoExportGltfAddonPreferences +from ..helpers.helpers_scenes import (get_scenes, ) from .get_blueprints_to_export import get_blueprints_to_export from .get_levels_to_export import get_levels_to_export @@ -14,13 +11,12 @@ from .get_standard_exporter_settings import get_standard_exporter_settings from .export_main_scenes import export_main_scene from .export_blueprints import export_blueprints - -from ..helpers.helpers_scenes import (get_scenes, ) -from ..helpers.helpers_blueprints import blueprints_scan - from ..modules.export_materials import cleanup_materials, export_materials from ..modules.bevy_scene_components import remove_scene_components, upsert_scene_components +from ...blueprints.blueprints_scan import blueprints_scan +from ...blueprints.blueprint_helpers import inject_export_path_into_internal_blueprints + """this is the main 'central' function for all auto export """ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs): @@ -68,19 +64,23 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs): addon_prefs.export_assets_path_full = os.path.join(blend_file_path, export_root_path, export_assets_path) addon_prefs.export_blueprints_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_blueprints_path")) addon_prefs.export_levels_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_levels_path")) - addon_prefs.export_materials_path = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_materials_path")) + addon_prefs.export_materials_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_materials_path")) addon_prefs.export_gltf_extension = gltf_extension [main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs) - print("main scenes", main_scene_names, "library_scenes", library_scene_names) - print("export_assets_path", export_assets_path) - blueprints_data = blueprints_scan(level_scenes, library_scenes, addon_prefs) blueprints_per_scene = blueprints_data.blueprints_per_scenes internal_blueprints = [blueprint.name for blueprint in blueprints_data.internal_blueprints] external_blueprints = [blueprint.name for blueprint in blueprints_data.external_blueprints] + + # we inject the blueprints export path + export_blueprints_path = getattr(addon_prefs,"export_blueprints_path") + inject_export_path_into_internal_blueprints(internal_blueprints=blueprints_data.internal_blueprints, export_blueprints_path=export_blueprints_path, gltf_extension=gltf_extension) + for blueprint in blueprints_data.blueprints: + bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint) + if export_scene_settings: # inject/ update scene components upsert_scene_components(level_scenes) @@ -101,7 +101,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs): # since materials export adds components we need to call this before blueprints are exported # export materials & inject materials components into relevant objects if export_materials_library: - export_materials(blueprints_data.blueprint_names, library_scenes, blend_file_path, addon_prefs) + export_materials(blueprints_data.blueprint_names, library_scenes, addon_prefs) # update the list of tracked exports exports_total = len(blueprints_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0) @@ -139,11 +139,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs): do_export_library_scene = not export_change_detection or changed_export_parameters or len(blueprints_to_export) > 0 if do_export_library_scene: print("export LIBRARY") - # we only want to go through the library scenes where our blueprints to export are present - """for (scene_name, blueprints_to_export) in blueprints_per_scene.items(): - print(" exporting blueprints from scene:", scene_name) - print(" blueprints to export", blueprints_to_export)""" - export_blueprints(blueprints_to_export, blend_file_path, addon_prefs, blueprints_data) + export_blueprints(blueprints_to_export, addon_prefs, blueprints_data) # reset current scene from backup bpy.context.window.scene = old_current_scene diff --git a/tools/blenvy/gltf_auto_export/auto_export/export_blueprints.py b/tools/blenvy/gltf_auto_export/auto_export/export_blueprints.py index df0ffdf..41e167e 100644 --- a/tools/blenvy/gltf_auto_export/auto_export/export_blueprints.py +++ b/tools/blenvy/gltf_auto_export/auto_export/export_blueprints.py @@ -7,7 +7,7 @@ from .export_gltf import (generate_gltf_export_preferences) from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into -def export_blueprints(blueprints, blend_file_path, addon_prefs, blueprints_data): +def export_blueprints(blueprints, addon_prefs, blueprints_data): export_blueprints_path_full = getattr(addon_prefs,"export_blueprints_path_full") gltf_export_preferences = generate_gltf_export_preferences(addon_prefs) @@ -26,6 +26,7 @@ def export_blueprints(blueprints, blend_file_path, addon_prefs, blueprints_data) export_settings['export_materials'] = 'PLACEHOLDER' collection = bpy.data.collections[blueprint.name] + # do the actual export generate_and_export( addon_prefs, temp_scene_name=TEMPSCENE_PREFIX+collection.name, diff --git a/tools/blenvy/gltf_auto_export/auto_export/export_main_scenes.py b/tools/blenvy/gltf_auto_export/auto_export/export_main_scenes.py index 913c6e3..2da7fb2 100644 --- a/tools/blenvy/gltf_auto_export/auto_export/export_main_scenes.py +++ b/tools/blenvy/gltf_auto_export/auto_export/export_main_scenes.py @@ -7,7 +7,7 @@ from ..helpers.generate_and_export import generate_and_export from .export_gltf import (generate_gltf_export_preferences, export_gltf) from ..modules.bevy_dynamic import is_object_dynamic, is_object_static from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into -from ..helpers.helpers_blueprints import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene +from ...blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data): gltf_export_preferences = generate_gltf_export_preferences(addon_prefs) diff --git a/tools/blenvy/gltf_auto_export/auto_export/get_blueprints_to_export.py b/tools/blenvy/gltf_auto_export/auto_export/get_blueprints_to_export.py index 68969db..2e5a900 100644 --- a/tools/blenvy/gltf_auto_export/auto_export/get_blueprints_to_export.py +++ b/tools/blenvy/gltf_auto_export/auto_export/get_blueprints_to_export.py @@ -1,7 +1,7 @@ import bpy import os from ..helpers.helpers_scenes import (get_scenes, ) -from ..helpers.helpers_blueprints import find_blueprints_not_on_disk +from ...blueprints.blueprint_helpers import find_blueprints_not_on_disk # TODO: this should also take the split/embed mode into account: if a nested collection changes AND embed is active, its container collection should also be exported def get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs): diff --git a/tools/blenvy/gltf_auto_export/auto_export/get_levels_to_export.py b/tools/blenvy/gltf_auto_export/auto_export/get_levels_to_export.py index 0894f31..4a50342 100644 --- a/tools/blenvy/gltf_auto_export/auto_export/get_levels_to_export.py +++ b/tools/blenvy/gltf_auto_export/auto_export/get_levels_to_export.py @@ -1,5 +1,5 @@ import bpy -from ..helpers.helpers_blueprints import check_if_blueprint_on_disk +from ...blueprints.blueprint_helpers import check_if_blueprint_on_disk from ..helpers.helpers_scenes import (get_scenes, ) # IF collection_instances_combine_mode is not 'split' check for each scene if any object in changes_per_scene has an instance in the scene diff --git a/tools/blenvy/gltf_auto_export/helpers/helpers_scenes.py b/tools/blenvy/gltf_auto_export/helpers/helpers_scenes.py index 850630a..75c137d 100644 --- a/tools/blenvy/gltf_auto_export/helpers/helpers_scenes.py +++ b/tools/blenvy/gltf_auto_export/helpers/helpers_scenes.py @@ -1,12 +1,12 @@ import json import bpy -from .object_makers import (make_empty) +from ...core.object_makers import (make_empty) # these are mostly for when using this add-on together with the bevy_components add-on custom_properties_to_filter_out = ['_combine', 'template', 'components_meta'] -def is_component_valid(object, component_name): +def is_component_valid_and_enabled(object, component_name): if "components_meta" in object or hasattr(object, "components_meta"): target_components_metadata = object.components_meta.components component_meta = next(filter(lambda component: component["long_name"] == component_name, target_components_metadata), None) @@ -18,7 +18,7 @@ def remove_unwanted_custom_properties(object): to_remove = [] component_names = list(object.keys()) # to avoid 'IDPropertyGroup changed size during iteration' issues for component_name in component_names: - if not is_component_valid(object, component_name): + if not is_component_valid_and_enabled(object, component_name): to_remove.append(component_name) for cp in custom_properties_to_filter_out + to_remove: if cp in object: @@ -118,7 +118,7 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep # we copy custom properties over from our original object to our empty for component_name, component_value in object.items(): - if component_name not in custom_properties_to_filter_out and is_component_valid(object, component_name): #copy only valid properties + if component_name not in custom_properties_to_filter_out and is_component_valid_and_enabled(object, component_name): #copy only valid properties empty_obj[component_name] = component_value copy = empty_obj else: @@ -174,9 +174,6 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par blueprints_data = blueprints_data, addon_prefs=addon_prefs ) - - - return {} # clear & remove "hollow scene" diff --git a/tools/blenvy/gltf_auto_export/modules/bevy_scene_components.py b/tools/blenvy/gltf_auto_export/modules/bevy_scene_components.py index b6f384f..b945101 100644 --- a/tools/blenvy/gltf_auto_export/modules/bevy_scene_components.py +++ b/tools/blenvy/gltf_auto_export/modules/bevy_scene_components.py @@ -1,6 +1,6 @@ import bpy -from ..helpers.object_makers import make_empty +from ...core.object_makers import make_empty # TODO: replace this with placing scene level custom properties once support for that has been added to bevy_gltf def upsert_scene_components(main_scenes): diff --git a/tools/blenvy/gltf_auto_export/modules/export_materials.py b/tools/blenvy/gltf_auto_export/modules/export_materials.py index 4716875..429b9d5 100644 --- a/tools/blenvy/gltf_auto_export/modules/export_materials.py +++ b/tools/blenvy/gltf_auto_export/modules/export_materials.py @@ -3,10 +3,9 @@ import bpy from pathlib import Path from ..helpers.generate_and_export import generate_and_export - from ..helpers.helpers_collections import (traverse_tree) from ..auto_export.export_gltf import (export_gltf, generate_gltf_export_preferences) -from ..helpers.object_makers import make_cube +from ...core.object_makers import make_cube # get materials per object, and injects the materialInfo component def get_materials(object): @@ -90,11 +89,9 @@ def clear_materials_scene(temp_scene): # exports the materials used inside the current project: # the name of the output path is /_materials_library.gltf/glb -def export_materials(collections, library_scenes, folder_path, addon_prefs): +def export_materials(collections, library_scenes, addon_prefs): gltf_export_preferences = generate_gltf_export_preferences(addon_prefs) - export_materials_path = getattr(addon_prefs,"export_materials_path") - export_root_path = getattr(addon_prefs, "export_root_path") - + export_materials_path_full = getattr(addon_prefs,"export_materials_path_full") used_material_names = get_all_materials(collections, library_scenes) current_project_name = Path(bpy.context.blend_data.filepath).stem @@ -108,7 +105,7 @@ def export_materials(collections, library_scenes, folder_path, addon_prefs): 'export_apply':True } - gltf_output_path = os.path.join(export_root_path, export_materials_path, current_project_name + "_materials_library") + gltf_output_path = os.path.join(export_materials_path_full, current_project_name + "_materials_library") print(" exporting Materials to", gltf_output_path, ".gltf/glb") diff --git a/tools/blenvy/gltf_auto_export/ui/main.py b/tools/blenvy/gltf_auto_export/ui/main.py index baabad9..693e19c 100644 --- a/tools/blenvy/gltf_auto_export/ui/main.py +++ b/tools/blenvy/gltf_auto_export/ui/main.py @@ -13,7 +13,6 @@ class GLTF_PT_auto_export_SidePanel(bpy.types.Panel): bl_context = "objectmode" bl_parent_id = "BLENVY_PT_SidePanel" - @classmethod def poll(cls, context): return context.window_manager.blenvy.mode == 'SETTINGS' @@ -40,26 +39,6 @@ class GLTF_PT_auto_export_SidePanel(bpy.types.Panel): op = layout.operator("EXPORT_SCENES_OT_auto_gltf", text="Auto Export Settings") op.auto_export = True -class GLTF_PT_auto_export_changes_list(bpy.types.Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Changes per scene since last save " - bl_parent_id = "GLTF_PT_auto_export_SidePanel" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False # No animation. - - #if "auto_export_tracker" in context.window_manager: - changed_objects_per_scene = context.window_manager.auto_export_tracker.changed_objects_per_scene - for scene_name in changed_objects_per_scene: - layout.label(text=f'{scene_name}') - for object_name in list(changed_objects_per_scene[scene_name].keys()): - row = layout.row() - row.label(text=f' {object_name}') - # main ui in the file => export class GLTF_PT_auto_export_main(bpy.types.Panel): bl_space_type = 'FILE_BROWSER' diff --git a/tools/blenvy/gltf_auto_export/ui/operators.py b/tools/blenvy/gltf_auto_export/ui/operators.py index a2fcffd..c5501f5 100644 --- a/tools/blenvy/gltf_auto_export/ui/operators.py +++ b/tools/blenvy/gltf_auto_export/ui/operators.py @@ -130,7 +130,7 @@ class OT_OpenFolderbrowser(Operator, ImportHelper): print("blend_file_folder_path", blend_file_folder_path) print("new_path", self.directory, self.target_property, operator) - path_names = ['export_assets_path', 'export_blueprints_path', 'export_levels_path', 'export_materials_path'] + asset_path_names = ['export_assets_path', 'export_blueprints_path', 'export_levels_path', 'export_materials_path'] export_root_path = operator.export_root_path export_assets_path = operator.export_assets_path #export_root_path_absolute = os.path.join(blend_file_folder_path, export_root_path) @@ -142,10 +142,11 @@ class OT_OpenFolderbrowser(Operator, ImportHelper): new_root_path_relative = os.path.relpath(new_path, blend_file_folder_path) print("changing root new_path to", self.directory, blend_file_folder_path, new_root_path_relative) # we need to change all other relative paths before setting the new absolute path - for path_name in path_names: - # get absolute path + for path_name in asset_path_names: + # get current relative path relative_path = getattr(operator, path_name, None) if relative_path is not None: + # and now get absolute path of asset_path absolute_path = os.path.join(export_assets_path_full, relative_path) print("absolute path for", path_name, absolute_path) relative_path = os.path.relpath(absolute_path, new_path) @@ -153,7 +154,8 @@ class OT_OpenFolderbrowser(Operator, ImportHelper): # store the root path as relative to the current blend file setattr(operator, target_path_name, new_path) - + elif target_path_name == 'export_assets_path': + pass else: relative_path = os.path.relpath(new_path, export_assets_path_full) setattr(operator, target_path_name, relative_path) diff --git a/tools/gltf_auto_export/TODO.md b/tools/gltf_auto_export/TODO.md index 791240b..ebfda0a 100644 --- a/tools/gltf_auto_export/TODO.md +++ b/tools/gltf_auto_export/TODO.md @@ -67,7 +67,3 @@ Change storage of 'blueprint' assets : (from BlueprintsList) - make asset storage generic enough to allow adding additional asset types - get inspired by bevy_asset_loader ? -Assets: - - [ ] store assets - - [ ] per main scene for level/world assets - - [ ] per blueprint for blueprint in lib scene \ No newline at end of file diff --git a/tools/gltf_auto_export/helpers/helpers_blueprints.py b/tools/gltf_auto_export/helpers/helpers_blueprints.py index 9d0f4a4..ebe2811 100644 --- a/tools/gltf_auto_export/helpers/helpers_blueprints.py +++ b/tools/gltf_auto_export/helpers/helpers_blueprints.py @@ -308,7 +308,6 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs): assets_list_name = f"assets_list_{scene.name}_components" assets_list_data = {} - # FIXME: temporary hack for blueprint in blueprints_data.blueprints: bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint) @@ -325,7 +324,7 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs): blueprints_in_scene += blueprint.nested_blueprints assets_list_data["BlueprintsList"] = f"({json.dumps(dict(children_per_blueprint))})" print(blueprint_instance_names_for_scene) - add_scene_property(scene, assets_list_name, assets_list_data) + #add_scene_property(scene, assets_list_name, assets_list_data) relative_blueprints_path = os.path.relpath(export_blueprints_path, export_root_folder) @@ -346,7 +345,6 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs): if blueprint_exported_path is not None: blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "internal": True}) - # fetch images/textures # see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image textures = []