feat(Blenvy): a lot of verious tweaks & fixes

* fixed/ overhauld asset & blueprint scanning
 * added polling for blueprints (not 100% sure yet)
 * add-on-prefs => settings
 * removed the now obsolete auto-export operator & preperences
 * a lot of other minor changes
This commit is contained in:
kaosat.dev 2024-05-25 10:46:14 +02:00
parent 008f6b3a88
commit c00c9908eb
30 changed files with 199 additions and 604 deletions

View File

@ -71,7 +71,7 @@ Components:
General things to solve:
- [x] save settings
- [x] load settings
- [ ] add_blueprints_data
- [ ] add blueprints data
- [x] rename all path stuff using the old naming convention : "blueprints_path_full"
- [x] generate the full paths directly when setting them in the UI
@ -83,6 +83,5 @@ General issues:
- "parents" can only be blueprints
- they normally need/have unique export paths (otherwise, user error, perhaps show it ?)
- perhaps a simple hashing of the parent's path would be enought
- [ ] addon-prefs => settings
- [ ] generate_gltf_export_preferences => should not use add-on prefs at all ? since we are not overriding gltf settings that way anymore ?
- [x] addon-prefs => settings
- [x] generate_gltf_export_preferences => should not use add-on prefs at all ? since we are not overriding gltf settings that way anymore ?

View File

@ -31,7 +31,6 @@ from .bevy_components.components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
# auto export
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.settings import AutoExportSettings
@ -114,7 +113,6 @@ classes = [
GENERIC_MAP_OT_actions,
# gltf auto export
AutoExportGLTF,
AutoExportTracker,
AutoExportSettings,
@ -146,6 +144,7 @@ def post_save(scene, depsgraph):
@persistent
def post_load(file_name):
print("POST LOAD")
registry = bpy.context.window_manager.components_registry
if registry is not None:
registry.load_settings()

View File

@ -4,12 +4,12 @@ import bpy
from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list
def scan_assets(scene, blueprints_data, addon_prefs):
project_root_path = getattr(addon_prefs, "project_root_path")
export_output_folder = getattr(addon_prefs,"export_output_folder")
levels_path = getattr(addon_prefs,"levels_path")
blueprints_path = getattr(addon_prefs, "blueprints_path")
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
def scan_assets(scene, blueprints_data, settings):
project_root_path = getattr(settings, "project_root_path")
export_output_folder = getattr(settings,"export_output_folder")
levels_path = getattr(settings,"levels_path")
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension")
relative_blueprints_path = os.path.relpath(blueprints_path, project_root_path)
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None)
@ -61,9 +61,9 @@ def get_userTextures():
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
print("textures", textures)
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
blueprints_path = getattr(addon_prefs, "blueprints_path")
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension")
assets_list = []
@ -80,7 +80,7 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
assets_list.append({"name": child_blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True,"internal":blueprint.local, "parent": blueprint.name})
# and add sub stuff
sub_assets_lists = get_blueprint_assets_tree(child_blueprint, blueprints_data, parent=child_blueprint.name, addon_prefs=addon_prefs)
sub_assets_lists = get_blueprint_assets_tree(child_blueprint, blueprints_data, parent=child_blueprint.name, settings=settings)
assets_list += sub_assets_lists
direct_assets = get_user_assets_as_list(blueprint.collection)
@ -90,9 +90,9 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
assets_list += direct_assets
return assets_list
def get_main_scene_assets_tree(main_scene, blueprints_data, addon_prefs):
blueprints_path = getattr(addon_prefs, "blueprints_path")
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
def get_main_scene_assets_tree(main_scene, blueprints_data, settings):
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension")
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(main_scene.name, None)
assets_list = get_user_assets_as_list(main_scene)
@ -109,7 +109,7 @@ def get_main_scene_assets_tree(main_scene, blueprints_data, addon_prefs):
if blueprint_exported_path is not None and not does_asset_exist(assets_list, blueprint_exported_path):
assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True, "internal":blueprint.local, "parent": None})
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, addon_prefs=addon_prefs)
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, settings=settings)
print("TOTAL ASSETS", assets_list)
return assets_list

View File

@ -52,7 +52,6 @@ class OT_add_bevy_asset(Operator):
) # type: ignore
def execute(self, context):
assets = []
blueprint_assets = self.target_type == 'BLUEPRINT'
target = None
if blueprint_assets:
@ -61,7 +60,9 @@ class OT_add_bevy_asset(Operator):
target = bpy.data.scenes[self.target_name]
assets = get_user_assets(target)
asset = {"name": self.asset_name, "type": self.asset_type, "path": self.asset_path}
print('assets', assets, target)
if not does_asset_exist(target, asset):
print("add asset", target, asset)
upsert_asset(target, asset)
#assets.append({"name": self.asset_name, "type": self.asset_type, "path": self.asset_path, "internal": False})
@ -202,7 +203,7 @@ class OT_test_bevy_assets(Operator):
blenvy = context.window_manager.blenvy
settings = blenvy
blueprints_registry = context.window_manager.blueprints_registry
blueprints_registry.add_blueprints_data()
blueprints_registry.refresh_blueprints()
blueprints_data = blueprints_registry.blueprints_data
for scene in blenvy.main_scenes:

View File

