feat(auto_export): experimenting with the insane workarounds needed to get access to standard gltf exporter settings

* got a basic working version that runs the standard exporter with some overrides,
deletes the temporary exported gltf file, extracts the scene level settings etc
 * convoluted as hell , but still better than the alternatives
This commit is contained in:
kaosat.dev 2024-04-01 16:12:05 +02:00
parent 66df7fae99
commit 66a893e5b6
2 changed files with 209 additions and 2 deletions

View File

@ -11,6 +11,8 @@ bl_info = {
"category": "Import-Export" "category": "Import-Export"
} }
import bpy import bpy
from bpy.types import Context
from bpy.props import (StringProperty, BoolProperty, PointerProperty)
from .auto_export.operators import AutoExportGLTF from .auto_export.operators import AutoExportGLTF
from .auto_export.tracker import AutoExportTracker from .auto_export.tracker import AutoExportTracker
@ -39,6 +41,94 @@ from .ui.operators import (SCENES_LIST_OT_actions)
This is a workaround needed because of the way the settings are stored , perhaps there is a better way to deal with it ? ie by calling the AutoExportGLTF operator from the auto_export function ? This is a workaround needed because of the way the settings are stored , perhaps there is a better way to deal with it ? ie by calling the AutoExportGLTF operator from the auto_export function ?
""" """
from io_scene_gltf2 import (GLTF_PT_export_main, GLTF_PT_export_include)
class Testing_PT_MainPanel(bpy.types.Panel):
bl_idname = "Testing_PT_MainPanel"
bl_label = ""
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Gltf auto_export"
bl_context = "objectmode"
def draw_header(self, context):
layout = self.layout
name = context.object.name if context.object != None else ''
layout.label(text="Gltf auto export ")
def draw(self, context):
layout = self.layout
object = context.object
collection = context.collection
layout.label(text="MAKE SURE TO CLICK ON 'REMEMBER EXPORT SETTINGS' !!")
op = layout.operator("EXPORT_SCENE_OT_gltf", text='Gltf settings')#'glTF 2.0 (.glb/.gltf)')
#op.export_format = 'GLTF_SEPARATE'
op.use_selection=True
op.will_save_settings=True
op.use_visible=True # Export visible and hidden objects. See Object/Batch Export to skip.
op.use_renderable=True
op.use_active_collection = True
op.use_active_collection_with_nested=True
op.use_active_scene = True
op.filepath="dummy"
#print("GLTF_PT_export_main", GLTF_PT_export_main.bl_parent_id)
# wrapper operator
"""class WrapperOperator(bpy.types.Operator):
bl_idname = "node.delete"
bl_label = "Delete"
@classmethod
def poll(cls, context):
return True
def execute(self, context):
# unregister wrapper replacement operator
bpy.utils.unregister_class(DeleteOperator)
# call original native operator
bpy.ops.node.delete()
# register back the wrapper
bpy.utils.register_class(DeleteOperator)
return {'FINISHED'}"""
class GLTF_PT_export_main2(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = ""
bl_parent_id = "Testing_PT_MainPanel"
bl_options = {'HIDE_HEADER'}
'''@classmethod
def poll(cls, context):
sfile = context.space_data
operator = sfile.active_operator
return operator.bl_idname == "EXPORT_SCENE_OT_gltf"'''
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
"""sfile = context.space_data
operator = sfile.active_operator
layout.prop(operator, 'export_format')
if operator.export_format == 'GLTF_SEPARATE':
layout.prop(operator, 'export_keep_originals')
if operator.export_keep_originals is False:
layout.prop(operator, 'export_texture_dir', icon='FILE_FOLDER')
if operator.export_format == 'GLTF_EMBEDDED':
layout.label(text="This is the least efficient of the available forms, and should only be used when required.", icon='ERROR')
layout.prop(operator, 'export_copyright')
layout.prop(operator, 'will_save_settings')"""
#see here for original gltf exporter infos https://github.com/KhronosGroup/glTF-Blender-IO/blob/main/addons/io_scene_gltf2/__init__.py #see here for original gltf exporter infos https://github.com/KhronosGroup/glTF-Blender-IO/blob/main/addons/io_scene_gltf2/__init__.py
classes = [ classes = [
@ -60,7 +150,11 @@ classes = [
GLTF_PT_auto_export_collections_list, GLTF_PT_auto_export_collections_list,
GLTF_PT_auto_export_gltf, GLTF_PT_auto_export_gltf,
AutoExportTracker AutoExportTracker,
Testing_PT_MainPanel,
GLTF_PT_export_main2,
] ]
def menu_func_import(self, context): def menu_func_import(self, context):
@ -76,6 +170,8 @@ def post_save(scene, depsgraph):
bpy.context.window_manager.auto_export_tracker.save_handler( scene, depsgraph) bpy.context.window_manager.auto_export_tracker.save_handler( scene, depsgraph)
def register(): def register():
for cls in classes: for cls in classes:
bpy.utils.register_class(cls) bpy.utils.register_class(cls)
@ -86,6 +182,18 @@ def register():
# add our addon to the toolbar # add our addon to the toolbar
bpy.types.TOPBAR_MT_file_export.append(menu_func_import) bpy.types.TOPBAR_MT_file_export.append(menu_func_import)
bpy.types.WindowManager.was_good_operator = BoolProperty(default=False)
bpy.types.Scene.was_good_operator = BoolProperty(default=False)
#GLTF_PT_export_main.bl_parent_id = "Testing_PT_MainPanel"
#GLTF_PT_export_include.bl_parent_id = "Testing_PT_MainPanel"
"""try:
bpy.app.timers.unregister(watch_schema)
except Exception as error:
print("failed to unregister", error)
pass"""
def unregister(): def unregister():
for cls in classes: for cls in classes:
bpy.utils.unregister_class(cls) bpy.utils.unregister_class(cls)
@ -94,6 +202,8 @@ def unregister():
bpy.app.handlers.depsgraph_update_post.remove(post_update) bpy.app.handlers.depsgraph_update_post.remove(post_update)
bpy.app.handlers.save_post.remove(post_save) bpy.app.handlers.save_post.remove(post_save)
if "gltf_auto_export" == "__main__": if "gltf_auto_export" == "__main__":
register() register()

View File

@ -47,11 +47,103 @@ class AutoExportTracker(PropertyGroup):
# all our logic is done, mark this as done # all our logic is done, mark this as done
print("EXPORT DONE") print("EXPORT DONE")
@classmethod
def gltf_exporter_handler(cls):
# FOr some reason, the active operator here is always None, so using a workaround
# active_operator = bpy.context.active_operator
print("here", bpy.context.window_manager.was_good_operator)
if bpy.context.window_manager.was_good_operator:
dummy_file_path = "/home/ckaos/projects/bevy/Blender_bevy_components_worklflow/testing/bevy_example/assets/dummy.glb"
import os
if os.path.exists(dummy_file_path):
print("dummy file exists, assuming it worked")
os.unlink(dummy_file_path)
# get the parameters
scene = bpy.context.scene
print("scene", scene["glTF2ExportSettings"])
if "glTF2ExportSettings" in scene:
settings = scene["glTF2ExportSettings"]
print("gltf settings", dict(settings))
# now reset the original gltf_settings
if getattr(cls, "existing_gltf_settings", None) != None:
print("resetting original gltf settings")
scene["glTF2ExportSettings"] = cls.existing_gltf_settings
else:
print("no pre_existing settings")
if "glTF2ExportSettings" in scene:
del scene["glTF2ExportSettings"]
cls.existing_gltf_settings = None
bpy.context.window_manager.was_good_operator = False
return None
else:
try:
bpy.app.timers.unregister(cls.gltf_exporter_handler)
except:pass
return None
return 1
@classmethod @classmethod
def deps_update_handler(cls, scene, depsgraph): def deps_update_handler(cls, scene, depsgraph):
# print("change detection enabled", cls.change_detection_enabled) # print("change detection enabled", cls.change_detection_enabled)
active_operator = bpy.context.active_operator
if active_operator:
#print("Operator", active_operator.bl_label, active_operator.bl_idname)
if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and not bpy.context.window_manager.was_good_operator:
try:
bpy.app.timers.unregister(cls.gltf_exporter_handler)
except:pass
bpy.app.timers.register(cls.gltf_exporter_handler, first_interval=3)
# we force saving params
active_operator.will_save_settings = True
# we backup any existing gltf export settings, if there where any
scene = bpy.context.scene
if "glTF2ExportSettings" in scene:
existing_setting = scene["glTF2ExportSettings"]
cls.existing_gltf_settings = existing_setting
bpy.context.window_manager.was_good_operator = True
else:
if bpy.context.window_manager.was_good_operator:
bpy.context.window_manager.was_good_operator = False
"""if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf":
scene = bpy.context.scene
if "glTF2ExportSettings" in scene:
existing_setting = scene["glTF2ExportSettings"]
cls.existing_gltf_settings = existing_setting
print("we just executed the correct operator")
active_operator.will_save_settings = True
else:
import os
dummy_file_path = "/home/ckaos/projects/bevy/Blender_bevy_components_worklflow/testing/bevy_example/assets/dummy.glb"
if os.path.exists(dummy_file_path):
print("dummy file exists")
os.unlink(dummy_file_path)
# get the parameters
scene = bpy.context.scene
settings = scene["glTF2ExportSettings"]
print("gltf settings", dict(settings))
# now reset the original gltf_settings
if hasattr(cls, "existing_gltf_settings"):
print("resetting original gltf settings")
scene["glTF2ExportSettings"] = cls.existing_gltf_settings
else:
del scene["glTF2ExportSettings"]"""
if scene.name != "temp_scene": if scene.name != "temp_scene":
#print("depsgraph_update_post", scene.name) # print("depsgraph_update_post", scene.name)
changed_scene = scene.name or "" changed_scene = scene.name or ""
# only deal with changes if we are no in the mids of saving/exporting # only deal with changes if we are no in the mids of saving/exporting
@ -62,6 +154,7 @@ class AutoExportTracker(PropertyGroup):
# depsgraph = bpy.context.evaluated_depsgraph_get() # depsgraph = bpy.context.evaluated_depsgraph_get()
for obj in depsgraph.updates: for obj in depsgraph.updates:
print("depsgraph update", obj)
if isinstance(obj.id, bpy.types.Object): if isinstance(obj.id, bpy.types.Object):
# get the actual object # get the actual object
object = bpy.data.objects[obj.id.name] object = bpy.data.objects[obj.id.name]
@ -85,6 +178,10 @@ class AutoExportTracker(PropertyGroup):
else: else:
cls.changed_objects_per_scene.clear() cls.changed_objects_per_scene.clear()
depsgraph = bpy.context.evaluated_depsgraph_get()
for update in depsgraph.updates:
print("update", update)
def disable_change_detection(self,): def disable_change_detection(self,):
self.change_detection_enabled = False self.change_detection_enabled = False
self.__class__.change_detection_enabled = False self.__class__.change_detection_enabled = False