mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-27 05:46:59 +00:00
Compare commits
No commits in common. "c2dc0324c3b424ce109f5b5802e5348c4ac55a0f" and "8683a6482fb19f64035ea6f2324c60c19bafb8e5" have entirely different histories.
c2dc0324c3
...
8683a6482f
@ -1,6 +0,0 @@
|
|||||||
import rna_prop_ui
|
|
||||||
|
|
||||||
# fake way to make our operator's changes be visible to the change/depsgraph update handler in gltf_auto_export
|
|
||||||
def ping_depsgraph_update(object):
|
|
||||||
rna_prop_ui.rna_idprop_ui_create(object, "________temp", default=0)
|
|
||||||
rna_prop_ui.rna_idprop_ui_prop_clear(object, "________temp")
|
|
@ -1,8 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.props import (StringProperty, BoolProperty, PointerProperty)
|
from bpy.props import (StringProperty, BoolProperty, PointerProperty)
|
||||||
from bpy_types import (PropertyGroup)
|
from bpy_types import (PropertyGroup)
|
||||||
|
|
||||||
from .helpers import ping_depsgraph_update
|
|
||||||
from ..propGroups.conversions_from_prop_group import property_group_value_to_custom_property_value
|
from ..propGroups.conversions_from_prop_group import property_group_value_to_custom_property_value
|
||||||
from ..propGroups.conversions_to_prop_group import property_group_value_from_custom_property_value
|
from ..propGroups.conversions_to_prop_group import property_group_value_from_custom_property_value
|
||||||
|
|
||||||
@ -130,8 +128,6 @@ def add_metadata_to_components_without_metadata(object):
|
|||||||
continue
|
continue
|
||||||
upsert_component_in_object(object, component_name, registry)
|
upsert_component_in_object(object, component_name, registry)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# adds a component to an object (including metadata) using the provided component definition & optional value
|
# adds a component to an object (including metadata) using the provided component definition & optional value
|
||||||
def add_component_to_object(object, component_definition, value=None):
|
def add_component_to_object(object, component_definition, value=None):
|
||||||
cleanup_invalid_metadata(object)
|
cleanup_invalid_metadata(object)
|
||||||
@ -153,8 +149,6 @@ def add_component_to_object(object, component_definition, value=None):
|
|||||||
del object["__disable__update"]
|
del object["__disable__update"]
|
||||||
|
|
||||||
object[short_name] = value
|
object[short_name] = value
|
||||||
ping_depsgraph_update(object)
|
|
||||||
|
|
||||||
|
|
||||||
def upsert_component_in_object(object, component_name, registry):
|
def upsert_component_in_object(object, component_name, registry):
|
||||||
# print("upsert_component_in_object", object, "component name", component_name)
|
# print("upsert_component_in_object", object, "component name", component_name)
|
||||||
@ -229,8 +223,6 @@ def copy_propertyGroup_values_to_another_object(source_object, target_object, co
|
|||||||
if field_name in source_propertyGroup:
|
if field_name in source_propertyGroup:
|
||||||
target_propertyGroup[field_name] = source_propertyGroup[field_name]
|
target_propertyGroup[field_name] = source_propertyGroup[field_name]
|
||||||
apply_propertyGroup_values_to_object_customProperties(target_object)
|
apply_propertyGroup_values_to_object_customProperties(target_object)
|
||||||
ping_depsgraph_update(object)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: move to propgroups ?
|
# TODO: move to propgroups ?
|
||||||
def apply_propertyGroup_values_to_object_customProperties(object):
|
def apply_propertyGroup_values_to_object_customProperties(object):
|
||||||
@ -303,16 +295,6 @@ def remove_component_from_object(object, component_name):
|
|||||||
break
|
break
|
||||||
for index in to_remove:
|
for index in to_remove:
|
||||||
components_metadata.remove(index)
|
components_metadata.remove(index)
|
||||||
ping_depsgraph_update(object)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_component_from_custom_property(object):
|
|
||||||
add_metadata_to_components_without_metadata(object)
|
|
||||||
apply_customProperty_values_to_object_propertyGroups(object)
|
|
||||||
ping_depsgraph_update(object)
|
|
||||||
|
|
||||||
def toggle_component(object, component_name):
|
|
||||||
components_in_object = object.components_meta.components
|
|
||||||
component_meta = next(filter(lambda component: component["name"] == component_name, components_in_object), None)
|
|
||||||
if component_meta != None:
|
|
||||||
component_meta.visible = not component_meta.visible
|
|
||||||
|
@ -3,13 +3,12 @@ import json
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy_types import Operator
|
from bpy_types import Operator
|
||||||
from bpy.props import (StringProperty)
|
from bpy.props import (StringProperty)
|
||||||
|
from .metadata import add_component_to_object, add_metadata_to_components_without_metadata, apply_customProperty_values_to_object_propertyGroups, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, find_component_definition_from_short_name, remove_component_from_object
|
||||||
from .metadata import add_component_from_custom_property, add_component_to_object, add_metadata_to_components_without_metadata, apply_customProperty_values_to_object_propertyGroups, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, find_component_definition_from_short_name, remove_component_from_object, toggle_component
|
|
||||||
|
|
||||||
class AddComponentOperator(Operator):
|
class AddComponentOperator(Operator):
|
||||||
"""Add Bevy component to object"""
|
"""Add component to blueprint"""
|
||||||
bl_idname = "object.add_bevy_component"
|
bl_idname = "object.add_bevy_component"
|
||||||
bl_label = "Add component to object Operator"
|
bl_label = "Add component to blueprint Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
component_type: StringProperty(
|
component_type: StringProperty(
|
||||||
@ -30,7 +29,7 @@ class AddComponentOperator(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class CopyComponentOperator(Operator):
|
class CopyComponentOperator(Operator):
|
||||||
"""Copy Bevy component from object"""
|
"""Copy component from blueprint"""
|
||||||
bl_idname = "object.copy_bevy_component"
|
bl_idname = "object.copy_bevy_component"
|
||||||
bl_label = "Copy component Operator"
|
bl_label = "Copy component Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -67,9 +66,9 @@ class CopyComponentOperator(Operator):
|
|||||||
|
|
||||||
|
|
||||||
class PasteComponentOperator(Operator):
|
class PasteComponentOperator(Operator):
|
||||||
"""Paste Bevy component to object"""
|
"""Paste component to blueprint"""
|
||||||
bl_idname = "object.paste_bevy_component"
|
bl_idname = "object.paste_bevy_component"
|
||||||
bl_label = "Paste component to object Operator"
|
bl_label = "Paste component to blueprint Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -92,7 +91,7 @@ class PasteComponentOperator(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class RemoveComponentOperator(Operator):
|
class RemoveComponentOperator(Operator):
|
||||||
"""Remove Bevy component from object"""
|
"""Remove component from object"""
|
||||||
bl_idname = "object.remove_bevy_component"
|
bl_idname = "object.remove_bevy_component"
|
||||||
bl_label = "Remove component from object Operator"
|
bl_label = "Remove component from object Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -118,11 +117,12 @@ class RemoveComponentOperator(Operator):
|
|||||||
remove_component_from_object(object, self.component_name)
|
remove_component_from_object(object, self.component_name)
|
||||||
else:
|
else:
|
||||||
self.report({"ERROR"}, "The object/ component to remove ("+ self.component_name +") does not exist")
|
self.report({"ERROR"}, "The object/ component to remove ("+ self.component_name +") does not exist")
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class RemoveComponentFromAllObjectsOperator(Operator):
|
class RemoveComponentFromAllObjectsOperator(Operator):
|
||||||
"""Remove Bevy component from all object"""
|
"""Remove component from all object"""
|
||||||
bl_idname = "object.remove_bevy_component_all"
|
bl_idname = "object.remove_bevy_component_all"
|
||||||
bl_label = "Remove component from all objects Operator"
|
bl_label = "Remove component from all objects Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -172,7 +172,7 @@ class RenameHelper(bpy.types.PropertyGroup):
|
|||||||
del bpy.types.WindowManager.bevy_component_rename_helper
|
del bpy.types.WindowManager.bevy_component_rename_helper
|
||||||
|
|
||||||
class OT_rename_component(Operator):
|
class OT_rename_component(Operator):
|
||||||
"""Rename Bevy component"""
|
"""Rename component"""
|
||||||
bl_idname = "object.rename_bevy_component"
|
bl_idname = "object.rename_bevy_component"
|
||||||
bl_label = "rename component"
|
bl_label = "rename component"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -270,7 +270,7 @@ class OT_rename_component(Operator):
|
|||||||
|
|
||||||
|
|
||||||
class GenerateComponent_From_custom_property_Operator(Operator):
|
class GenerateComponent_From_custom_property_Operator(Operator):
|
||||||
"""Generate Bevy components from custom property"""
|
"""generate components from custom property"""
|
||||||
bl_idname = "object.generate_bevy_component_from_custom_property"
|
bl_idname = "object.generate_bevy_component_from_custom_property"
|
||||||
bl_label = "Generate component from custom_property Operator"
|
bl_label = "Generate component from custom_property Operator"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -285,7 +285,8 @@ class GenerateComponent_From_custom_property_Operator(Operator):
|
|||||||
|
|
||||||
error = False
|
error = False
|
||||||
try:
|
try:
|
||||||
add_component_from_custom_property(object)
|
add_metadata_to_components_without_metadata(object)
|
||||||
|
apply_customProperty_values_to_object_propertyGroups(object)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
|
||||||
error = True
|
error = True
|
||||||
@ -296,7 +297,7 @@ class GenerateComponent_From_custom_property_Operator(Operator):
|
|||||||
|
|
||||||
|
|
||||||
class Fix_Component_Operator(Operator):
|
class Fix_Component_Operator(Operator):
|
||||||
"""Attempt to fix Bevy component"""
|
"""attempt to fix component"""
|
||||||
bl_idname = "object.fix_bevy_component"
|
bl_idname = "object.fix_bevy_component"
|
||||||
bl_label = "Fix component (attempts to)"
|
bl_label = "Fix component (attempts to)"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -321,7 +322,7 @@ class Fix_Component_Operator(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class Toggle_ComponentVisibility(Operator):
|
class Toggle_ComponentVisibility(Operator):
|
||||||
"""Toggle Bevy component's visibility"""
|
"""toggles components visibility"""
|
||||||
bl_idname = "object.toggle_bevy_component_visibility"
|
bl_idname = "object.toggle_bevy_component_visibility"
|
||||||
bl_label = "Toggle component visibility"
|
bl_label = "Toggle component visibility"
|
||||||
bl_options = {"UNDO"}
|
bl_options = {"UNDO"}
|
||||||
@ -333,6 +334,10 @@ class Toggle_ComponentVisibility(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
object = context.object
|
object = context.object
|
||||||
toggle_component(object, self.component_name)
|
components_in_object = object.components_meta.components
|
||||||
|
component_meta = next(filter(lambda component: component["name"] == self.component_name, components_in_object), None)
|
||||||
|
if component_meta != None:
|
||||||
|
component_meta.visible = not component_meta.visible
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import json
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Context
|
from bpy.types import Context
|
||||||
from bpy.props import (StringProperty, BoolProperty, IntProperty, PointerProperty)
|
from bpy.props import (StringProperty, BoolProperty, IntProperty, PointerProperty)
|
||||||
import rna_prop_ui
|
|
||||||
|
|
||||||
# from .extension import ExampleExtensionProperties, GLTF_PT_UserExtensionPanel, unregister_panel
|
# from .extension import ExampleExtensionProperties, GLTF_PT_UserExtensionPanel, unregister_panel
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ from .auto_export.internals import (SceneLink,
|
|||||||
CollectionsToExport,
|
CollectionsToExport,
|
||||||
CUSTOM_PG_sceneName
|
CUSTOM_PG_sceneName
|
||||||
)
|
)
|
||||||
from .ui.main import (GLTF_PT_auto_export_changes_list, GLTF_PT_auto_export_main,
|
from .ui.main import (GLTF_PT_auto_export_main,
|
||||||
GLTF_PT_auto_export_root,
|
GLTF_PT_auto_export_root,
|
||||||
GLTF_PT_auto_export_general,
|
GLTF_PT_auto_export_general,
|
||||||
GLTF_PT_auto_export_scenes,
|
GLTF_PT_auto_export_scenes,
|
||||||
@ -113,9 +112,8 @@ classes = [
|
|||||||
GLTF_PT_auto_export_general,
|
GLTF_PT_auto_export_general,
|
||||||
GLTF_PT_auto_export_scenes,
|
GLTF_PT_auto_export_scenes,
|
||||||
GLTF_PT_auto_export_blueprints,
|
GLTF_PT_auto_export_blueprints,
|
||||||
GLTF_PT_auto_export_SidePanel,
|
|
||||||
GLTF_PT_auto_export_collections_list,
|
GLTF_PT_auto_export_collections_list,
|
||||||
GLTF_PT_auto_export_changes_list,
|
GLTF_PT_auto_export_SidePanel,
|
||||||
|
|
||||||
AutoExportTracker,
|
AutoExportTracker,
|
||||||
]
|
]
|
||||||
@ -195,7 +193,6 @@ def register():
|
|||||||
"""bpy.utils.register_class(AutoExportExtensionProperties)
|
"""bpy.utils.register_class(AutoExportExtensionProperties)
|
||||||
bpy.types.Scene.AutoExportExtensionProperties = bpy.props.PointerProperty(type=AutoExportExtensionProperties)"""
|
bpy.types.Scene.AutoExportExtensionProperties = bpy.props.PointerProperty(type=AutoExportExtensionProperties)"""
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
@ -3,12 +3,12 @@ import os
|
|||||||
import bpy
|
import bpy
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from .get_collections_to_export import get_collections_to_export
|
|
||||||
|
|
||||||
from .export_main_scenes import export_main_scene
|
from .export_main_scenes import export_main_scene
|
||||||
from .export_blueprints import check_if_blueprint_on_disk, check_if_blueprints_exist, export_blueprints_from_collections
|
from .export_blueprints import check_if_blueprint_on_disk, check_if_blueprints_exist, export_blueprints_from_collections
|
||||||
|
from .get_standard_exporter_settings import get_standard_exporter_settings
|
||||||
|
|
||||||
from ..helpers.helpers_scenes import (get_scenes, )
|
from ..helpers.helpers_scenes import (get_scenes, )
|
||||||
|
from ..helpers.helpers_collections import (get_collections_in_library, get_exportable_collections, get_collections_per_scene, find_collection_ascendant_target_collection)
|
||||||
from ..modules.export_materials import cleanup_materials, export_materials
|
from ..modules.export_materials import cleanup_materials, export_materials
|
||||||
from ..modules.bevy_scene_components import upsert_scene_components
|
from ..modules.bevy_scene_components import upsert_scene_components
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
print ("changed_export_parameters", changed_export_parameters)
|
print ("changed_export_parameters", changed_export_parameters)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# path to the current blend file
|
|
||||||
file_path = bpy.data.filepath
|
file_path = bpy.data.filepath
|
||||||
# Get the folder
|
# Get the folder
|
||||||
folder_path = os.path.dirname(file_path)
|
folder_path = os.path.dirname(file_path)
|
||||||
@ -35,6 +34,10 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
|
|
||||||
[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_scenes(addon_prefs)
|
||||||
|
|
||||||
|
# standard gltf export settings are stored differently
|
||||||
|
|
||||||
|
standard_gltf_exporter_settings = get_standard_exporter_settings()
|
||||||
|
|
||||||
print("main scenes", main_scene_names, "library_scenes", library_scene_names)
|
print("main scenes", main_scene_names, "library_scenes", library_scene_names)
|
||||||
print("export_output_folder", export_output_folder)
|
print("export_output_folder", export_output_folder)
|
||||||
|
|
||||||
@ -50,13 +53,81 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
if export_blueprints:
|
if export_blueprints:
|
||||||
print("EXPORTING")
|
print("EXPORTING")
|
||||||
# create parent relations for all collections
|
# create parent relations for all collections
|
||||||
(collections, collections_to_export, main_scenes_to_export, library_collections, collections_per_scene, blueprint_hierarchy, export_levels_path, gltf_extension) = get_collections_to_export(folder_path, export_output_folder, changes_per_scene, changed_export_parameters, addon_prefs)
|
collection_parents = dict()
|
||||||
|
for collection in bpy.data.collections:
|
||||||
|
collection_parents[collection.name] = None
|
||||||
|
for collection in bpy.data.collections:
|
||||||
|
for ch in collection.children:
|
||||||
|
collection_parents[ch.name] = collection.name
|
||||||
|
|
||||||
|
# get a list of all collections actually in use
|
||||||
|
(collections, blueprint_hierarchy) = get_exportable_collections(level_scenes, library_scenes, addon_prefs)
|
||||||
|
|
||||||
|
# first check if all collections have already been exported before (if this is the first time the exporter is run
|
||||||
|
# in your current Blender session for example)
|
||||||
|
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
|
||||||
|
export_levels_path = os.path.join(folder_path, export_output_folder)
|
||||||
|
|
||||||
|
|
||||||
|
gltf_extension = standard_gltf_exporter_settings.get("export_format", 'GLB')
|
||||||
|
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
|
||||||
|
collections_not_on_disk = check_if_blueprints_exist(collections, export_blueprints_path, gltf_extension)
|
||||||
|
changed_collections = []
|
||||||
|
|
||||||
|
for scene, objects in changes_per_scene.items():
|
||||||
|
print(" changed scene", scene)
|
||||||
|
for obj_name, obj in objects.items():
|
||||||
|
object_collections = list(obj.users_collection) if hasattr(obj, 'users_collection') else []
|
||||||
|
object_collection_names = list(map(lambda collection: collection.name, object_collections))
|
||||||
|
|
||||||
|
if len(object_collection_names) > 1:
|
||||||
|
print("ERRROR for",obj_name,"objects in multiple collections not supported")
|
||||||
|
else:
|
||||||
|
object_collection_name = object_collection_names[0] if len(object_collection_names) > 0 else None
|
||||||
|
#recurse updwards until we find one of our collections (or not)
|
||||||
|
matching_collection = find_collection_ascendant_target_collection(collection_parents, collections, object_collection_name)
|
||||||
|
if matching_collection is not None:
|
||||||
|
changed_collections.append(matching_collection)
|
||||||
|
|
||||||
|
collections_to_export = list(set(changed_collections + collections_not_on_disk)) if export_change_detection else collections
|
||||||
|
|
||||||
|
# we need to re_export everything if the export parameters have been changed
|
||||||
|
collections_to_export = collections if changed_export_parameters else collections_to_export
|
||||||
|
collections_per_scene = get_collections_per_scene(collections_to_export, library_scenes)
|
||||||
|
|
||||||
|
|
||||||
|
# collections that do not come from a library should not be exported as seperate blueprints
|
||||||
|
# FIMXE: logic is erroneous, needs to be changed
|
||||||
|
library_collections = get_collections_in_library(library_scenes)
|
||||||
|
collections_to_export = list(set(collections_to_export).intersection(set(library_collections)))
|
||||||
|
|
||||||
# since materials export adds components we need to call this before blueprints are exported
|
# since materials export adds components we need to call this before blueprints are exported
|
||||||
# export materials & inject materials components into relevant objects
|
# export materials & inject materials components into relevant objects
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
export_materials(collections, library_scenes, folder_path, addon_prefs)
|
export_materials(collections, library_scenes, folder_path, addon_prefs)
|
||||||
|
|
||||||
|
|
||||||
|
main_scenes_to_export = [scene_name for scene_name in main_scene_names if not export_change_detection or changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)]
|
||||||
|
|
||||||
|
bpy.context.window_manager.auto_export_tracker.exports_count = len(collections_to_export)
|
||||||
|
bpy.context.window_manager.auto_export_tracker.exports_count += len(main_scenes_to_export)
|
||||||
|
if export_materials_library:
|
||||||
|
bpy.context.window_manager.auto_export_tracker.exports_count += 1
|
||||||
|
|
||||||
|
print("-------------------------------")
|
||||||
|
print("collections: all:", collections)
|
||||||
|
print("collections: changed:", changed_collections)
|
||||||
|
print("collections: not found on disk:", collections_not_on_disk)
|
||||||
|
print("collections: in library:", library_collections)
|
||||||
|
print("collections: to export:", collections_to_export)
|
||||||
|
print("collections: per_scene:", collections_per_scene)
|
||||||
|
print("-------------------------------")
|
||||||
|
print("BLUEPRINTS: to export:", collections_to_export)
|
||||||
|
print("-------------------------------")
|
||||||
|
print("MAIN SCENES: to export:", main_scenes_to_export)
|
||||||
|
print("-------------------------------")
|
||||||
|
|
||||||
|
|
||||||
# backup current active scene
|
# backup current active scene
|
||||||
old_current_scene = bpy.context.scene
|
old_current_scene = bpy.context.scene
|
||||||
# backup current selections
|
# backup current selections
|
||||||
@ -97,6 +168,8 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
for scene_name in main_scene_names:
|
for scene_name in main_scene_names:
|
||||||
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, [])
|
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, [])
|
||||||
|
|
||||||
|
print("we are done with all export work",bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
import os
|
|
||||||
import bpy
|
|
||||||
|
|
||||||
from .get_standard_exporter_settings import get_standard_exporter_settings
|
|
||||||
from .export_blueprints import check_if_blueprint_on_disk, check_if_blueprints_exist, export_blueprints_from_collections
|
|
||||||
from ..helpers.helpers_collections import get_exportable_collections
|
|
||||||
from ..helpers.helpers_collections import (get_collections_in_library, get_exportable_collections, get_collections_per_scene, find_collection_ascendant_target_collection)
|
|
||||||
from ..helpers.helpers_scenes import (get_scenes, )
|
|
||||||
|
|
||||||
def get_collections_to_export(folder_path, export_output_folder, changes_per_scene, changed_export_parameters, addon_prefs):
|
|
||||||
export_change_detection = getattr(addon_prefs, "export_change_detection")
|
|
||||||
export_materials_library = getattr(addon_prefs,"export_materials_library")
|
|
||||||
|
|
||||||
# standard gltf export settings are stored differently
|
|
||||||
standard_gltf_exporter_settings = get_standard_exporter_settings()
|
|
||||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
|
||||||
|
|
||||||
collection_parents = dict()
|
|
||||||
for collection in bpy.data.collections:
|
|
||||||
collection_parents[collection.name] = None
|
|
||||||
for collection in bpy.data.collections:
|
|
||||||
for ch in collection.children:
|
|
||||||
collection_parents[ch.name] = collection.name
|
|
||||||
|
|
||||||
# get a list of all collections actually in use
|
|
||||||
(collections, blueprint_hierarchy) = get_exportable_collections(level_scenes, library_scenes, addon_prefs)
|
|
||||||
|
|
||||||
# first check if all collections have already been exported before (if this is the first time the exporter is run
|
|
||||||
# in your current Blender session for example)
|
|
||||||
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
|
|
||||||
export_levels_path = os.path.join(folder_path, export_output_folder)
|
|
||||||
|
|
||||||
gltf_extension = standard_gltf_exporter_settings.get("export_format", 'GLB')
|
|
||||||
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
|
|
||||||
collections_not_on_disk = check_if_blueprints_exist(collections, export_blueprints_path, gltf_extension)
|
|
||||||
changed_collections = []
|
|
||||||
|
|
||||||
for scene, objects in changes_per_scene.items():
|
|
||||||
print(" changed scene", scene)
|
|
||||||
for obj_name, obj in objects.items():
|
|
||||||
object_collections = list(obj.users_collection) if hasattr(obj, 'users_collection') else []
|
|
||||||
object_collection_names = list(map(lambda collection: collection.name, object_collections))
|
|
||||||
|
|
||||||
if len(object_collection_names) > 1:
|
|
||||||
print("ERRROR for",obj_name,"objects in multiple collections not supported")
|
|
||||||
else:
|
|
||||||
object_collection_name = object_collection_names[0] if len(object_collection_names) > 0 else None
|
|
||||||
#recurse updwards until we find one of our collections (or not)
|
|
||||||
matching_collection = find_collection_ascendant_target_collection(collection_parents, collections, object_collection_name)
|
|
||||||
if matching_collection is not None:
|
|
||||||
changed_collections.append(matching_collection)
|
|
||||||
|
|
||||||
collections_to_export = list(set(changed_collections + collections_not_on_disk)) if export_change_detection else collections
|
|
||||||
|
|
||||||
# we need to re_export everything if the export parameters have been changed # TODO: perhaps do this BEFORE the rest above for better perfs
|
|
||||||
collections_to_export = collections if changed_export_parameters else collections_to_export
|
|
||||||
collections_per_scene = get_collections_per_scene(collections_to_export, library_scenes)
|
|
||||||
|
|
||||||
# collections that do not come from a library should not be exported as seperate blueprints
|
|
||||||
# FIMXE: logic is erroneous, needs to be changed
|
|
||||||
library_collections = get_collections_in_library(library_scenes)
|
|
||||||
collections_to_export = list(set(collections_to_export).intersection(set(library_collections)))
|
|
||||||
|
|
||||||
|
|
||||||
main_scenes_to_export = [scene_name for scene_name in main_scene_names if not export_change_detection or changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)]
|
|
||||||
|
|
||||||
# update the list of tracked exports
|
|
||||||
exports_total = len(collections_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0)
|
|
||||||
bpy.context.window_manager.auto_export_tracker.exports_total = exports_total
|
|
||||||
bpy.context.window_manager.auto_export_tracker.exports_count = exports_total
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("-------------------------------")
|
|
||||||
print("collections: all:", collections)
|
|
||||||
print("collections: changed:", changed_collections)
|
|
||||||
print("collections: not found on disk:", collections_not_on_disk)
|
|
||||||
print("collections: in library:", library_collections)
|
|
||||||
print("collections: to export:", collections_to_export)
|
|
||||||
print("collections: per_scene:", collections_per_scene)
|
|
||||||
print("-------------------------------")
|
|
||||||
print("BLUEPRINTS: to export:", collections_to_export)
|
|
||||||
print("-------------------------------")
|
|
||||||
print("MAIN SCENES: to export:", main_scenes_to_export)
|
|
||||||
print("-------------------------------")
|
|
||||||
|
|
||||||
return (collections, collections_to_export, main_scenes_to_export, library_collections, collections_per_scene, blueprint_hierarchy, export_levels_path, gltf_extension)
|
|
@ -2,10 +2,14 @@ import json
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy_extras.io_utils import ExportHelper
|
from bpy_extras.io_utils import ExportHelper
|
||||||
from bpy.props import (IntProperty)
|
from bpy.props import (IntProperty, StringProperty)
|
||||||
from .preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
|
from .preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
|
||||||
|
from ..helpers.helpers_scenes import (get_scenes)
|
||||||
|
from ..helpers.helpers_collections import (get_exportable_collections)
|
||||||
from .auto_export import auto_export
|
from .auto_export import auto_export
|
||||||
|
|
||||||
|
from io_scene_gltf2 import (ExportGLTF2, GLTF_PT_export_main,ExportGLTF2_Base, GLTF_PT_export_include)
|
||||||
|
|
||||||
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
"""auto export gltf"""
|
"""auto export gltf"""
|
||||||
#bl_idname = "object.xxx"
|
#bl_idname = "object.xxx"
|
||||||
@ -154,6 +158,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
|
|
||||||
# if there were no setting before, it is new, we need export
|
# if there were no setting before, it is new, we need export
|
||||||
changed = False
|
changed = False
|
||||||
|
print("previous_auto_settings", previous_auto_settings, "previous_gltf_settings", previous_gltf_settings)
|
||||||
if previous_auto_settings == None:
|
if previous_auto_settings == None:
|
||||||
print("previous settings missing, exporting")
|
print("previous settings missing, exporting")
|
||||||
changed = True
|
changed = True
|
||||||
@ -162,7 +167,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
previous_gltf_settings = bpy.data.texts.new(".gltf_auto_export_gltf_settings_previous")
|
previous_gltf_settings = bpy.data.texts.new(".gltf_auto_export_gltf_settings_previous")
|
||||||
previous_gltf_settings.write(json.dumps({}))
|
previous_gltf_settings.write(json.dumps({}))
|
||||||
if current_gltf_settings == None:
|
if current_gltf_settings == None:
|
||||||
current_gltf_settings = bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
current_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"]
|
||||||
current_gltf_settings.write(json.dumps({}))
|
current_gltf_settings.write(json.dumps({}))
|
||||||
|
|
||||||
changed = True
|
changed = True
|
||||||
@ -194,35 +199,65 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
return changed
|
return changed
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
#print("execute")
|
print("execute")
|
||||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||||
if self.direct_mode:
|
if self.direct_mode:
|
||||||
self.load_settings(context)
|
self.load_settings(context)
|
||||||
if self.will_save_settings:
|
if self.will_save_settings:
|
||||||
self.save_settings(context)
|
self.save_settings(context)
|
||||||
|
|
||||||
|
changes_per_scene = context.window_manager.auto_export_tracker.changed_objects_per_scene
|
||||||
if self.auto_export: # only do the actual exporting if auto export is actually enabled
|
if self.auto_export: # only do the actual exporting if auto export is actually enabled
|
||||||
changes_per_scene = context.window_manager.auto_export_tracker.changed_objects_per_scene
|
|
||||||
#& do the export
|
#& do the export
|
||||||
if self.direct_mode: #Do not auto export when applying settings in the menu, do it on save only
|
if self.direct_mode: #Do not auto export when applying settings in the menu, do it on save only
|
||||||
|
# disable change detection while the operator runs
|
||||||
|
|
||||||
#determine changed parameters
|
#determine changed parameters
|
||||||
params_changed = self.did_export_settings_change()
|
params_changed = self.did_export_settings_change()
|
||||||
auto_export(changes_per_scene, params_changed, self)
|
auto_export(changes_per_scene, params_changed, self)
|
||||||
# cleanup
|
# cleanup
|
||||||
# reset the list of changes in the tracker
|
|
||||||
bpy.context.window_manager.auto_export_tracker.clear_changes()
|
|
||||||
print("AUTO EXPORT DONE")
|
print("AUTO EXPORT DONE")
|
||||||
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=0.1)
|
if bpy.context.window_manager.auto_export_tracker.exports_count == 0: # we need this in case there was nothing to export, to make sure change detection is enabled again
|
||||||
|
pass #print("YOLOOO")
|
||||||
|
#py.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)
|
||||||
|
#bpy.context.window_manager.auto_export_tracker.enable_change_detection()
|
||||||
|
# FIXME: wrong logic, this should be called only in an glTF2_post_export_callback
|
||||||
|
#bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||||
else:
|
else:
|
||||||
print("auto export disabled, skipping")
|
print("auto export disabled, skipping")
|
||||||
|
|
||||||
|
"""if not self.direct_mode:
|
||||||
|
print("enabling")
|
||||||
|
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)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
#print("invoke")
|
print("invoke")
|
||||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||||
self.load_settings(context)
|
self.load_settings(context)
|
||||||
|
|
||||||
|
addon_prefs = self
|
||||||
|
"""[main_scene_names, level_scenes, library_scene_names, library_scenes]=get_scenes(addon_prefs)
|
||||||
|
(collections, _) = get_exportable_collections(level_scenes, library_scenes, addon_prefs)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# we save this list of collections in the context
|
||||||
|
bpy.context.window_manager.exportedCollections.clear()
|
||||||
|
#TODO: add error handling for this
|
||||||
|
for collection_name in collections:
|
||||||
|
ui_info = bpy.context.window_manager.exportedCollections.add()
|
||||||
|
ui_info.name = collection_name
|
||||||
|
except Exception as error:
|
||||||
|
self.report({"ERROR"}, "Failed to populate list of exported collections/blueprints")"""
|
||||||
|
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
wm.fileselect_add(self)
|
wm.fileselect_add(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import json
|
import json
|
||||||
from types import SimpleNamespace
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import (PropertyGroup)
|
from bpy.types import (PropertyGroup)
|
||||||
from bpy.props import (PointerProperty, IntProperty, StringProperty)
|
from bpy.props import (PointerProperty, IntProperty, StringProperty)
|
||||||
|
|
||||||
from ..constants import TEMPSCENE_PREFIX
|
from ..constants import TEMPSCENE_PREFIX
|
||||||
from .internals import CollectionsToExport
|
from .internals import CollectionsToExport
|
||||||
from ..helpers.helpers_scenes import (get_scenes)
|
|
||||||
from ..helpers.helpers_collections import (get_exportable_collections)
|
|
||||||
|
|
||||||
class AutoExportTracker(PropertyGroup):
|
class AutoExportTracker(PropertyGroup):
|
||||||
|
|
||||||
@ -19,18 +16,14 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
last_operator = None
|
last_operator = None
|
||||||
dummy_file_path = ""
|
dummy_file_path = ""
|
||||||
|
|
||||||
exports_total : IntProperty(
|
|
||||||
name='exports_total',
|
|
||||||
description='Number of total exports',
|
|
||||||
default=0
|
|
||||||
) # type: ignore
|
|
||||||
|
|
||||||
exports_count : IntProperty(
|
exports_count : IntProperty(
|
||||||
name='exports_count',
|
name='exports_count',
|
||||||
description='Number of exports in progress',
|
description='Number of exports in progress',
|
||||||
default=0
|
default=0
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
||||||
@ -69,15 +62,15 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
|
|
||||||
@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)
|
||||||
|
|
||||||
"""ops = bpy.context.window_manager.operators
|
ops = bpy.context.window_manager.operators
|
||||||
print("last operators", ops)
|
print("last operators", ops)
|
||||||
for op in ops:
|
for op in ops:
|
||||||
print("operator", op)"""
|
print("operator", op)
|
||||||
active_operator = bpy.context.active_operator
|
active_operator = bpy.context.active_operator
|
||||||
if active_operator:
|
if active_operator:
|
||||||
#print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
||||||
if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "gltf_auto_export":
|
if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "gltf_auto_export":
|
||||||
# we backup any existing gltf export settings, if there were any
|
# we backup any existing gltf export settings, if there were any
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
@ -94,28 +87,30 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
# we force saving params
|
# we force saving params
|
||||||
active_operator.will_save_settings = True
|
active_operator.will_save_settings = True
|
||||||
active_operator.auto_export = True
|
active_operator.auto_export = True
|
||||||
print("setting stuff for auto_export")
|
|
||||||
|
|
||||||
# only deal with changes if we are NOT in the mids of saving/exporting
|
# only deal with changes if we are NOT in the mids of saving/exporting
|
||||||
if cls.change_detection_enabled:
|
if cls.change_detection_enabled:
|
||||||
# ignore anything going on with temporary scenes
|
# ignore anything going on with temporary scenes
|
||||||
if not scene.name.startswith(TEMPSCENE_PREFIX):
|
if not scene.name.startswith(TEMPSCENE_PREFIX):
|
||||||
# print("depsgraph_update_post", scene.name)
|
print("depsgraph_update_post", scene.name)
|
||||||
changed_scene = scene.name or ""
|
changed_scene = scene.name or ""
|
||||||
|
|
||||||
|
|
||||||
#print("-------------")
|
#print("-------------")
|
||||||
if not changed_scene in cls.changed_objects_per_scene:
|
if not changed_scene in cls.changed_objects_per_scene:
|
||||||
cls.changed_objects_per_scene[changed_scene] = {}
|
cls.changed_objects_per_scene[changed_scene] = {}
|
||||||
# print("cls.changed_objects_per_scene", cls.changed_objects_per_scene)
|
print("cls.changed_objects_per_scene", cls.changed_objects_per_scene)
|
||||||
# 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)
|
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]
|
||||||
# print(" changed object", obj.id.name,"transforms", obj.is_updated_transform, "geometry", obj.is_updated_geometry)
|
print("changed object", obj.id.name)
|
||||||
|
print("FOO","transforms", obj.is_updated_transform, "geometry", obj.is_updated_geometry)
|
||||||
cls.changed_objects_per_scene[scene.name][obj.id.name] = object
|
cls.changed_objects_per_scene[scene.name][obj.id.name] = object
|
||||||
elif isinstance(obj.id, bpy.types.Material): # or isinstance(obj.id, bpy.types.ShaderNodeTree):
|
elif isinstance(obj.id, bpy.types.Material): # or isinstance(obj.id, bpy.types.ShaderNodeTree):
|
||||||
# print(" changed material", obj.id, "scene", scene.name,)
|
print("changed material", obj.id, "scene", scene.name,)
|
||||||
material = bpy.data.materials[obj.id.name]
|
material = bpy.data.materials[obj.id.name]
|
||||||
#now find which objects are using the material
|
#now find which objects are using the material
|
||||||
for obj in bpy.data.objects:
|
for obj in bpy.data.objects:
|
||||||
@ -128,68 +123,37 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
items += len(cls.changed_objects_per_scene[scene_name].keys())
|
items += len(cls.changed_objects_per_scene[scene_name].keys())
|
||||||
if items == 0:
|
if items == 0:
|
||||||
cls.changed_objects_per_scene.clear()
|
cls.changed_objects_per_scene.clear()
|
||||||
# print("changed_objects_per_scene", cls.changed_objects_per_scene)
|
print("changed_objects_per_scene", cls.changed_objects_per_scene)
|
||||||
else:
|
else:
|
||||||
cls.changed_objects_per_scene.clear()
|
cls.changed_objects_per_scene.clear()
|
||||||
|
|
||||||
|
|
||||||
# get a list of exportable collections for display
|
|
||||||
# keep it simple, just use Simplenamespace for compatibility with the rest of our code
|
|
||||||
addon_prefs = SimpleNamespace(**get_auto_exporter_settings())
|
|
||||||
print("addon prefs", addon_prefs)
|
|
||||||
addon_prefs.export_marked_assets = True
|
|
||||||
[_, level_scenes, _, library_scenes] = get_scenes(addon_prefs)
|
|
||||||
(collections, _) = get_exportable_collections(level_scenes, library_scenes, addon_prefs)
|
|
||||||
try:
|
|
||||||
# we save this list of collections in the context
|
|
||||||
bpy.context.window_manager.exportedCollections.clear()
|
|
||||||
#TODO: add error handling for this
|
|
||||||
for collection_name in collections:
|
|
||||||
ui_info = bpy.context.window_manager.exportedCollections.add()
|
|
||||||
ui_info.name = collection_name
|
|
||||||
except Exception as error:
|
|
||||||
pass
|
|
||||||
#self.report({"ERROR"}, "Failed to populate list of exported collections/blueprints")
|
|
||||||
|
|
||||||
"""depsgraph = bpy.context.evaluated_depsgraph_get()
|
"""depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||||
for update in depsgraph.updates:
|
for update in depsgraph.updates:
|
||||||
print("update", update)"""
|
print("update", update)"""
|
||||||
|
|
||||||
def disable_change_detection(self):
|
def disable_change_detection(self):
|
||||||
#print("disable change detection")
|
print("disable change detection")
|
||||||
self.change_detection_enabled = False
|
self.change_detection_enabled = False
|
||||||
self.__class__.change_detection_enabled = False
|
self.__class__.change_detection_enabled = False
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def enable_change_detection(self):
|
def enable_change_detection(self):
|
||||||
#print("enable change detection")
|
print("enable change detection")
|
||||||
self.change_detection_enabled = True
|
self.change_detection_enabled = True
|
||||||
self.__class__.change_detection_enabled = True
|
self.__class__.change_detection_enabled = True
|
||||||
#print("bpy.context.window_manager.auto_export_tracker.change_detection_enabled", bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
#FIXME: not sure about these
|
||||||
return None
|
|
||||||
|
|
||||||
def clear_changes(self):
|
|
||||||
self.changed_objects_per_scene.clear()
|
self.changed_objects_per_scene.clear()
|
||||||
self.__class__.changed_objects_per_scene.clear()
|
self.__class__.changed_objects_per_scene.clear()
|
||||||
|
# bpy.context.window_manager.auto_export_tracker.change_detection_enabled = True
|
||||||
def export_finished(self):
|
print("bpy.context.window_manager.auto_export_tracker.change_detection_enabled", bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
||||||
#print("export_finished")
|
|
||||||
self.exports_count -= 1
|
|
||||||
if self.exports_count == 0:
|
|
||||||
print("preparing to reset change detection")
|
|
||||||
bpy.app.timers.register(self.enable_change_detection, first_interval=0.1)
|
|
||||||
#self.enable_change_detection()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def export_finished(self):
|
||||||
|
print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHH export_finished")
|
||||||
|
bpy.context.window_manager.auto_export_tracker.exports_count -= 1
|
||||||
|
if bpy.context.window_manager.auto_export_tracker.exports_count == 0:
|
||||||
|
#print("preparing to reset change detection")
|
||||||
|
# bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||||
|
|
||||||
def get_auto_exporter_settings():
|
self.enable_change_detection()
|
||||||
auto_exporter_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
|
return None
|
||||||
if auto_exporter_settings != None:
|
|
||||||
try:
|
|
||||||
auto_exporter_settings = json.loads(auto_exporter_settings.as_string())
|
|
||||||
except:
|
|
||||||
auto_exporter_settings = {}
|
|
||||||
else:
|
|
||||||
auto_exporter_settings = {}
|
|
||||||
|
|
||||||
return auto_exporter_settings
|
|
||||||
|
@ -212,8 +212,8 @@ def clear_hollow_scene(temp_scene, original_root_collection):
|
|||||||
|
|
||||||
# convenience utility to get lists of scenes
|
# convenience utility to get lists of scenes
|
||||||
def get_scenes(addon_prefs):
|
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")))
|
level_scene_names= list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes"))) # getattr(addon_prefs, "main_scene_names_compact").split(',')#
|
||||||
library_scene_names = getattr(addon_prefs,"library_scene_names") #list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
|
library_scene_names = list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes"))) #getattr(addon_prefs, "main_scene_names_compact").split(',')#
|
||||||
|
|
||||||
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, 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))
|
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
||||||
|
@ -51,12 +51,11 @@ def test_export_do_not_export_blueprints(setup_data):
|
|||||||
"main_scene_names" : ['World'],
|
"main_scene_names" : ['World'],
|
||||||
"library_scene_names": ['Library']
|
"library_scene_names": ['Library']
|
||||||
}
|
}
|
||||||
stored_auto_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 = 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_auto_settings.clear()
|
stored_settings.clear()
|
||||||
stored_auto_settings.write(json.dumps(export_props))
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -76,13 +75,11 @@ def test_export_custom_blueprints_path(setup_data):
|
|||||||
"main_scene_names" : ['World'],
|
"main_scene_names" : ['World'],
|
||||||
"library_scene_names": ['Library']
|
"library_scene_names": ['Library']
|
||||||
}
|
}
|
||||||
|
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_auto_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()
|
||||||
stored_auto_settings.clear()
|
stored_settings.write(json.dumps(export_props))
|
||||||
stored_auto_settings.write(json.dumps(export_props))
|
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -107,7 +104,6 @@ def test_export_materials_library(setup_data):
|
|||||||
stored_settings.write(json.dumps(export_props))
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -133,7 +129,6 @@ def test_export_materials_library_custom_path(setup_data):
|
|||||||
stored_settings.write(json.dumps(export_props))
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -164,7 +159,6 @@ def test_export_collection_instances_combine_mode(setup_data): # TODO: change &
|
|||||||
bpy.data.objects["Cube"]["dynamic"] = True
|
bpy.data.objects["Cube"]["dynamic"] = True
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_blueprints=True,
|
export_blueprints=True,
|
||||||
@ -190,7 +184,6 @@ def test_export_do_not_export_marked_assets(setup_data):
|
|||||||
stored_settings.write(json.dumps(export_props))
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -223,7 +216,6 @@ def test_export_separate_dynamic_and_static_objects(setup_data):
|
|||||||
bpy.data.objects["Cube"]["dynamic"] = True
|
bpy.data.objects["Cube"]["dynamic"] = True
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
||||||
@ -250,7 +242,6 @@ def test_export_should_not_generate_orphan_data(setup_data):
|
|||||||
stored_settings.write(json.dumps(export_props))
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
export_output_folder="./models",
|
export_output_folder="./models",
|
||||||
export_scene_settings=True,
|
export_scene_settings=True,
|
@ -5,7 +5,6 @@ import mathutils
|
|||||||
import pytest
|
import pytest
|
||||||
import shutil
|
import shutil
|
||||||
import pathlib
|
import pathlib
|
||||||
import rna_prop_ui
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_data(request):
|
def setup_data(request):
|
||||||
@ -81,89 +80,6 @@ def setup_data(request):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def test_export_change_tracking_custom_properties(setup_data):
|
|
||||||
root_path = "../../testing/bevy_example"
|
|
||||||
assets_root_path = os.path.join(root_path, "assets")
|
|
||||||
models_path = os.path.join(assets_root_path, "models")
|
|
||||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
|
||||||
|
|
||||||
# with change detection
|
|
||||||
# first, configure things
|
|
||||||
# we use the global settings for that
|
|
||||||
export_props = {
|
|
||||||
"main_scene_names" : ['World'],
|
|
||||||
"library_scene_names": ['Library'],
|
|
||||||
}
|
|
||||||
|
|
||||||
# store settings for the auto_export part
|
|
||||||
stored_auto_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_auto_settings.clear()
|
|
||||||
stored_auto_settings.write(json.dumps(export_props))
|
|
||||||
|
|
||||||
gltf_settings = {
|
|
||||||
"export_animations": False,
|
|
||||||
"export_optimize_animation_size": False
|
|
||||||
}
|
|
||||||
# and store settings for the gltf part
|
|
||||||
stored_gltf_settings = bpy.data.texts[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_gltf_settings")
|
|
||||||
stored_gltf_settings.clear()
|
|
||||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
|
||||||
|
|
||||||
auto_export_operator(
|
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
|
||||||
export_output_folder="./models",
|
|
||||||
export_scene_settings=True,
|
|
||||||
export_blueprints=True,
|
|
||||||
export_legacy_mode=False,
|
|
||||||
export_materials_library=False
|
|
||||||
)
|
|
||||||
|
|
||||||
world_file_path = os.path.join(models_path, "World.glb")
|
|
||||||
assert os.path.exists(world_file_path) == True
|
|
||||||
|
|
||||||
models_library_path = os.path.join(models_path, "library")
|
|
||||||
model_library_file_paths = list(map(lambda file_name: os.path.join(models_library_path, file_name), sorted(os.listdir(models_library_path))))
|
|
||||||
modification_times_first = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
|
||||||
|
|
||||||
mapped_files_to_timestamps_and_index = {}
|
|
||||||
for (index, file_path) in enumerate(model_library_file_paths+ [world_file_path]):
|
|
||||||
file_path = pathlib.Path(file_path).stem
|
|
||||||
mapped_files_to_timestamps_and_index[file_path] = (modification_times_first[index], index)
|
|
||||||
|
|
||||||
# now add a custom property to the cube in the main scene & export again
|
|
||||||
print("----------------")
|
|
||||||
print("main scene change (custom property)")
|
|
||||||
print("----------------")
|
|
||||||
|
|
||||||
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
|
||||||
bpy.data.objects["Cube"]["test_property"] = 42
|
|
||||||
|
|
||||||
#force an update
|
|
||||||
rna_prop_ui.rna_idprop_ui_create(bpy.data.objects["Cube"], "________temp", default=0)
|
|
||||||
rna_prop_ui.rna_idprop_ui_prop_clear(bpy.data.objects["Cube"], "________temp")
|
|
||||||
|
|
||||||
auto_export_operator(
|
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
|
||||||
export_output_folder="./models",
|
|
||||||
export_scene_settings=True,
|
|
||||||
export_blueprints=True,
|
|
||||||
export_legacy_mode=False,
|
|
||||||
export_materials_library=False
|
|
||||||
)
|
|
||||||
|
|
||||||
modification_times = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
|
||||||
assert modification_times != modification_times_first
|
|
||||||
# only the "world" file should have changed
|
|
||||||
world_file_index = mapped_files_to_timestamps_and_index["World"][1]
|
|
||||||
other_files_modification_times = [value for index, value in enumerate(modification_times) if index not in [world_file_index]]
|
|
||||||
other_files_modification_times_first = [value for index, value in enumerate(modification_times_first) if index not in [world_file_index]]
|
|
||||||
|
|
||||||
assert modification_times[world_file_index] != modification_times_first[world_file_index]
|
|
||||||
assert other_files_modification_times == other_files_modification_times_first
|
|
||||||
# reset the comparing
|
|
||||||
modification_times_first = modification_times
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
- setup gltf parameters & auto_export parameters
|
- setup gltf parameters & auto_export parameters
|
||||||
@ -317,7 +233,7 @@ def test_export_changed_parameters(setup_data):
|
|||||||
print("----------------")
|
print("----------------")
|
||||||
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
||||||
|
|
||||||
bpy.data.objects["Blueprint3_mesh"].location= [0, 0.1 ,2]
|
bpy.data.objects["Blueprint3_mesh"]["test_component"] = 42
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
auto_export=True,
|
||||||
@ -333,17 +249,13 @@ def test_export_changed_parameters(setup_data):
|
|||||||
assert modification_times != modification_times_first
|
assert modification_times != modification_times_first
|
||||||
# the "world" file should have changed (TODO: double check: this is since changing an instances collection changes the instance too ?)
|
# the "world" file should have changed (TODO: double check: this is since changing an instances collection changes the instance too ?)
|
||||||
world_file_index = mapped_files_to_timestamps_and_index["World"][1]
|
world_file_index = mapped_files_to_timestamps_and_index["World"][1]
|
||||||
# and the blueprint3 file too, since that is the collection we changed
|
# and the blueprint1 file too, since that is the collection we changed
|
||||||
blueprint3_file_index = mapped_files_to_timestamps_and_index["Blueprint3"][1]
|
blueprint1_file_index = mapped_files_to_timestamps_and_index["Blueprint1"][1]
|
||||||
# and the blueprint4 file too, since it contains the collection we changed
|
other_files_modification_times = [value for index, value in enumerate(modification_times) if index not in [world_file_index, blueprint1_file_index]]
|
||||||
blueprint4_file_index = mapped_files_to_timestamps_and_index["Blueprint4_nested"][1]
|
other_files_modification_times_first = [value for index, value in enumerate(modification_times_first) if index not in [world_file_index, blueprint1_file_index]]
|
||||||
|
|
||||||
other_files_modification_times = [value for index, value in enumerate(modification_times) if index not in [world_file_index, blueprint3_file_index, blueprint4_file_index]]
|
|
||||||
other_files_modification_times_first = [value for index, value in enumerate(modification_times_first) if index not in [world_file_index, blueprint3_file_index, blueprint4_file_index]]
|
|
||||||
|
|
||||||
assert modification_times[world_file_index] != modification_times_first[world_file_index]
|
assert modification_times[world_file_index] != modification_times_first[world_file_index]
|
||||||
assert modification_times[blueprint3_file_index] != modification_times_first[blueprint3_file_index]
|
assert modification_times[blueprint1_file_index] != modification_times_first[blueprint1_file_index]
|
||||||
assert modification_times[blueprint4_file_index] != modification_times_first[blueprint4_file_index]
|
|
||||||
assert other_files_modification_times == other_files_modification_times_first
|
assert other_files_modification_times == other_files_modification_times_first
|
||||||
# reset the comparing
|
# reset the comparing
|
||||||
modification_times_first = modification_times
|
modification_times_first = modification_times
|
||||||
@ -359,15 +271,11 @@ def test_export_changed_parameters(setup_data):
|
|||||||
|
|
||||||
with bpy.context.temp_override(active_object=bpy.data.objects["Cube"]):
|
with bpy.context.temp_override(active_object=bpy.data.objects["Cube"]):
|
||||||
print("translate using operator")
|
print("translate using operator")
|
||||||
bpy.ops.transform.translate(value=mathutils.Vector((2.0, 1.0, -5.0)))
|
bpy.ops.transform.translate(value=mathutils.Vector((2.0, 1.0, -5.0)))
|
||||||
bpy.ops.transform.rotate(value=0.378874, constraint_axis=(False, False, True), mirror=False, proportional_edit_falloff='SMOOTH', proportional_size=1)
|
bpy.ops.transform.rotate(value=0.378874, constraint_axis=(False, False, True), mirror=False, proportional_edit_falloff='SMOOTH', proportional_size=1)
|
||||||
bpy.ops.object.transform_apply()
|
bpy.ops.object.transform_apply()
|
||||||
bpy.ops.transform.translate(value=(0.5, 0, 0), constraint_axis=(True, False, False))
|
bpy.ops.transform.translate(value=(0.5, 0, 0), constraint_axis=(True, False, False))
|
||||||
|
|
||||||
#force an update, as apparently all the operators above do not trigger changes ???
|
|
||||||
rna_prop_ui.rna_idprop_ui_create(bpy.data.objects["Cube"], "________temp", default=0)
|
|
||||||
rna_prop_ui.rna_idprop_ui_prop_clear(bpy.data.objects["Cube"], "________temp")
|
|
||||||
|
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
auto_export=True,
|
||||||
|
@ -57,7 +57,7 @@ def test_export_no_parameters(setup_data):
|
|||||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
|
||||||
# first test exporting withouth any parameters set, this should not export anything
|
# first test exporting withouth any parameters set, this should export with default parameters gracefully
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
auto_export=True,
|
||||||
@ -67,35 +67,7 @@ def test_export_no_parameters(setup_data):
|
|||||||
export_materials_library=True
|
export_materials_library=True
|
||||||
)
|
)
|
||||||
|
|
||||||
world_file_path = os.path.join(models_path, "World.glb")
|
|
||||||
assert os.path.exists(world_file_path) != True
|
|
||||||
|
|
||||||
def test_export_auto_export_parameters_only(setup_data):
|
|
||||||
root_path = "../../testing/bevy_example"
|
|
||||||
assets_root_path = os.path.join(root_path, "assets")
|
|
||||||
models_path = os.path.join(assets_root_path, "models")
|
|
||||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
|
||||||
|
|
||||||
export_props = {
|
|
||||||
"main_scene_names" : ['World'],
|
|
||||||
"library_scene_names": ['Library'],
|
|
||||||
}
|
|
||||||
|
|
||||||
# store settings for the auto_export part
|
|
||||||
stored_auto_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_auto_settings.clear()
|
|
||||||
stored_auto_settings.write(json.dumps(export_props))
|
|
||||||
|
|
||||||
auto_export_operator(
|
|
||||||
auto_export=True,
|
|
||||||
direct_mode=True,
|
|
||||||
export_output_folder="./models",
|
|
||||||
export_legacy_mode=False,
|
|
||||||
export_materials_library=True
|
|
||||||
)
|
|
||||||
|
|
||||||
world_file_path = os.path.join(models_path, "World.glb")
|
|
||||||
assert os.path.exists(world_file_path) == True
|
|
||||||
|
|
||||||
def test_export_changed_parameters(setup_data):
|
def test_export_changed_parameters(setup_data):
|
||||||
root_path = "../../testing/bevy_example"
|
root_path = "../../testing/bevy_example"
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
from typing import Set
|
from typing import Set
|
||||||
import bpy
|
import bpy
|
||||||
|
from bpy.types import Context, Event, Operator
|
||||||
|
from bpy_extras.io_utils import ExportHelper
|
||||||
|
from bpy.props import (BoolProperty,
|
||||||
|
IntProperty,
|
||||||
|
StringProperty,
|
||||||
|
EnumProperty,
|
||||||
|
CollectionProperty
|
||||||
|
)
|
||||||
|
|
||||||
|
from ..auto_export import auto_export
|
||||||
|
|
||||||
|
from ..auto_export.preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
|
||||||
|
from ..helpers.helpers_scenes import (get_scenes)
|
||||||
|
from ..helpers.helpers_collections import (get_exportable_collections)
|
||||||
######################################################
|
######################################################
|
||||||
## ui logic & co
|
## ui logic & co
|
||||||
|
|
||||||
@ -35,41 +49,15 @@ class GLTF_PT_auto_export_SidePanel(bpy.types.Panel):
|
|||||||
op = layout.operator("EXPORT_SCENES_OT_auto_gltf", text="Auto Export Settings")
|
op = layout.operator("EXPORT_SCENES_OT_auto_gltf", text="Auto Export Settings")
|
||||||
op.auto_export = True
|
op.auto_export = True
|
||||||
|
|
||||||
class GLTF_PT_auto_export_changes_list(bpy.types.Panel):
|
layout.label(text="changes since last save:")
|
||||||
bl_space_type = 'VIEW_3D'
|
changed_objects_per_scene = {}
|
||||||
bl_region_type = 'UI'
|
for scene in context.window_manager.auto_export_tracker.changed_objects_per_scene:
|
||||||
bl_label = "Changes per scene since last save "
|
if not scene in changed_objects_per_scene.keys():
|
||||||
bl_parent_id = "GLTF_PT_auto_export_SidePanel"
|
changed_objects_per_scene[scene] = []
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
changed_objects_per_scene[scene]+= context.window_manager.auto_export_tracker.changed_objects_per_scene[scene].keys()
|
||||||
|
|
||||||
def draw(self, context):
|
layout.label(text=str(changed_objects_per_scene))
|
||||||
layout = self.layout
|
#print("GLTF_PT_export_main", GLTF_PT_export_main.bl_parent_id)
|
||||||
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}')
|
|
||||||
|
|
||||||
class GLTF_PT_auto_export_collections_list(bpy.types.Panel):
|
|
||||||
bl_space_type = 'VIEW_3D'
|
|
||||||
bl_region_type = 'UI'
|
|
||||||
bl_label = "Blueprints to export"
|
|
||||||
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.
|
|
||||||
|
|
||||||
for collection in bpy.context.window_manager.exportedCollections:
|
|
||||||
row = layout.row()
|
|
||||||
row.label(text=collection.name)
|
|
||||||
|
|
||||||
# main ui in the file => export
|
# main ui in the file => export
|
||||||
class GLTF_PT_auto_export_main(bpy.types.Panel):
|
class GLTF_PT_auto_export_main(bpy.types.Panel):
|
||||||
@ -273,6 +261,34 @@ class GLTF_PT_auto_export_blueprints(bpy.types.Panel):
|
|||||||
layout.prop(operator, "export_materials_library")
|
layout.prop(operator, "export_materials_library")
|
||||||
layout.prop(operator, "export_materials_path")
|
layout.prop(operator, "export_materials_path")
|
||||||
|
|
||||||
|
|
||||||
|
class GLTF_PT_auto_export_collections_list(bpy.types.Panel):
|
||||||
|
bl_space_type = 'FILE_BROWSER'
|
||||||
|
bl_region_type = 'TOOL_PROPS'
|
||||||
|
bl_label = "Blueprints: Exported Collections"
|
||||||
|
bl_parent_id = "GLTF_PT_auto_export_blueprints"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
sfile = context.space_data
|
||||||
|
operator = sfile.active_operator
|
||||||
|
|
||||||
|
return operator.bl_idname == "EXPORT_SCENES_OT_auto_gltf" #"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.active = operator.auto_export and operator.export_blueprints
|
||||||
|
|
||||||
|
for collection in bpy.context.window_manager.exportedCollections:
|
||||||
|
row = layout.row()
|
||||||
|
row.label(text=collection.name)
|
||||||
|
|
||||||
class SCENE_UL_GLTF_auto_export(bpy.types.UIList):
|
class SCENE_UL_GLTF_auto_export(bpy.types.UIList):
|
||||||
# The draw_item function is called for each item of the collection that is visible in the list.
|
# The draw_item function is called for each item of the collection that is visible in the list.
|
||||||
# data is the RNA object containing the collection,
|
# data is the RNA object containing the collection,
|
||||||
|
Loading…
Reference in New Issue
Block a user