@ -74,7 +74,7 @@ class Blenvy_assets(bpy.types.Panel):
asset_registry = context.window_manager.assets_registry
blueprints_registry = context.window_manager.blueprints_registry
blueprints_registry.add_blueprints_data()
#blueprints_registry.refresh_blueprints()
blueprints_data = blueprints_registry.blueprints_data
name = "world"
@ -85,9 +85,12 @@ class Blenvy_assets(bpy.types.Panel):
settings = SimpleNamespace(**settings)
if panel:
for scene in blenvy.main_scenes:
#print("dfs")
for scene_selector in blenvy.main_scenes:
scene = bpy.data.scenes[scene_selector.name]
#get_main_scene_assets_tree(scene, blueprints_data, settings)
user_assets = get_user_assets(scene)
#print("user assets", user_assets, scene)
row = panel.row()
scene_assets_panel = draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
"""if scene.name in blueprints_data.blueprint_instances_per_main_scene:

View File

@ -206,14 +206,14 @@ class OT_select_object(Operator):
bl_label = "Select object"
bl_options = {"UNDO"}
object_name: StringProperty(
name="object_name",
description="object to select's name ",
target_name: StringProperty(
name="target name",
description="target to select's name ",
) # type: ignore
def execute(self, context):
if self.object_name:
object = bpy.data.objects[self.object_name]
if self.target_name:
object = bpy.data.objects[self.target_name]
scenes_of_object = list(object.users_scene)
if len(scenes_of_object) > 0:
bpy.ops.object.select_all(action='DESELECT')

View File

@ -3,6 +3,8 @@ import bpy
from bpy_types import (UIList)
from bpy.props import (StringProperty)
from ..utils import get_selection_type
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator
from .operators import(
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
@ -78,7 +80,7 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
col.label(text=item)
def draw_invalid_or_unregistered(self, layout, status, component_name, object):
def draw_invalid_or_unregistered(self, layout, status, component_name, target):
available_components = bpy.context.window_manager.components_list
registry = bpy.context.window_manager.components_registry
registry_has_type_infos = registry.has_type_infos()
@ -89,8 +91,8 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
col.label(text=component_name)
col = row.column()
operator = col.operator(OT_select_object.bl_idname, text=object.name)
operator.object_name = object.name
operator = col.operator("object.select", text=target.name)
operator.target_name = target.name
col = row.column()
col.label(text=status)
@ -99,22 +101,24 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
col.prop(available_components, "list", text="")
col = row.column()
operator = col.operator(OT_rename_component.bl_idname, text="", icon="SHADERFX") #rename
operator = col.operator("object.rename_bevy_component", text="", icon="SHADERFX") #rename
new_name = registry.type_infos[available_components.list]['long_name'] if available_components.list in registry.type_infos else ""
operator.original_name = component_name
operator.target_objects = json.dumps([object.name])
operator.target_objects = json.dumps([target.name])
operator.new_name = new_name
col.enabled = registry_has_type_infos and component_name != "" and component_name != new_name
col = row.column()
operator = col.operator(RemoveComponentOperator.bl_idname, text="", icon="X")
operator.object_name = object.name
operator = col.operator("object.remove_bevy_component", text="", icon="X")
operator.item_name = target.name
operator.component_name = component_name
operator.item_type = get_selection_type(target)
col = row.column()
col = row.column()
operator = col.operator(OT_select_component_name_to_replace.bl_idname, text="", icon="EYEDROPPER") #text="select for rename",
operator = col.operator("object.select_component_name_to_replace", text="", icon="EYEDROPPER") #text="select for rename",
operator.component_name = component_name
def draw(self, context):

View File

@ -25,12 +25,12 @@ def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_
blueprint_exported_path = os.path.join(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):
project_root_path = getattr(addon_prefs, "project_root_path")
assets_path = getattr(addon_prefs,"assets_path")
levels_path = getattr(addon_prefs,"levels_path")
blueprints_path = getattr(addon_prefs, "blueprints_path")
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
def inject_blueprints_list_into_main_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"

View File

@ -8,9 +8,20 @@ from bpy_types import (PropertyGroup)
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
from ..settings import load_settings
from ..gltf_auto_export.helpers.helpers_scenes import get_scenes
from ..core.scene_helpers import get_main_and_library_scenes
from .blueprints_scan import blueprints_scan
def refresh_blueprints():
try:
blueprints_registry = bpy.context.window_manager.blueprints_registry
blueprints_registry.refresh_blueprints()
#print('refresh blueprints')
except:pass
return 3
# this is where we store the information for all available Blueprints
class BlueprintsRegistry(PropertyGroup):
blueprints_data = {}
@ -40,17 +51,25 @@ class BlueprintsRegistry(PropertyGroup):
@classmethod
def register(cls):
bpy.types.WindowManager.blueprints_registry = PointerProperty(type=BlueprintsRegistry)
bpy.app.timers.register(refresh_blueprints)
@classmethod
def unregister(cls):
try:
bpy.app.timers.unregister(refresh_blueprints)
except: pass
del bpy.types.WindowManager.blueprints_registry
def add_blueprint(self, blueprint):
self.blueprints_list.append(blueprint)
def add_blueprints_data(self):
def refresh_blueprints(self):
blenvy = bpy.context.window_manager.blenvy
addon_prefs = blenvy
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
blueprints_data = blueprints_scan(level_scenes, library_scenes, addon_prefs)
settings = blenvy
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
blueprints_data = blueprints_scan(level_scenes, library_scenes, settings)
self.blueprints_data = blueprints_data
"""for blueprint in blueprints_data.blueprints:
self.add_blueprint(blueprint)"""

View File

@ -7,8 +7,8 @@ from .blueprint import Blueprint
# - marked as asset
# - with the "auto_export" flag
# https://blender.stackexchange.com/questions/167878/how-to-get-all-collections-of-the-current-scene
def blueprints_scan(main_scenes, library_scenes, addon_prefs):
export_marked_assets = getattr(addon_prefs.auto_export,"export_marked_assets")
def blueprints_scan(main_scenes, library_scenes, settings):
export_marked_assets = getattr(settings.auto_export, "export_marked_assets")
blueprints = {}
blueprints_from_objects = {}

View File

@ -14,15 +14,18 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
@classmethod
def poll(cls, context):
return context.window_manager.blenvy.mode == 'BLUEPRINTS'
return context.window_manager.blenvy.mode == 'BLUEPRINTS' if 'blenvy' in context.window_manager else False
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
asset_registry = context.window_manager.assets_registry
blueprint_registry = context.window_manager.blueprints_registry
for blueprint in context.window_manager.blueprints_registry.blueprints_list:
blueprint_registry.refresh_blueprints()
for blueprint in blueprint_registry.blueprints_data.blueprints:
row = layout.row()
row.label(icon="RIGHTARROW")
row.label(text=blueprint.name)

View File

@ -132,6 +132,7 @@ class BlenvyManager(PropertyGroup):
del bpy.types.WindowManager.library_scene
def load_settings(self):
print("LOAD SETTINGS")
settings = load_settings(self.settings_save_path)
if settings is not None:
if "mode" in settings:

View File

@ -8,7 +8,7 @@ class OT_switch_bevy_tooling(Operator):
"""Switch bevy tooling"""
bl_idname = "bevy.tooling_switch"
bl_label = "Switch bevy tooling"
bl_options = {"UNDO"}
#bl_options = {}
tool: EnumProperty(

View File

@ -7,6 +7,24 @@ class SceneSelector(bpy.types.PropertyGroup):
display: bpy.props.BoolProperty() # type: ignore
# convenience utility to get lists of scenes
def get_main_and_library_scenes(settings):
level_scene_names= getattr(settings, "main_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
library_scene_names = getattr(settings, "library_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
level_scene_names= list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
library_scene_names = list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
print("level_scene_names", level_scene_names)
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
level_scenes = list(map(lambda name: bpy.data.scenes[name], level_scene_names))
library_scenes = list(map(lambda name: bpy.data.scenes[name], library_scene_names))
return [level_scene_names, level_scenes, library_scene_names, library_scenes]
def add_scene_property(scene, scene_component_name, property_data, limit_to=None):
root_collection = scene.collection
scene_property = None

View File

@ -31,12 +31,12 @@ def gltf_post_export_callback(data):
scene = bpy.context.scene
if "glTF2ExportSettings" in scene:
settings = scene["glTF2ExportSettings"]
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
gltf_export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
# now write new settings
export_settings.clear()
gltf_export_settings.clear()
current_gltf_settings = generate_complete_preferences_dict_gltf(dict(settings))
export_settings.write(json.dumps(current_gltf_settings))
gltf_export_settings.write(json.dumps(current_gltf_settings))
# now reset the original gltf_settings
if gltf_settings_backup != "":
scene["glTF2ExportSettings"] = json.loads(gltf_settings_backup)

View File

@ -3,7 +3,7 @@ import os
import bpy
import traceback
from ..helpers.helpers_scenes import (get_scenes, )
from ...core.scene_helpers import get_main_and_library_scenes
from .get_blueprints_to_export import get_blueprints_to_export
from .get_levels_to_export import get_levels_to_export
@ -19,7 +19,7 @@ from ...blueprints.blueprint_helpers import inject_export_path_into_internal_blu
"""this is the main 'central' function for all auto export """
def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
def auto_export(changes_per_scene, changed_export_parameters, settings):
# have the export parameters (not auto export, just gltf export) have changed: if yes (for example switch from glb to gltf, compression or not, animations or not etc), we need to re-export everything
print ("changed_export_parameters", changed_export_parameters)
try:
@ -27,41 +27,34 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
file_path = bpy.data.filepath
# Get the folder
blend_file_path = os.path.dirname(file_path)
# get the preferences for our addon
project_root_path = getattr(addon_prefs, "project_root_path")
assets_path = getattr(addon_prefs,"assets_path")
#should we use change detection or not
change_detection = getattr(addon_prefs.auto_export, "change_detection")
export_scene_settings = getattr(addon_prefs.auto_export,"export_scene_settings")
do_export_blueprints = getattr(addon_prefs.auto_export,"export_blueprints")
export_materials_library = getattr(addon_prefs.auto_export,"export_materials_library")
change_detection = getattr(settings.auto_export, "change_detection")
export_scene_settings = getattr(settings.auto_export,"export_scene_settings")
do_export_blueprints = getattr(settings.auto_export,"export_blueprints")
export_materials_library = getattr(settings.auto_export,"export_materials_library")
# standard gltf export settings are stored differently
standard_gltf_exporter_settings = get_standard_exporter_settings()
gltf_extension = standard_gltf_exporter_settings.get("export_format", 'GLB')
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
# generate the actual complete output paths
"""addon_prefs.assets_path_full = os.path.join(blend_file_path, project_root_path, assets_path)
addon_prefs.blueprints_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"blueprints_path"))
addon_prefs.levels_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"levels_path"))
addon_prefs.materials_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"materials_path"))"""
addon_prefs.export_gltf_extension = gltf_extension
settings.export_gltf_extension = gltf_extension
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
blueprints_data = blueprints_scan(level_scenes, library_scenes, addon_prefs)
bpy.context.window_manager.blueprints_registry.refresh_blueprints()
blueprints_data = bpy.context.window_manager.blueprints_registry.blueprints_data
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
blueprints_path = getattr(addon_prefs,"blueprints_path")
blueprints_path = getattr(settings,"blueprints_path")
inject_export_path_into_internal_blueprints(internal_blueprints=blueprints_data.internal_blueprints, blueprints_path=blueprints_path, gltf_extension=gltf_extension)
for blueprint in blueprints_data.blueprints:
bpy.context.window_manager.blueprints_registry.add_blueprint(blueprint)
#bpy.context.window_manager.blueprints_registry.add_blueprints_data()
#bpy.context.window_manager.blueprints_registry.refresh_blueprints()
print("YO YO")
if export_scene_settings:
# inject/ update scene components
@ -75,15 +68,15 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
if do_export_blueprints:
print("EXPORTING")
# get blueprints/collections infos
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs)
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings)
# get level/main scenes infos
(main_scenes_to_export) = get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs)
(main_scenes_to_export) = get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings)
# 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, addon_prefs)
export_materials(blueprints_data.blueprint_names, library_scenes, settings)
# update the list of tracked exports
exports_total = len(blueprints_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0)
@ -115,13 +108,13 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
print("export MAIN scenes")
for scene_name in main_scenes_to_export:
print(" exporting scene:", scene_name)
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, addon_prefs, blueprints_data)
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, blueprints_data)
# now deal with blueprints/collections
do_export_library_scene = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
if do_export_library_scene:
print("export LIBRARY")
export_blueprints(blueprints_to_export, addon_prefs, blueprints_data)
export_blueprints(blueprints_to_export, settings, blueprints_data)
# reset current scene from backup
bpy.context.window.scene = old_current_scene
@ -134,7 +127,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
else:
for scene_name in main_scene_names:
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, addon_prefs, [])
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, [])
@ -148,7 +141,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
finally:
# FIXME: error handling ? also redundant
[main_scene_names, main_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
[main_scene_names, main_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
if export_scene_settings:
# inject/ update scene components

View File

@ -7,32 +7,32 @@ from .export_gltf import (generate_gltf_export_preferences)
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
def export_blueprints(blueprints, addon_prefs, blueprints_data):
blueprints_path_full = getattr(addon_prefs, "blueprints_path_full")
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
def export_blueprints(blueprints, settings, blueprints_data):
blueprints_path_full = getattr(settings, "blueprints_path_full")
gltf_export_preferences = generate_gltf_export_preferences(settings)
try:
# save current active collection
active_collection = bpy.context.view_layer.active_layer_collection
export_materials_library = getattr(addon_prefs.auto_export, "export_materials_library")
export_materials_library = getattr(settings.auto_export, "export_materials_library")
for blueprint in blueprints:
print("exporting collection", blueprint.name)
gltf_output_path = os.path.join(blueprints_path_full, blueprint.name)
export_settings = { **gltf_export_preferences, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
gltf_export_settings = { **gltf_export_preferences, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
# if we are using the material library option, do not export materials, use placeholder instead
if export_materials_library:
export_settings['export_materials'] = 'PLACEHOLDER'
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
collection = bpy.data.collections[blueprint.name]
# do the actual export
generate_and_export(
addon_prefs,
settings,
temp_scene_name=TEMPSCENE_PREFIX+collection.name,
export_settings=export_settings,
gltf_export_settings=gltf_export_settings,
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, addon_prefs=addon_prefs),
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=collection, temp_scene=temp_scene, **params)
)

View File

@ -3,9 +3,8 @@ import os
import bpy
from .get_standard_exporter_settings import get_standard_exporter_settings
from .preferences import (AutoExportGltfPreferenceNames)
def generate_gltf_export_preferences(addon_prefs):
def generate_gltf_export_preferences(settings):
# default values
gltf_export_preferences = dict(
# export_format= 'GLB', #'GLB', 'GLTF_SEPARATE', 'GLTF_EMBEDDED'
@ -43,10 +42,10 @@ def generate_gltf_export_preferences(addon_prefs):
#export_optimize_animation_size=False
)
for key in addon_prefs.__annotations__.keys():
"""for key in settings.__annotations__.keys():
if str(key) not in AutoExportGltfPreferenceNames:
#print("overriding setting", key, "value", getattr(addon_prefs,key))
pass#gltf_export_preferences[key] = getattr(addon_prefs, key)
#print("overriding setting", key, "value", getattr(settings,key))
pass#gltf_export_preferences[key] = getattr(settings, key)"""
standard_gltf_exporter_settings = get_standard_exporter_settings()
@ -70,8 +69,8 @@ def generate_gltf_export_preferences(addon_prefs):
#https://docs.blender.org/api/current/bpy.ops.export_scene.html#bpy.ops.export_scene.gltf
def export_gltf (path, export_settings):
settings = {**export_settings, "filepath": path}
def export_gltf (path, gltf_export_settings):
settings = {**gltf_export_settings, "filepath": path}
# print("export settings",settings)
os.makedirs(os.path.dirname(path), exist_ok=True)
bpy.ops.export_scene.gltf(**settings)

