Blender_bevy_components_wor.../tools/gltf_auto_export/helpers_export.py

197 lines
9.2 KiB
Python

import os
import bpy
from .preferences import (AutoExportGltfPreferenceNames)
from .helpers_scenes import (generate_hollow_scene, clear_hollow_scene)
from .helpers_collections import (recurLayerCollection)
from .blueprints import clear_blueprint_hollow_scene, generate_blueprint_hollow_scene
from .helpers import (traverse_tree)
from .dynamic import (is_object_dynamic, is_object_static)
######################################################
#### Export logic #####
def generate_gltf_export_preferences(addon_prefs):
# default values
gltf_export_preferences = dict(
export_format= 'GLB', #'GLB', 'GLTF_SEPARATE', 'GLTF_EMBEDDED'
check_existing=False,
use_selection=False,
use_visible=True, # Export visible and hidden objects. See Object/Batch Export to skip.
use_renderable=False,
use_active_collection= False,
use_active_collection_with_nested=False,
use_active_scene = False,
export_texcoords=True,
export_normals=True,
# here add draco settings
export_draco_mesh_compression_enable = False,
export_tangents=False,
#export_materials
export_colors=True,
export_attributes=True,
#use_mesh_edges
#use_mesh_vertices
export_cameras=True,
export_extras=True, # For custom exported properties.
export_lights=True,
export_yup=True,
export_skins=True,
export_morph=False,
export_apply=False,
export_animations=False
)
for key in addon_prefs.__annotations__.keys():
if str(key) not in AutoExportGltfPreferenceNames:
#print("overriding setting", key, "value", getattr(addon_prefs,key))
gltf_export_preferences[key] = getattr(addon_prefs,key)
return gltf_export_preferences
# find which of the library scenes the given collection stems from
# TODO: does not seem efficient at all ?
def get_source_scene(collection_name, library_scenes):
match = None
for scene in library_scenes:
root_collection = scene.collection
found = False
for cur_collection in traverse_tree(root_collection):
if cur_collection.name == collection_name:
found = True
break
if found:
match = scene
break
return match
# export collections: all the collections that have an instance in the main scene AND any marked collections, even if they do not have instances
def export_collections(collections, folder_path, library_scene, addon_prefs, gltf_export_preferences, blueprint_hierarchy, library_collections):
# set active scene to be the library scene (hack for now)
bpy.context.window.scene = library_scene
# save current active collection
active_collection = bpy.context.view_layer.active_layer_collection
export_materials_library = getattr(addon_prefs,"export_materials_library")
for collection_name in collections:
print("exporting collection", collection_name)
layer_collection = bpy.context.view_layer.layer_collection
layerColl = recurLayerCollection(layer_collection, collection_name)
# set active collection to the collection
bpy.context.view_layer.active_layer_collection = layerColl
gltf_output_path = os.path.join(folder_path, collection_name)
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'
#if relevant we replace sub collections instances with placeholders too
# this is not needed if a collection/blueprint does not have sub blueprints or sub collections
collection_in_blueprint_hierarchy = collection_name in blueprint_hierarchy and len(blueprint_hierarchy[collection_name]) > 0
collection_has_child_collections = len(bpy.data.collections[collection_name].children) > 0
if collection_in_blueprint_hierarchy or collection_has_child_collections:
#print("generate hollow scene for nested blueprints", library_collections)
backup = bpy.context.window.scene
collection = bpy.data.collections[collection_name]
(hollow_scene, temporary_collections, root_objects, special_properties) = generate_blueprint_hollow_scene(collection, library_collections, addon_prefs)
export_gltf(gltf_output_path, export_settings)
clear_blueprint_hollow_scene(hollow_scene, collection, temporary_collections, root_objects, special_properties)
bpy.context.window.scene = backup
else:
#print("standard export")
export_gltf(gltf_output_path, export_settings)
# reset active collection to the one we save before
bpy.context.view_layer.active_layer_collection = active_collection
def export_blueprints_from_collections(collections, library_scene, folder_path, addon_prefs, blueprint_hierarchy, library_collections):
export_output_folder = getattr(addon_prefs,"export_output_folder")
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
export_blueprints_path = os.path.join(folder_path, export_output_folder, getattr(addon_prefs,"export_blueprints_path")) if getattr(addon_prefs,"export_blueprints_path") != '' else folder_path
#print("-----EXPORTING BLUEPRINTS----")
#print("LIBRARY EXPORT", export_blueprints_path )
try:
export_collections(collections, export_blueprints_path, library_scene, addon_prefs, gltf_export_preferences, blueprint_hierarchy, library_collections)
except Exception as error:
print("failed to export collections to gltf: ", error)
# TODO : rethrow
# export all main scenes
def export_main_scenes(scenes, folder_path, addon_prefs):
for scene in scenes:
export_main_scene(scene, folder_path, addon_prefs)
def export_main_scene(scene, folder_path, addon_prefs, library_collections):
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
export_output_folder = getattr(addon_prefs,"export_output_folder")
export_blueprints = getattr(addon_prefs,"export_blueprints")
export_separate_dynamic_and_static_objects = getattr(addon_prefs, "export_separate_dynamic_and_static_objects")
gltf_output_path = os.path.join(folder_path, export_output_folder, scene.name)
export_settings = { **gltf_export_preferences,
'use_active_scene': True,
'use_active_collection':True,
'use_active_collection_with_nested':True,
'use_visible': False,
'use_renderable': False,
'export_apply':True
}
if export_blueprints :
if export_separate_dynamic_and_static_objects:
# first export all dynamic objects
(hollow_scene, temporary_collections, root_objects, special_properties) = generate_hollow_scene(scene, library_collections, addon_prefs, is_object_dynamic)
gltf_output_path = os.path.join(folder_path, export_output_folder, scene.name+ "_dynamic")
# set active scene to be the given scene
bpy.context.window.scene = hollow_scene
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
export_gltf(gltf_output_path, export_settings)
clear_hollow_scene(hollow_scene, scene, temporary_collections, root_objects, special_properties)
# now export static objects
(hollow_scene, temporary_collections, root_objects, special_properties) = generate_hollow_scene(scene, library_collections, addon_prefs, is_object_static)
gltf_output_path = os.path.join(folder_path, export_output_folder, scene.name)
# set active scene to be the given scene
bpy.context.window.scene = hollow_scene
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
export_gltf(gltf_output_path, export_settings)
clear_hollow_scene(hollow_scene, scene, temporary_collections, root_objects, special_properties)
else:
print("NO SPLIT")
# todo: add exception handling
(hollow_scene, temporary_collections, root_objects, special_properties) = generate_hollow_scene(scene, library_collections, addon_prefs)
# set active scene to be the given scene
bpy.context.window.scene = hollow_scene
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
export_gltf(gltf_output_path, export_settings)
clear_hollow_scene(hollow_scene, scene, temporary_collections, root_objects, special_properties)
else:
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
export_gltf(gltf_output_path, export_settings)
#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}
os.makedirs(os.path.dirname(path), exist_ok=True)
bpy.ops.export_scene.gltf(**settings)