View File

@ -9,15 +9,15 @@ from ..modules.bevy_dynamic import is_object_dynamic, is_object_static
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
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)
assets_path_full = getattr(addon_prefs,"assets_path_full")
levels_path_full = getattr(addon_prefs,"levels_path_full")
def export_main_scene(scene, blend_file_path, settings, blueprints_data):
gltf_export_preferences = generate_gltf_export_preferences(settings)
assets_path_full = getattr(settings,"assets_path_full")
levels_path_full = getattr(settings,"levels_path_full")
export_blueprints = getattr(addon_prefs.auto_export,"export_blueprints")
export_separate_dynamic_and_static_objects = getattr(addon_prefs.auto_export, "export_separate_dynamic_and_static_objects")
export_blueprints = getattr(settings.auto_export,"export_blueprints")
export_separate_dynamic_and_static_objects = getattr(settings.auto_export, "export_separate_dynamic_and_static_objects")
export_settings = { **gltf_export_preferences,
gltf_export_settings = { **gltf_export_preferences,
'use_active_scene': True,
'use_active_collection':True,
'use_active_collection_with_nested':True,
@ -29,45 +29,46 @@ def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data):
if export_blueprints :
gltf_output_path = os.path.join(levels_path_full, scene.name)
#inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs)
#inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
if export_separate_dynamic_and_static_objects:
#print("SPLIT STATIC AND DYNAMIC")
# first export static objects
generate_and_export(
addon_prefs,
settings,
temp_scene_name=TEMPSCENE_PREFIX,
export_settings=export_settings,
gltf_export_settings=gltf_export_settings,
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_static, addon_prefs=addon_prefs),
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_static, settings=settings),
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
)
# then export all dynamic objects
gltf_output_path = os.path.join(levels_path_full, scene.name+ "_dynamic")
generate_and_export(
addon_prefs,
settings,
temp_scene_name=TEMPSCENE_PREFIX,
export_settings=export_settings,
gltf_export_settings=gltf_export_settings,
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_dynamic, addon_prefs=addon_prefs),
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_dynamic, settings=settings),
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
)
else:
#print("NO SPLIT")
generate_and_export(
addon_prefs,
settings,
temp_scene_name=TEMPSCENE_PREFIX,
export_settings=export_settings,
gltf_export_settings=gltf_export_settings,
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, addon_prefs=addon_prefs),
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
)
else:
gltf_output_path = os.path.join(assets_path_full, scene.name)
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
export_gltf(gltf_output_path, export_settings)
if settings.auto_export.dry_run == "DISABLED":
export_gltf(gltf_output_path, gltf_export_settings)
remove_blueprints_list_from_main_scene(scene)

View File

@ -1,16 +1,15 @@
import bpy
import os
from ..helpers.helpers_scenes import (get_scenes, )
from ...core.scene_helpers import get_main_and_library_scenes
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):
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension", ".glb")
blueprints_path_full = getattr(addon_prefs,"blueprints_path_full", "")
change_detection = getattr(addon_prefs.auto_export, "change_detection")
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
def get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
blueprints_path_full = getattr(settings,"blueprints_path_full", "")
change_detection = getattr(settings.auto_export, "change_detection")
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
internal_blueprints = blueprints_data.internal_blueprints
blueprints_to_export = internal_blueprints # just for clarity

View File

@ -1,6 +1,6 @@
import bpy
from ...core.scene_helpers import get_main_and_library_scenes
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
def changed_object_in_scene(scene_name, changes_per_scene, blueprints_data, collection_instances_combine_mode):
@ -36,14 +36,14 @@ def changed_object_in_scene(scene_name, changes_per_scene, blueprints_data, coll
# this also takes the split/embed mode into account: if a collection instance changes AND embed is active, its container level/world should also be exported
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs):
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
levels_path_full = getattr(addon_prefs, "levels_path_full")
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
export_gltf_extension = getattr(settings, "export_gltf_extension")
levels_path_full = getattr(settings, "levels_path_full")
change_detection = getattr(addon_prefs.auto_export, "change_detection")
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
change_detection = getattr(settings.auto_export, "change_detection")
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
# determine list of main scenes to export
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)

View File

@ -1,228 +0,0 @@
import json
import bpy
from bpy.types import Operator
#from ..ui.main import GLTF_PT_auto_export_general, GLTF_PT_auto_export_main, GLTF_PT_auto_export_root
from .preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
from .auto_export import auto_export
from ..helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_auto
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
"""auto export gltf"""
#bl_idname = "object.xxx"
bl_idname = "export_scenes.auto_gltf"
bl_label = "Apply settings"
bl_options = {'PRESET'} # we do not add UNDO otherwise it leads to an invisible operation that resets the state of the saved serialized scene, breaking compares for normal undo/redo operations
# ExportHelper mixin class uses this
#filename_ext = ''
#filepath: bpy.props.StringProperty(subtype="FILE_PATH", default="") # type: ignore
#list of settings (other than purely gltf settings) whose change should trigger a re-generation of gltf files
white_list = [
'auto_export',
'project_root_path',
'assets_path',
'change_detection',
'export_scene_settings',
'main_scene_names',
'library_scene_names',
'export_blueprints',
'blueprints_path',
'export_marked_assets',
'collection_instances_combine_mode',
'levels_path',
'export_separate_dynamic_and_static_objects',
'export_materials_library',
'materials_path',
]
@classmethod
def register(cls):
pass
@classmethod
def unregister(cls):
pass
def format_settings(self):
# find all props to save
exceptional = [
# options that don't start with 'export_'
'collection_instances_combine_mode',
]
all_props = self.properties
export_props = {
x: getattr(self, x) for x in dir(all_props)
if (x.startswith("export_") or x in exceptional) and all_props.get(x) is not None
}
# we inject all that we need, the above is not sufficient
for (k, v) in self.properties.items():
if k in self.white_list or k not in AutoExportGltfPreferenceNames:
value = v
# FIXME: really weird having to do this
if k == "collection_instances_combine_mode":
value = self.collection_instances_combine_mode
if k == "export_materials":
value = self.export_materials
export_props[k] = value
# we add main & library scene names to our preferences
return export_props
def save_settings(self, context):
print("save settings")
auto_export_settings = self.format_settings()
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
stored_settings.clear()
auto_export_settings = generate_complete_preferences_dict_auto(auto_export_settings)
stored_settings.write(json.dumps(auto_export_settings))
print("saved settings", auto_export_settings)
#print("saving settings", bpy.data.texts[".gltf_auto_export_settings"].as_string(), "raw", json.dumps(export_props))
def load_settings(self, context):
print("loading settings")
settings = None
try:
settings = bpy.data.texts[".gltf_auto_export_settings"].as_string()
settings = json.loads(settings)
except: pass
self.will_save_settings = False
if settings:
#print("loading settings in invoke AutoExportGLTF", settings)
try:
for (k, v) in settings.items():
#print("loading setting", k, v)
setattr(self, k, v)
self.will_save_settings = True
# Update filter if user saved settings
if hasattr(self, 'export_format'):
self.filter_glob = '*.glb' if self.export_format == 'GLB' else '*.gltf'
# inject scenes data
if hasattr(self, 'main_scene_names'):
main_scenes = self.main_scenes
main_scenes.clear()
for item_name in self.main_scene_names:
item = main_scenes.add()
item.name = item_name
if hasattr(self, 'library_scene_names'):
library_scenes = self.library_scenes
library_scenes.clear()
for item_name in self.library_scene_names:
item = library_scenes.add()
item.name = item_name
except Exception as error:
print("error", error)
self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
bpy.data.texts.remove(bpy.data.texts[".gltf_auto_export_settings"])
else:
self.will_save_settings = True
"""
This should ONLY be run when actually doing exports/aka calling auto_export function, because we only care about the difference in settings between EXPORTS
"""
def did_export_settings_change(self):
return True
# compare both the auto export settings & the gltf settings
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else None
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else None
current_auto_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
current_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
#check if params have changed
# if there were no setting before, it is new, we need export
changed = False
if previous_auto_settings == None:
#print("previous settings missing, exporting")
changed = True
elif previous_gltf_settings == None:
#print("previous gltf settings missing, exporting")
previous_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings_previous")
previous_gltf_settings.write(json.dumps({}))
if current_gltf_settings == None:
current_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings")
current_gltf_settings.write(json.dumps({}))
changed = True
else:
auto_settings_changed = sorted(json.loads(previous_auto_settings.as_string()).items()) != sorted(json.loads(current_auto_settings.as_string()).items()) if current_auto_settings != None else False
gltf_settings_changed = sorted(json.loads(previous_gltf_settings.as_string()).items()) != sorted(json.loads(current_gltf_settings.as_string()).items()) if current_gltf_settings != None else False
"""print("auto settings previous", sorted(json.loads(previous_auto_settings.as_string()).items()))
print("auto settings current", sorted(json.loads(current_auto_settings.as_string()).items()))
print("auto_settings_changed", auto_settings_changed)
print("gltf settings previous", sorted(json.loads(previous_gltf_settings.as_string()).items()))
print("gltf settings current", sorted(json.loads(current_gltf_settings.as_string()).items()))
print("gltf_settings_changed", gltf_settings_changed)"""
changed = auto_settings_changed or gltf_settings_changed
# now write the current settings to the "previous settings"
if current_auto_settings != None:
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings_previous")
previous_auto_settings.clear()
previous_auto_settings.write(current_auto_settings.as_string()) # TODO : check if this is always valid
if current_gltf_settings != None:
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings_previous")
previous_gltf_settings.clear()
previous_gltf_settings.write(current_gltf_settings.as_string())
return changed
def did_objects_change(self):
# FIXME: add it back
return {}
def execute(self, context):
print("execute auto export", context.window_manager.blenvy.auto_export)
blenvy = context.window_manager.blenvy
auto_export_settings = blenvy.auto_export
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
if self.direct_mode:
self.load_settings(context)
if self.will_save_settings:
self.save_settings(context)
#print("self", self.auto_export)
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled
print("auto export")
#changes_per_scene = context.window_manager.auto_export_tracker.changed_objects_per_scene
#& do the export
# determine changed objects
changes_per_scene = self.did_objects_change()
# determine changed parameters
params_changed = self.did_export_settings_change()
auto_export(changes_per_scene, params_changed, blenvy)
# cleanup
# reset the list of changes in the tracker
bpy.context.window_manager.auto_export_tracker.clear_changes()
print("AUTO EXPORT DONE")
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=0.1)
else:
print("auto export disabled, skipping")
return {'FINISHED'}
def invoke(self, context, event):
print("invoke")
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
self.load_settings(context)
return context.window_manager.invoke_props_dialog(self, title="Auto export", width=640)
def cancel(self, context):
print("cancel")
#bpy.context.window_manager.auto_export_tracker.enable_change_detection()
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)

View File

@ -1,201 +0,0 @@
import os
from bpy.types import AddonPreferences
from bpy.props import (BoolProperty,
IntProperty,
StringProperty,
EnumProperty,
CollectionProperty
)
AutoExportGltfPreferenceNames = [
'will_save_settings',
'direct_mode',# specific to main auto_export operator
'show_general_settings',
'auto_export',
'project_root_path',
'assets_path',
'export_scene_settings',
'show_change_detection_settings',
'change_detection',
'show_scene_settings',
'main_scenes',
'library_scenes',
'main_scenes_index',
'library_scenes_index',
'main_scene_names',
'library_scene_names',
'show_blueprint_settings',
'export_blueprints',
'blueprints_path',
'export_marked_assets',
'collection_instances_combine_mode',
'levels_path',
'export_separate_dynamic_and_static_objects',
'export_materials_library',
'materials_path',
]
def on_export_output_folder_updated(self, context):
#self.project_root_path = os.path.relpath(self.project_root_path)
#self.assets_path = os.path.join(self.project_root_path, self.assets_path)
print("on_foo_updated", self.project_root_path, self.assets_path)
class AutoExportGltfAddonPreferences(AddonPreferences):
# this must match the add-on name, use '__package__'
# when defining this in a submodule of a python package.
bl_idname = __package__
bl_options = {'PRESET'}
#### these are for the operator
will_save_settings: BoolProperty(
name='Remember Export Settings',
description='Store glTF export settings in the Blender project',
default=True
) # type: ignore
# use when operator is called directly, works a bit differently than inside the ui
direct_mode: BoolProperty(
default=False
) # type: ignore
auto_export: BoolProperty(
name='Auto export',
description='Automatically export to gltf on save',
default=False
) # type: ignore
#### general
# for UI only, workaround for lacking panels
show_general_settings: BoolProperty(
name="show_general settings",
description="show/hide general settings (UI only: has no impact on exports)",
default=True
) # type: ignore
project_root_path: StringProperty(
name = "Project Root Path",
description="The root folder of your (Bevy) project (not assets!)",
# subtype='DIR_PATH',
default='../'
#update=on_export_output_folder_updated) # type: ignore
)
assets_path: StringProperty(
name='Export folder',
description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ',
default='./assets',
#subtype='DIR_PATH',
options={'HIDDEN'}
# update=on_export_output_folder_updated
) # type: ignore
# for UI only, workaround for lacking panels
show_change_detection_settings: BoolProperty(
name="show change detection settings",
description="show/hide change detection settings (UI only: has no impact on exports)",
default=True
) # type: ignore
change_detection: BoolProperty(
name='Change detection',
description='Use change detection to determine what/if should be exported',
default=True
) # type: ignore
# scenes
# for UI only, workaround for lacking panels
show_scene_settings: BoolProperty(
name="show scene settings",
description="show/hide scene settings (UI only: has no impact on exports)",
default=True
) # type: ignore
# scene components
export_scene_settings: BoolProperty(
name='Export scene settings',
description='Export scene settings ie AmbientLighting, Bloom, AO etc',
default=False
) # type: ignore
# blueprint settings
# for UI only, workaround for lacking panels
show_blueprint_settings: BoolProperty(
name="show blueprint settings",
description="show/hide blueprint settings (UI only: has no impact on exports)",
default=True
) # type: ignore
export_blueprints: BoolProperty(
name='Export Blueprints',
description='Replaces collection instances with an Empty with a BlueprintName custom property, and enabled a lot more features !',
default=True
) # type: ignore
blueprints_path: StringProperty(
name='Blueprints path',
description='path to export the blueprints to (relative to the assets folder)',
default='blueprints',
#subtype='DIR_PATH'
) # type: ignore
levels_path: StringProperty(
name='Levels path',
description='path to export the levels (main scenes) to (relative to the assets folder)',
default='levels',
#subtype='DIR_PATH'
) # type: ignore
export_separate_dynamic_and_static_objects: BoolProperty(
name="Export levels' dynamic and static objects seperatly",
description="""For MAIN scenes only (aka levels), toggle this to generate 2 files per level:
- one with all dynamic data: collection or instances marked as dynamic/ saveable
- one with all static data: anything else that is NOT marked as dynamic""",
default=False
) # type: ignore
export_materials_library: BoolProperty(
name='Export materials library',
description='remove materials from blueprints and use the material library instead',
default=False
) # type: ignore
materials_path: StringProperty(
name='Materials path',
description='path to export the materials libraries to (relative to the assets folder)',
default='materials',
#subtype='DIR_PATH'
) # type: ignore
""" combine mode can be
- 'Split' (default): replace with an empty, creating links to sub blueprints
- 'Embed' : treat it as an embeded object and do not replace it with an empty
- 'EmbedExternal': embed any instance of a non local collection (ie external assets)
- 'Inject': inject components from sub collection instances into the curent object => this is now a seperate custom property that you can apply to a collecion instance
"""
collection_instances_combine_mode : EnumProperty(
name='Collection instances',
items=(
('Split', 'Split', 'replace collection instances with an empty + blueprint, creating links to sub blueprints (Default, Recomended)'),
('Embed', 'Embed', 'treat collection instances as embeded objects and do not replace them with an empty'),
('EmbedExternal', 'EmbedExternal', 'treat instances of external (not specifified in the current blend file) collections (aka assets etc) as embeded objects and do not replace them with empties'),
#('Inject', 'Inject', 'inject components from sub collection instances into the curent object')
),
default='Split'
) # type: ignore
export_marked_assets: BoolProperty(
name='Auto export marked assets',
description='Collections that have been marked as assets will be systematically exported, even if not in use in another scene',
default=True
) # type: ignore

View File

@ -8,8 +8,8 @@ from .settings_diff import get_setting_changes
# prepare export by gather the changes to the scenes & settings
def prepare_and_export():
print("prepare and export")
blenvy = bpy.context.window_manager.blenvy
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
blenvy = bpy.context.window_manager.blenvy
auto_export_settings = blenvy.auto_export
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled

View File

@ -6,11 +6,11 @@ from ...core.helpers_collections import (set_active_collection)
generates a temporary scene, fills it with data, cleans up after itself
* named using temp_scene_name
* filled using the tempScene_filler
* written on disk to gltf_output_path, with the gltf export parameters in export_settings
* written on disk to gltf_output_path, with the gltf export parameters in gltf_export_settings
* cleaned up using tempScene_cleaner
"""
def generate_and_export(addon_prefs, export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
def generate_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
temp_root_collection = temp_scene.collection
@ -41,7 +41,8 @@ def generate_and_export(addon_prefs, export_settings, gltf_output_path, temp_sce
scene_filler_data = tempScene_filler(temp_root_collection)
# export the temporary scene
try:
export_gltf(gltf_output_path, export_settings)
if settings.auto_export.dry_run == "DISABLED":
export_gltf(gltf_output_path, gltf_export_settings)
except Exception as error:
print("failed to export gltf !", error)
raise error

View File

@ -1,5 +1,4 @@
from ..auto_export.preferences import AutoExportGltfAddonPreferences
from io_scene_gltf2 import (ExportGLTF2_Base)
# given the input (actual) gltf settings, filters out any invalid/useless params & params that are equal to defaults
@ -28,12 +27,12 @@ def generate_complete_preferences_dict_gltf(settings):
return complete_preferences
# given the input (actual) auto settings, filters out any invalid/useless params & params that are equal to defaults
def generate_complete_preferences_dict_auto(settings):
def generate_complete_preferences_dict_auto(settings, presets):
complete_preferences = {}
defaults = {}
for k in AutoExportGltfAddonPreferences.__annotations__:
item = AutoExportGltfAddonPreferences.__annotations__[k]
for k in presets.__annotations__:
item = presets.__annotations__[k]
default = item.keywords.get('default', None)
#complete_preferences[k] = default
defaults[k] = default

View File

@ -145,8 +145,8 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
duplicate_object(child, copy, combine_mode, destination_collection, blueprints_data, nester+" ")
# copies the contents of a collection into another one while replacing library instances with empties
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, blueprints_data=None, addon_prefs={}):
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, blueprints_data=None, settings={}):
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
for object in source_collection.objects:
if object.name.endswith("____bak"): # some objects could already have been handled, ignore them
@ -172,7 +172,7 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par
parent_empty = collection_placeholder,
filter = filter,
blueprints_data = blueprints_data,
addon_prefs=addon_prefs
settings=settings
)
return {}
@ -204,20 +204,3 @@ def clear_hollow_scene(temp_scene, original_root_collection):
# reset original names
restore_original_names(original_root_collection)
# convenience utility to get lists of scenes
def get_scenes(addon_prefs):
level_scene_names= getattr(addon_prefs, "main_scene_names", []) #list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes")))
library_scene_names = getattr(addon_prefs, "library_scene_names", []) #list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
level_scene_names= list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes")))
library_scene_names = list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
print("level_scene_names", level_scene_names)
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
level_scenes = list(map(lambda name: bpy.data.scenes[name], level_scene_names))
library_scenes = list(map(lambda name: bpy.data.scenes[name], library_scene_names))
return [level_scene_names, level_scenes, library_scene_names, library_scenes]

View File

@ -155,7 +155,7 @@ class glTF2ExportUserExtension:
self.Extension = Extension
self.properties = bpy.context.scene.ExampleExtensionProperties
def gather_node_hook(self, gltf2_object, blender_object, export_settings):
def gather_node_hook(self, gltf2_object, blender_object, gltf_export_settings):
if self.properties.enabled:
if gltf2_object.extensions is None:
gltf2_object.extensions = {}
@ -193,7 +193,7 @@ def did_export_parameters_change(current_params, previous_params):
bpy.context.window.scene = library_scene
with bpy.context.temp_override(scene=library_scene):
print("active scene", bpy.context.scene)
export_gltf(gltf_output_path, export_settings)
export_gltf(gltf_output_path, gltf_export_settings)
bpy.context.window.scene = original_scene"""
"""
@ -296,16 +296,16 @@ def duplicate_object2(object, original_name):
settings = scene["glTF2ExportSettings"]
formatted_settings = dict(settings)
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
gltf_export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
#check if params have changed
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(export_settings.as_string()).items()) != sorted(formatted_settings.items())
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(gltf_export_settings.as_string()).items()) != sorted(formatted_settings.items())
print("gltf NEW settings", formatted_settings, "OLD settings", export_settings, "CHANGED ?", bpy.context.window_manager.gltf_settings_changed)
print("gltf NEW settings", formatted_settings, "OLD settings", gltf_export_settings, "CHANGED ?", bpy.context.window_manager.gltf_settings_changed)
# now write new settings
export_settings.clear()
export_settings.write(json.dumps(formatted_settings))
gltf_export_settings.clear()
gltf_export_settings.write(json.dumps(formatted_settings))
# now reset the original gltf_settings

View File

@ -59,14 +59,14 @@ def clear_materials_scene(temp_scene):
# exports the materials used inside the current project:
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
def export_materials(collections, library_scenes, addon_prefs):
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
materials_path_full = getattr(addon_prefs,"materials_path_full")
def export_materials(collections, library_scenes, settings):
gltf_export_preferences = generate_gltf_export_preferences(settings)
materials_path_full = getattr(settings,"materials_path_full")
used_material_names = get_all_materials(collections, library_scenes)
current_project_name = Path(bpy.context.blend_data.filepath).stem
export_settings = { **gltf_export_preferences,
gltf_export_settings = { **gltf_export_preferences,
'use_active_scene': True,
'use_active_collection':True,
'use_active_collection_with_nested':True,
@ -80,9 +80,9 @@ def export_materials(collections, library_scenes, addon_prefs):
print(" exporting Materials to", gltf_output_path, ".gltf/glb")
generate_and_export(
addon_prefs,
settings=settings,
gltf_export_settings=gltf_export_settings,
temp_scene_name="__materials_scene",
export_settings=export_settings,
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)

View File

@ -76,9 +76,11 @@ class AutoExportSettings(PropertyGroup):
name="dry run",
description="debug/ develop helper to enable everything but the actual exporting of files",
items=(
("DISABLED", "Disabled","Run exports normally (no Dry run)"),
("NO_EXPORT", "No export", "do not actually export gltf files"),
("NO_PREPARE", "No prepare", "do not actually export gltf files AND do not prepare the exports either (ie no creating fake scenes etc)"),
)
),
default="DISABLED"
) # type: ignore
# special property for gltf settings