feat(blenvy): massive overhaul
* removed a lot of obsolete code * overhauled settings upsert * added save & load of blenvy common settings * removed most of the specific uis (mostly auto export) * moved change detection logic out of auto export (wip) * added helper to compare setting dicts * cleaned up some incoherent naming * stripped auto_export of a lot of its internals (wip) * main settings ui overhaul: now components & auto export provide their own settings UI function
This commit is contained in:
parent
c476c05c55
commit
21a36f9878
|
@ -5,7 +5,7 @@ Auto export
|
|||
- [x] blueprints
|
||||
- [x] materials
|
||||
- [x] move out the UI for "assets" folder out of "blueprints condition"
|
||||
- [ ] fix asset path calculations
|
||||
- [x] fix asset path calculations
|
||||
- root path => relative to blend file path
|
||||
- asset path => relative to root path
|
||||
- blueprints/levels/blueprints path => relative to assets path
|
||||
|
@ -49,6 +49,10 @@ Blueprints:
|
|||
- [ ] scan & inject on load
|
||||
- [ ] scan & inject on save
|
||||
|
||||
General things to solve:
|
||||
- [x] save settings
|
||||
- [x] load settings
|
||||
- [ ] add_blueprints_data
|
||||
|
||||
General issues:
|
||||
- there is no safeguard for naming collisions for naming across blender files
|
||||
|
|
|
@ -15,11 +15,12 @@ import bpy
|
|||
from bpy.app.handlers import persistent
|
||||
from bpy.props import (StringProperty)
|
||||
|
||||
|
||||
# components management
|
||||
from .bevy_components.components.operators import CopyComponentOperator, Fix_Component_Operator, OT_rename_component, RemoveComponentFromAllObjectsOperator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, AddComponentOperator, RenameHelper, Toggle_ComponentVisibility
|
||||
|
||||
from .bevy_components.registry.registry import ComponentsRegistry,MissingBevyType
|
||||
from .bevy_components.registry.operators import (COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT, OT_select_component_name_to_replace, OT_select_object, ReloadRegistryOperator, OT_OpenFilebrowser)
|
||||
from .bevy_components.registry.operators import (COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL, COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT, OT_select_component_name_to_replace, OT_select_object, ReloadRegistryOperator, OT_OpenSchemaFileBrowser)
|
||||
from .bevy_components.registry.ui import (BEVY_COMPONENTS_PT_Configuration, BEVY_COMPONENTS_PT_AdvancedToolsPanel, BEVY_COMPONENTS_PT_MissingTypesPanel, MISSING_TYPES_UL_List)
|
||||
|
||||
from .bevy_components.components.metadata import (ComponentMetadata, ComponentsMeta)
|
||||
|
@ -32,12 +33,8 @@ from .bevy_components.components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
|
|||
from .gltf_auto_export import gltf_post_export_callback
|
||||
from .gltf_auto_export.auto_export.operators import AutoExportGLTF
|
||||
from .gltf_auto_export.auto_export.tracker import AutoExportTracker
|
||||
from .gltf_auto_export.ui.main import (GLTF_PT_auto_export_change_detection, GLTF_PT_auto_export_main,
|
||||
GLTF_PT_auto_export_root,
|
||||
GLTF_PT_auto_export_general,
|
||||
GLTF_PT_auto_export_blueprints,
|
||||
GLTF_PT_auto_export_SidePanel
|
||||
)
|
||||
from .gltf_auto_export.settings import AutoExportSettings
|
||||
|
||||
# asset management
|
||||
from .assets.ui import Blenvy_assets
|
||||
from .assets.assets_registry import Asset, AssetsRegistry
|
||||
|
@ -54,7 +51,7 @@ from .core.operators import OT_switch_bevy_tooling
|
|||
from .core.scene_helpers import (SceneSelector)
|
||||
from .core.ui.ui import (BLENVY_PT_SidePanel)
|
||||
from .core.ui.scenes_list import SCENES_LIST_OT_actions, SCENE_UL_Blenvy
|
||||
from .core.ui.folder_browser import OT_OpenFolderbrowser
|
||||
from .core.ui.folder_browser import OT_OpenAssetsFolderBrowser
|
||||
|
||||
|
||||
# this needs to be here, as it is how Blender's gltf exporter callbacks are defined, at the add-on root level
|
||||
|
@ -67,7 +64,7 @@ classes = [
|
|||
SceneSelector,
|
||||
SCENE_UL_Blenvy,
|
||||
SCENES_LIST_OT_actions,
|
||||
OT_OpenFolderbrowser,
|
||||
OT_OpenAssetsFolderBrowser,
|
||||
|
||||
# blenvy
|
||||
BLENVY_PT_SidePanel,
|
||||
|
@ -92,7 +89,7 @@ classes = [
|
|||
MissingBevyType,
|
||||
ComponentsRegistry,
|
||||
|
||||
OT_OpenFilebrowser,
|
||||
OT_OpenSchemaFileBrowser,
|
||||
ReloadRegistryOperator,
|
||||
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL,
|
||||
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT,
|
||||
|
@ -105,7 +102,7 @@ classes = [
|
|||
|
||||
BEVY_COMPONENTS_PT_ComponentsPanel,
|
||||
BEVY_COMPONENTS_PT_AdvancedToolsPanel,
|
||||
BEVY_COMPONENTS_PT_Configuration,
|
||||
#BEVY_COMPONENTS_PT_Configuration,
|
||||
MISSING_TYPES_UL_List,
|
||||
BEVY_COMPONENTS_PT_MissingTypesPanel,
|
||||
|
||||
|
@ -118,15 +115,8 @@ classes = [
|
|||
|
||||
# gltf auto export
|
||||
AutoExportGLTF,
|
||||
|
||||
|
||||
GLTF_PT_auto_export_main,
|
||||
GLTF_PT_auto_export_root,
|
||||
GLTF_PT_auto_export_general,
|
||||
GLTF_PT_auto_export_change_detection,
|
||||
GLTF_PT_auto_export_blueprints,
|
||||
GLTF_PT_auto_export_SidePanel,
|
||||
AutoExportTracker,
|
||||
AutoExportSettings,
|
||||
|
||||
# blenvy
|
||||
BlenvyManager,
|
||||
|
@ -157,8 +147,11 @@ def post_save(scene, depsgraph):
|
|||
@persistent
|
||||
def post_load(file_name):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
if registry != None:
|
||||
if registry is not None:
|
||||
registry.load_settings()
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
if blenvy is not None:
|
||||
blenvy.load_settings()
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
|
|
|
@ -5,13 +5,13 @@ 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):
|
||||
export_root_path = getattr(addon_prefs, "export_root_path")
|
||||
project_root_path = getattr(addon_prefs, "project_root_path")
|
||||
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
||||
export_levels_path = getattr(addon_prefs,"export_levels_path")
|
||||
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||
levels_path = getattr(addon_prefs,"levels_path")
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
|
||||
relative_blueprints_path = os.path.relpath(export_blueprints_path, export_root_path)
|
||||
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)
|
||||
|
||||
blueprint_assets_list = []
|
||||
|
@ -62,7 +62,7 @@ def get_userTextures():
|
|||
print("textures", textures)
|
||||
|
||||
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
|
||||
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
assets_list = []
|
||||
|
||||
|
@ -72,7 +72,7 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
|
|||
if child_blueprint:
|
||||
blueprint_exported_path = None
|
||||
if blueprint.local:
|
||||
blueprint_exported_path = os.path.join(export_blueprints_path, f"{child_blueprint.name}{export_gltf_extension}")
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{child_blueprint.name}{export_gltf_extension}")
|
||||
else:
|
||||
# get the injected path of the external blueprints
|
||||
blueprint_exported_path = child_blueprint.collection['export_path'] if 'export_path' in child_blueprint.collection else None
|
||||
|
@ -91,7 +91,7 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
|
|||
return assets_list
|
||||
|
||||
def get_main_scene_assets_tree(main_scene, blueprints_data, addon_prefs):
|
||||
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(main_scene.name, None)
|
||||
|
||||
|
@ -102,7 +102,7 @@ def get_main_scene_assets_tree(main_scene, blueprints_data, addon_prefs):
|
|||
if blueprint is not None:
|
||||
blueprint_exported_path = None
|
||||
if blueprint.local:
|
||||
blueprint_exported_path = os.path.join(export_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||
else:
|
||||
# get the injected path of the external blueprints
|
||||
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||
|
|
|
@ -145,11 +145,11 @@ class OT_Add_asset_filebrowser(Operator, ImportHelper):
|
|||
|
||||
def execute(self, context):
|
||||
current_auto_settings = load_settings(".gltf_auto_export_settings")
|
||||
export_root_path = current_auto_settings.get("export_root_path", "../")
|
||||
export_assets_path = current_auto_settings.get("export_assets_path", "assets")
|
||||
project_root_path = current_auto_settings.get("project_root_path", "../")
|
||||
assets_path = current_auto_settings.get("assets_path", "assets")
|
||||
# FIXME: not sure
|
||||
print("export_root_path", export_root_path, "export_assets_path", export_assets_path)
|
||||
export_assets_path_absolute = absolute_path_from_blend_file(os.path.join(export_root_path, export_assets_path))
|
||||
print("project_root_path", project_root_path, "assets_path", assets_path)
|
||||
export_assets_path_absolute = absolute_path_from_blend_file(os.path.join(project_root_path, assets_path))
|
||||
|
||||
asset_path = os.path.relpath(self.filepath, export_assets_path_absolute)
|
||||
print("asset path", asset_path)
|
||||
|
@ -203,7 +203,7 @@ class OT_test_bevy_assets(Operator):
|
|||
blueprints_registry.add_blueprints_data()
|
||||
blueprints_data = blueprints_registry.blueprints_data
|
||||
|
||||
settings = {"export_blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||
settings = SimpleNamespace(**settings)
|
||||
for scene in bpy.data.scenes:
|
||||
if scene.name != "Library":
|
||||
|
|
|
@ -80,7 +80,7 @@ class Blenvy_assets(bpy.types.Panel):
|
|||
header, panel = layout.box().panel(f"assets{name}", default_closed=False)
|
||||
header.label(text="World/Level Assets")
|
||||
|
||||
settings = {"export_blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||
settings = {"blueprints_path": "blueprints", "export_gltf_extension": ".glb"}
|
||||
settings = SimpleNamespace(**settings)
|
||||
|
||||
if panel:
|
||||
|
|
|
@ -173,9 +173,9 @@ class COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL(Operator):
|
|||
context.window_manager.components_from_custom_properties_progress_all = -1.0
|
||||
return {'FINISHED'}
|
||||
|
||||
class OT_OpenFilebrowser(Operator, ImportHelper):
|
||||
class OT_OpenSchemaFileBrowser(Operator, ImportHelper):
|
||||
"""Browse for registry json file"""
|
||||
bl_idname = "generic.open_filebrowser"
|
||||
bl_idname = "blenvy.open_schemafilebrowser"
|
||||
bl_label = "Open the file browser"
|
||||
|
||||
filter_glob: StringProperty(
|
||||
|
@ -194,7 +194,8 @@ class OT_OpenFilebrowser(Operator, ImportHelper):
|
|||
registry = context.window_manager.components_registry
|
||||
registry.schemaPath = relative_path
|
||||
|
||||
upsert_settings(registry.settings_save_path, {"schemaPath": relative_path})
|
||||
blenvy = context.window_manager.blenvy
|
||||
upsert_settings(blenvy.settings_save_path, {"components_schemaPath": relative_path})
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -283,8 +283,7 @@ class ComponentsRegistry(PropertyGroup):
|
|||
settings = load_settings(self.settings_save_path)
|
||||
|
||||
if settings!= None:
|
||||
print("settings", settings)
|
||||
self.schemaPath = settings["schemaPath"]
|
||||
self.schemaPath = settings["components_schemaPath"]
|
||||
self.load_schema()
|
||||
generate_propertyGroups_for_components()
|
||||
ensure_metadata_for_all_objects()
|
||||
|
|
|
@ -7,7 +7,7 @@ from ..components.operators import OT_rename_component, RemoveComponentFromAllOb
|
|||
from .operators import(
|
||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
|
||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT,
|
||||
OT_OpenFilebrowser,
|
||||
OT_OpenSchemaFileBrowser,
|
||||
OT_select_component_name_to_replace,
|
||||
OT_select_object, ReloadRegistryOperator,
|
||||
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL,
|
||||
|
@ -39,7 +39,7 @@ class BEVY_COMPONENTS_PT_Configuration(bpy.types.Panel):
|
|||
col.enabled = False
|
||||
col.prop(registry, "schemaPath", text="Registry Schema path")
|
||||
col = row.column()
|
||||
col.operator(OT_OpenFilebrowser.bl_idname, text="Browse for registry schema file (json)")
|
||||
col.operator(OT_OpenSchemaFileBrowser.bl_idname, text="Browse for registry schema file (json)")
|
||||
|
||||
layout.separator()
|
||||
layout.operator(ReloadRegistryOperator.bl_idname, text="reload registry" , icon="FILE_REFRESH")
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
def draw_settings_ui(layout, registry):
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.enabled = False
|
||||
col.prop(registry, "schemaPath", text="Registry Schema path")
|
||||
col = row.column()
|
||||
col.operator(operator="blenvy.open_schemafilebrowser", text="Browse for registry schema file (json)")
|
||||
|
||||
layout.separator()
|
||||
layout.operator(operator="object.reload_registry", text="reload registry" , icon="FILE_REFRESH")
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
|
||||
row.prop(registry, "watcher_enabled", text="enable registry file polling")
|
||||
row.prop(registry, "watcher_poll_frequency", text="registry file poll frequency (s)")
|
||||
|
||||
layout.separator()
|
||||
layout.separator()
|
|
@ -20,16 +20,16 @@ def check_if_blueprint_on_disk(scene_name, folder_path, extension):
|
|||
print("level", scene_name, "found", found, "path", gltf_output_path)
|
||||
return found
|
||||
|
||||
def inject_export_path_into_internal_blueprints(internal_blueprints, export_blueprints_path, gltf_extension):
|
||||
def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_path, gltf_extension):
|
||||
for blueprint in internal_blueprints:
|
||||
blueprint_exported_path = os.path.join(export_blueprints_path, f"{blueprint.name}{gltf_extension}")
|
||||
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):
|
||||
export_root_path = getattr(addon_prefs, "export_root_path")
|
||||
export_assets_path = getattr(addon_prefs,"export_assets_path")
|
||||
export_levels_path = getattr(addon_prefs,"export_levels_path")
|
||||
export_blueprints_path = getattr(addon_prefs, "export_blueprints_path")
|
||||
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")
|
||||
|
||||
# print("injecting assets/blueprints data into scene")
|
||||
|
@ -45,7 +45,7 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs):
|
|||
print("BLUEPRINT", blueprint)
|
||||
blueprint_exported_path = None
|
||||
if blueprint.local:
|
||||
blueprint_exported_path = os.path.join(export_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||
else:
|
||||
# get the injected path of the external blueprints
|
||||
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
||||
|
@ -61,8 +61,7 @@ def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs):
|
|||
|
||||
print("blueprint assets", blueprint_assets_list)
|
||||
"""add_scene_property(scene, assets_list_name, assets_list_data)
|
||||
for blueprint in blueprint_assets_list:
|
||||
bpy.context.window_manager.assets_registry.add_asset(**blueprint)"""
|
||||
"""
|
||||
|
||||
def remove_blueprints_list_from_main_scene(scene):
|
||||
assets_list = None
|
||||
|
|
|
@ -52,6 +52,7 @@ class BlueprintsRegistry(PropertyGroup):
|
|||
def add_blueprints_data(self):
|
||||
print("adding blueprints data")
|
||||
addon_prefs = load_settings(".gltf_auto_export_settings")
|
||||
if addon_prefs is not None:
|
||||
print("addon_prefs", addon_prefs)
|
||||
addon_prefs["export_marked_assets"] = False
|
||||
addon_prefs = SimpleNamespace(**addon_prefs)
|
||||
|
|
|
@ -2,9 +2,28 @@ import bpy
|
|||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty)
|
||||
from .scene_helpers import SceneSelector
|
||||
from ..settings import upsert_settings, load_settings
|
||||
import blenvy.gltf_auto_export.settings as auto_export_settings
|
||||
|
||||
def update_scene_lists(self, context):
|
||||
blenvy = self# context.window_manager.blenvy
|
||||
upsert_settings(blenvy.settings_save_path, {"common_main_scene_names": [scene.name for scene in blenvy.main_scenes]})
|
||||
upsert_settings(blenvy.settings_save_path, {"common_library_scene_names": [scene.name for scene in blenvy.library_scenes]})
|
||||
|
||||
def update_asset_folders(self, context):
|
||||
blenvy = context.window_manager.blenvy
|
||||
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
||||
for asset_path_name in asset_path_names:
|
||||
upsert_settings(blenvy.settings_save_path, {asset_path_name: getattr(blenvy, asset_path_name)})
|
||||
|
||||
def update_mode(self, context):
|
||||
blenvy = self # context.window_manager.blenvy
|
||||
upsert_settings(blenvy.settings_save_path, {"mode": blenvy.mode })
|
||||
|
||||
class BlenvyManager(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_settings" # where to store data in bpy.texts
|
||||
|
||||
mode: EnumProperty(
|
||||
items=(
|
||||
('COMPONENTS', "Components", ""),
|
||||
|
@ -12,46 +31,56 @@ class BlenvyManager(PropertyGroup):
|
|||
('ASSETS', "Assets", ""),
|
||||
('SETTINGS', "Settings", ""),
|
||||
('TOOLS', "Tools", ""),
|
||||
)
|
||||
),
|
||||
update=update_mode
|
||||
) # type: ignore
|
||||
|
||||
|
||||
export_root_path: StringProperty(
|
||||
project_root_path: StringProperty(
|
||||
name = "Project Root Path",
|
||||
description="The root folder of your (Bevy) project (not assets!)",
|
||||
default='../'
|
||||
default='../',
|
||||
update= update_asset_folders
|
||||
) # type: ignore
|
||||
|
||||
export_assets_path: StringProperty(
|
||||
assets_path: StringProperty(
|
||||
name='Export folder',
|
||||
description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ',
|
||||
default='./assets',
|
||||
options={'HIDDEN'}
|
||||
options={'HIDDEN'},
|
||||
update= update_asset_folders
|
||||
) # type: ignore
|
||||
|
||||
export_blueprints_path: StringProperty(
|
||||
blueprints_path: StringProperty(
|
||||
name='Blueprints path',
|
||||
description='path to export the blueprints to (relative to the assets folder)',
|
||||
default='blueprints',
|
||||
update= update_asset_folders
|
||||
) # type: ignore
|
||||
|
||||
export_levels_path: StringProperty(
|
||||
levels_path: StringProperty(
|
||||
name='Levels path',
|
||||
description='path to export the levels (main scenes) to (relative to the assets folder)',
|
||||
default='levels',
|
||||
update= update_asset_folders
|
||||
) # type: ignore
|
||||
|
||||
export_materials_path: StringProperty(
|
||||
materials_path: StringProperty(
|
||||
name='Materials path',
|
||||
description='path to export the materials libraries to (relative to the assets folder)',
|
||||
default='materials',
|
||||
update= update_asset_folders
|
||||
) # type: ignore
|
||||
|
||||
main_scenes: CollectionProperty(name="main scenes", type=SceneSelector) # type: ignore
|
||||
main_scenes_index: IntProperty(name = "Index for main scenes list", default = 0) # type: ignore
|
||||
main_scenes_index: IntProperty(name = "Index for main scenes list", default = 0, update=update_scene_lists) # type: ignore
|
||||
|
||||
library_scenes: CollectionProperty(name="library scenes", type=SceneSelector) # type: ignore
|
||||
library_scenes_index: IntProperty(name = "Index for library scenes list", default = 0) # type: ignore
|
||||
library_scenes_index: IntProperty(name = "Index for library scenes list", default = 0, update=update_scene_lists) # type: ignore
|
||||
|
||||
# sub ones
|
||||
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
||||
#components: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
||||
|
||||
def is_scene_ok(self, scene):
|
||||
try:
|
||||
|
@ -65,9 +94,6 @@ class BlenvyManager(PropertyGroup):
|
|||
bpy.types.WindowManager.main_scene = bpy.props.PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=cls.is_scene_ok)
|
||||
bpy.types.WindowManager.library_scene = bpy.props.PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=cls.is_scene_ok)
|
||||
|
||||
bpy.types.WindowManager.main_scenes_list_index = IntProperty(name = "Index for main scenes list", default = 0)
|
||||
bpy.types.WindowManager.library_scenes_list_index = IntProperty(name = "Index for library scenes list", default = 0)
|
||||
|
||||
bpy.types.WindowManager.blenvy = PointerProperty(type=BlenvyManager)
|
||||
|
||||
@classmethod
|
||||
|
@ -76,10 +102,21 @@ class BlenvyManager(PropertyGroup):
|
|||
del bpy.types.WindowManager.main_scene
|
||||
del bpy.types.WindowManager.library_scene
|
||||
|
||||
del bpy.types.WindowManager.main_scenes_list_index
|
||||
del bpy.types.WindowManager.library_scenes_list_index
|
||||
|
||||
|
||||
def add_asset(self, name, type, path, internal): # internal means it cannot be edited by the user, aka auto generated
|
||||
pass
|
||||
def load_settings(self):
|
||||
settings = load_settings(self.settings_save_path)
|
||||
if settings is not None:
|
||||
if "mode" in settings:
|
||||
self.mode = settings["mode"]
|
||||
if "common_main_scene_names" in settings:
|
||||
for main_scene_name in settings["common_main_scene_names"]:
|
||||
added = self.main_scenes.add()
|
||||
added.name = main_scene_name
|
||||
if "common_library_scene_names" in settings:
|
||||
for main_scene_name in settings["common_library_scene_names"]:
|
||||
added = self.library_scenes.add()
|
||||
added.name = main_scene_name
|
||||
|
||||
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
|
||||
for asset_path_name in asset_path_names:
|
||||
if asset_path_name in settings:
|
||||
setattr(self, asset_path_name, settings[asset_path_name])
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import json
|
||||
import bpy
|
||||
from ..helpers.serialize_scene import serialize_scene
|
||||
|
||||
def bubble_up_changes(object, changes_per_scene):
|
||||
if object.parent:
|
||||
changes_per_scene[object.parent.name] = bpy.data.objects[object.parent.name]
|
||||
bubble_up_changes(object.parent, changes_per_scene)
|
||||
|
||||
|
||||
def foo():
|
||||
current = json.loads(current)
|
||||
|
||||
previous_stored = bpy.data.texts[".TESTING"] if ".TESTING" in bpy.data.texts else None # bpy.data.texts.new(".TESTING")
|
||||
if previous_stored == None:
|
||||
previous_stored = bpy.data.texts.new(".TESTING")
|
||||
previous_stored.write(current)
|
||||
return {}
|
||||
previous = json.loads(previous_stored.as_string())
|
||||
|
||||
|
||||
previous_stored.clear()
|
||||
previous_stored.write(json.dumps(current))
|
||||
|
||||
def project_diff(previous, current):
|
||||
# sigh... you need to save & reset the frame otherwise it saves the values AT THE CURRENT FRAME WHICH CAN DIFFER ACROSS SCENES
|
||||
current_frames = [scene.frame_current for scene in bpy.data.scenes]
|
||||
for scene in bpy.data.scenes:
|
||||
scene.frame_set(0)
|
||||
|
||||
current_scene = bpy.context.window.scene
|
||||
bpy.context.window.scene = bpy.data.scenes[0]
|
||||
#serialize scene at frame 0
|
||||
"""with bpy.context.temp_override(scene=bpy.data.scenes[1]):
|
||||
bpy.context.scene.frame_set(0)"""
|
||||
current = serialize_scene()
|
||||
bpy.context.window.scene = current_scene
|
||||
|
||||
# reset previous frames
|
||||
for (index, scene) in enumerate(bpy.data.scenes):
|
||||
scene.frame_set(int(current_frames[index]))
|
||||
|
||||
changes_per_scene = {}
|
||||
|
||||
# TODO : how do we deal with changed scene names ???
|
||||
for scene in current:
|
||||
previous_object_names = list(previous[scene].keys())
|
||||
current_object_names =list(current[scene].keys())
|
||||
added = list(set(current_object_names) - set(previous_object_names))
|
||||
removed = list(set(previous_object_names) - set(current_object_names))
|
||||
|
||||
for obj in added:
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
changes_per_scene[scene][obj] = bpy.data.objects[obj]
|
||||
|
||||
# TODO: how do we deal with this, as we obviously do not have data for removed objects ?
|
||||
for obj in removed:
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
changes_per_scene[scene][obj] = None
|
||||
|
||||
for object_name in list(current[scene].keys()): # TODO : exclude directly added/removed objects
|
||||
if object_name in previous[scene]:
|
||||
current_obj = current[scene][object_name]
|
||||
prev_obj = previous[scene][object_name]
|
||||
same = str(current_obj) == str(prev_obj)
|
||||
|
||||
if not same:
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
|
||||
changes_per_scene[scene][object_name] = bpy.data.objects[object_name]
|
||||
bubble_up_changes(bpy.data.objects[object_name], changes_per_scene[scene])
|
||||
# now bubble up for instances & parents
|
||||
|
||||
print("changes per scene", changes_per_scene)
|
||||
return changes_per_scene
|
|
@ -6,8 +6,8 @@ from bpy.types import Operator
|
|||
|
||||
from ...core.path_helpers import absolute_path_from_blend_file
|
||||
|
||||
class OT_OpenFolderbrowser(Operator, ImportHelper):
|
||||
"""Browse for registry json file"""
|
||||
class OT_OpenAssetsFolderBrowser(Operator, ImportHelper):
|
||||
"""Assets folder's browser"""
|
||||
bl_idname = "generic.open_folderbrowser"
|
||||
bl_label = "Select folder"
|
||||
|
||||
|
@ -41,31 +41,31 @@ class OT_OpenFolderbrowser(Operator, ImportHelper):
|
|||
# Get the folder
|
||||
blend_file_folder_path = os.path.dirname(blend_file_path)
|
||||
#print("blend_file_folder_path", blend_file_folder_path)
|
||||
print("new_path", self.directory, self.target_property, operator)
|
||||
#print("new_path", self.directory, self.target_property, operator)
|
||||
|
||||
asset_path_names = ['export_blueprints_path', 'export_levels_path', 'export_materials_path']
|
||||
export_root_path = absolute_path_from_blend_file(operator.export_root_path)
|
||||
export_assets_path = operator.export_assets_path
|
||||
export_assets_path_full = absolute_path_from_blend_file(os.path.join(export_root_path, export_assets_path)) #os.path.join(blend_file_folder_path, export_root_path, export_assets_path)
|
||||
print("export_assets_path_full", export_assets_path_full)
|
||||
asset_path_names = ['blueprints_path', 'levels_path', 'materials_path']
|
||||
project_root_path = absolute_path_from_blend_file(operator.project_root_path)
|
||||
assets_path = operator.assets_path
|
||||
export_assets_path_full = absolute_path_from_blend_file(os.path.join(project_root_path, assets_path)) #os.path.join(blend_file_folder_path, project_root_path, assets_path)
|
||||
#print("export_assets_path_full", export_assets_path_full)
|
||||
|
||||
#new_root_path = os.path.join(blend_file_folder_path, new_path)
|
||||
if target_path_name == 'export_root_path':
|
||||
if target_path_name == 'project_root_path':
|
||||
new_root_path_relative = os.path.relpath(new_path, blend_file_folder_path)
|
||||
new_root_path_absolute = new_path
|
||||
|
||||
print("new_root_path_relative", new_root_path_relative, new_root_path_absolute)
|
||||
#print("new_root_path_relative", new_root_path_relative, new_root_path_absolute)
|
||||
# first change the asset's path
|
||||
old_assets_paths_relative = getattr(operator, "export_assets_path", None)
|
||||
old_assets_paths_relative = getattr(operator, "assets_path", None)
|
||||
if old_assets_paths_relative is not None:
|
||||
old_assets_paths_absolute = os.path.abspath(os.path.join(export_root_path, old_assets_paths_relative))
|
||||
old_assets_paths_absolute = os.path.abspath(os.path.join(project_root_path, old_assets_paths_relative))
|
||||
new_assets_path_relative = os.path.relpath(old_assets_paths_absolute, new_root_path_absolute)
|
||||
new_assets_path_absolute = os.path.abspath(os.path.join(new_root_path_absolute, new_assets_path_relative))
|
||||
|
||||
print("old_assets_paths_absolute", old_assets_paths_absolute)
|
||||
"""print("old_assets_paths_absolute", old_assets_paths_absolute)
|
||||
print("new_assets_path_relative", new_assets_path_relative)
|
||||
print("new_assets_path_absolute", new_assets_path_absolute)
|
||||
setattr(operator, "export_assets_path", new_assets_path_relative)
|
||||
print("new_assets_path_absolute", new_assets_path_absolute)"""
|
||||
setattr(operator, "assets_path", new_assets_path_relative)
|
||||
|
||||
# we need to change all other relative paths (root => assets => blueprints/levels/materials etc)
|
||||
for path_name in asset_path_names:
|
||||
|
@ -80,8 +80,8 @@ class OT_OpenFolderbrowser(Operator, ImportHelper):
|
|||
|
||||
# store the root path as relative to the current blend file
|
||||
setattr(operator, target_path_name, new_root_path_relative)
|
||||
elif target_path_name == 'export_assets_path':
|
||||
new_assets_path_relative = os.path.relpath(new_path, export_root_path)
|
||||
elif target_path_name == 'assets_path':
|
||||
new_assets_path_relative = os.path.relpath(new_path, project_root_path)
|
||||
new_assets_path_absolute = new_path
|
||||
# we need to change all other relative paths (root => assets => blueprints/levels/materials etc)
|
||||
for path_name in asset_path_names:
|
||||
|
@ -98,7 +98,4 @@ class OT_OpenFolderbrowser(Operator, ImportHelper):
|
|||
relative_path = os.path.relpath(new_path, export_assets_path_full)
|
||||
setattr(operator, target_path_name, relative_path)
|
||||
|
||||
#filename, extension = os.path.splitext(self.filepath)
|
||||
|
||||
|
||||
return {'FINISHED'}
|
|
@ -46,16 +46,21 @@ class SCENES_LIST_OT_actions(Operator):
|
|||
('UP', "Up", ""),
|
||||
('DOWN', "Down", ""),
|
||||
('REMOVE', "Remove", ""),
|
||||
('ADD', "Add", ""))) # type: ignore
|
||||
('ADD', "Add", ""))
|
||||
) # type: ignore
|
||||
|
||||
|
||||
scene_type: bpy.props.StringProperty()# type: ignore #TODO: replace with enum
|
||||
scene_type: bpy.props.EnumProperty(
|
||||
items=(
|
||||
('LEVEL', "Level", ""),
|
||||
('LIBRARY', "Library", ""),
|
||||
)
|
||||
) # type: ignore
|
||||
|
||||
def invoke(self, context, event):
|
||||
source = context.window_manager.blenvy
|
||||
target_name = "library_scenes"
|
||||
target_index = "library_scenes_index"
|
||||
if self.scene_type == "level":
|
||||
if self.scene_type == "LEVEL":
|
||||
target_name = "main_scenes"
|
||||
target_index = "main_scenes_index"
|
||||
|
||||
|
@ -82,13 +87,14 @@ class SCENES_LIST_OT_actions(Operator):
|
|||
|
||||
elif self.action == 'REMOVE':
|
||||
info = 'Item "%s" removed from list' % (target[idx].name)
|
||||
setattr(source, target_index, current_index -1 )
|
||||
target.remove(idx)
|
||||
|
||||
setattr(source, target_index, current_index -1 )
|
||||
self.report({'INFO'}, info)
|
||||
|
||||
if self.action == 'ADD':
|
||||
new_scene_name = None
|
||||
if self.scene_type == "level":
|
||||
if self.scene_type == "LEVEL":
|
||||
if context.window_manager.main_scene:
|
||||
new_scene_name = context.window_manager.main_scene.name
|
||||
else:
|
||||
|
@ -96,17 +102,17 @@ class SCENES_LIST_OT_actions(Operator):
|
|||
new_scene_name = context.window_manager.library_scene.name
|
||||
if new_scene_name:
|
||||
item = target.add()
|
||||
item.name = new_scene_name#f"Rule {idx +1}"
|
||||
item.name = new_scene_name
|
||||
|
||||
if self.scene_type == "level":
|
||||
if self.scene_type == "LEVEL":
|
||||
context.window_manager.main_scene = None
|
||||
else:
|
||||
context.window_manager.library_scene = None
|
||||
|
||||
#name = f"Rule {idx +1}"
|
||||
#target.append({"name": name})
|
||||
setattr(source, target_index, len(target) - 1)
|
||||
#source[target_index] = len(target) - 1
|
||||
|
||||
|
||||
|
||||
info = '"%s" added to list' % (item.name)
|
||||
self.report({'INFO'}, info)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import bpy
|
||||
from ...settings import load_settings
|
||||
|
||||
import blenvy.bevy_components.ui as components_ui
|
||||
import blenvy.gltf_auto_export.ui as auto_export_ui
|
||||
from blenvy.settings import load_settings
|
||||
# from ...bevy_components.components import ui# as components_ui
|
||||
######################################################
|
||||
|
||||
## ui logic & co
|
||||
|
@ -17,7 +19,7 @@ def draw_folder_browser(layout, label, prop_origin, target_property):
|
|||
col.prop(prop_origin, target_property, text="")
|
||||
|
||||
folder_selector = row.operator("generic.open_folderbrowser", icon="FILE_FOLDER", text="")
|
||||
folder_selector.target_property = target_property #"export_root_path"
|
||||
folder_selector.target_property = target_property #"project_root_path"
|
||||
|
||||
# side panel
|
||||
class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
|
@ -42,7 +44,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||
library_scene_active = False
|
||||
active_collection = context.collection
|
||||
|
||||
current_auto_settings = load_settings(".gltf_auto_export_settings")
|
||||
"""current_auto_settings = load_settings(".gltf_auto_export_settings")
|
||||
current_gltf_settings = load_settings(".gltf_auto_export_gltf_settings")
|
||||
|
||||
if current_auto_settings is not None:
|
||||
|
@ -51,8 +53,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||
library_scene_names = current_auto_settings["library_scene_names"]
|
||||
|
||||
world_scene_active = context.scene.name in main_scene_names
|
||||
library_scene_active = context.scene.name in library_scene_names
|
||||
|
||||
library_scene_active = context.scene.name in library_scene_names"""
|
||||
|
||||
# Now to actual drawing of the UI
|
||||
target = row.box() if active_mode == 'COMPONENTS' else row
|
||||
|
@ -82,19 +83,19 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||
layout.label(text=blenvy.mode)"""
|
||||
|
||||
if blenvy.mode == "SETTINGS":
|
||||
header, panel = layout.panel("auto_export", default_closed=False)
|
||||
header, panel = layout.panel("common", default_closed=False)
|
||||
header.label(text="Common")
|
||||
if panel:
|
||||
row = panel.row()
|
||||
draw_folder_browser(layout=row, label="Root Folder", prop_origin=blenvy, target_property="export_root_path")
|
||||
draw_folder_browser(layout=row, label="Root Folder", prop_origin=blenvy, target_property="project_root_path")
|
||||
row = panel.row()
|
||||
draw_folder_browser(layout=row, label="Assets Folder", prop_origin=blenvy, target_property="export_assets_path")
|
||||
draw_folder_browser(layout=row, label="Assets Folder", prop_origin=blenvy, target_property="assets_path")
|
||||
row = panel.row()
|
||||
draw_folder_browser(layout=row, label="Blueprints Folder", prop_origin=blenvy, target_property="export_blueprints_path")
|
||||
draw_folder_browser(layout=row, label="Blueprints Folder", prop_origin=blenvy, target_property="blueprints_path")
|
||||
row = panel.row()
|
||||
draw_folder_browser(layout=row, label="Levels Folder", prop_origin=blenvy, target_property="export_levels_path")
|
||||
draw_folder_browser(layout=row, label="Levels Folder", prop_origin=blenvy, target_property="levels_path")
|
||||
row = panel.row()
|
||||
draw_folder_browser(layout=row, label="Materials Folder", prop_origin=blenvy, target_property="export_materials_path")
|
||||
draw_folder_browser(layout=row, label="Materials Folder", prop_origin=blenvy, target_property="materials_path")
|
||||
|
||||
panel.separator()
|
||||
# scenes selection
|
||||
|
@ -111,14 +112,14 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||
sub_row = col.row()
|
||||
add_operator = sub_row.operator("scene_list.list_action", icon='ADD', text="")
|
||||
add_operator.action = 'ADD'
|
||||
add_operator.scene_type = 'level'
|
||||
add_operator.scene_type = 'LEVEL'
|
||||
#add_operator.operator = operator
|
||||
sub_row.enabled = context.window_manager.main_scene is not None
|
||||
|
||||
sub_row = col.row()
|
||||
remove_operator = sub_row.operator("scene_list.list_action", icon='REMOVE', text="")
|
||||
remove_operator.action = 'REMOVE'
|
||||
remove_operator.scene_type = 'level'
|
||||
remove_operator.scene_type = 'LEVEL'
|
||||
col.separator()
|
||||
|
||||
# library scenes
|
||||
|
@ -133,41 +134,24 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
|||
sub_row = col.row()
|
||||
add_operator = sub_row.operator("scene_list.list_action", icon='ADD', text="")
|
||||
add_operator.action = 'ADD'
|
||||
add_operator.scene_type = 'library'
|
||||
add_operator.scene_type = 'LIBRARY'
|
||||
sub_row.enabled = context.window_manager.library_scene is not None
|
||||
|
||||
|
||||
sub_row = col.row()
|
||||
remove_operator = sub_row.operator("scene_list.list_action", icon='REMOVE', text="")
|
||||
remove_operator.action = 'REMOVE'
|
||||
remove_operator.scene_type = 'library'
|
||||
remove_operator.scene_type = 'LIBRARY'
|
||||
col.separator()
|
||||
|
||||
header, panel = layout.panel("components", default_closed=False)
|
||||
header.label(text="Components")
|
||||
if panel:
|
||||
components_ui.draw_settings_ui(panel, context.window_manager.components_registry)
|
||||
|
||||
"""if blenvy.mode == "SETTINGS":
|
||||
header, panel = layout.panel("auto_export", default_closed=False)
|
||||
header.label(text="Auto Export")
|
||||
if panel:
|
||||
layout = panel
|
||||
layout.label(text="MAKE SURE TO KEEP 'REMEMBER EXPORT SETTINGS' TOGGLED !!")
|
||||
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____"
|
||||
op.gltf_export_id = "gltf_auto_export" # we specify that we are in a special case
|
||||
|
||||
op = layout.operator("EXPORT_SCENES_OT_auto_gltf", text="Auto Export Settings")
|
||||
op.auto_export = True"""
|
||||
|
||||
"""header, panel = layout.panel("components", default_closed=False)
|
||||
header.label(text="Components")
|
||||
if panel:
|
||||
panel.label(text="YOOO")"""
|
||||
auto_export_ui.draw_settings_ui(panel, blenvy.auto_export)
|
||||
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||
blend_file_path = os.path.dirname(file_path)
|
||||
|
||||
# get the preferences for our addon
|
||||
export_root_path = getattr(addon_prefs, "export_root_path")
|
||||
export_assets_path = getattr(addon_prefs,"export_assets_path")
|
||||
project_root_path = getattr(addon_prefs, "project_root_path")
|
||||
assets_path = getattr(addon_prefs,"assets_path")
|
||||
|
||||
#should we use change detection or not
|
||||
export_change_detection = getattr(addon_prefs, "export_change_detection")
|
||||
|
@ -61,10 +61,10 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||
addon_prefs = SimpleNamespace(**tmp) #copy.deepcopy(addon_prefs)
|
||||
addon_prefs.__annotations__ = tmp"""
|
||||
# generate the actual complete output paths
|
||||
addon_prefs.export_assets_path_full = os.path.join(blend_file_path, export_root_path, export_assets_path)
|
||||
addon_prefs.export_blueprints_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_blueprints_path"))
|
||||
addon_prefs.export_levels_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_levels_path"))
|
||||
addon_prefs.export_materials_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"export_materials_path"))
|
||||
addon_prefs.export_assets_path_full = os.path.join(blend_file_path, project_root_path, assets_path)
|
||||
addon_prefs.export_blueprints_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"blueprints_path"))
|
||||
addon_prefs.export_levels_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"levels_path"))
|
||||
addon_prefs.export_materials_path_full = os.path.join(addon_prefs.export_assets_path_full, getattr(addon_prefs,"materials_path"))
|
||||
addon_prefs.export_gltf_extension = gltf_extension
|
||||
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
|
@ -76,8 +76,8 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||
|
||||
|
||||
# we inject the blueprints export path
|
||||
export_blueprints_path = getattr(addon_prefs,"export_blueprints_path")
|
||||
inject_export_path_into_internal_blueprints(internal_blueprints=blueprints_data.internal_blueprints, export_blueprints_path=export_blueprints_path, gltf_extension=gltf_extension)
|
||||
blueprints_path = getattr(addon_prefs,"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()
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
import json
|
||||
import bpy
|
||||
|
||||
"""
|
||||
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():
|
||||
# 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[".gltf_auto_export_gltf_settings_previous"] if ".gltf_auto_export_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[".gltf_auto_export_gltf_settings"] if ".gltf_auto_export_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")
|
||||
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
|
||||
|
||||
return changed
|
|
@ -6,13 +6,6 @@ from bpy.types import Operator
|
|||
from .preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
|
||||
from .auto_export import auto_export
|
||||
from ..helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_auto
|
||||
from ..helpers.serialize_scene import serialize_scene
|
||||
|
||||
def bubble_up_changes(object, changes_per_scene):
|
||||
if object.parent:
|
||||
changes_per_scene[object.parent.name] = bpy.data.objects[object.parent.name]
|
||||
bubble_up_changes(object.parent, changes_per_scene)
|
||||
|
||||
|
||||
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
||||
"""auto export gltf"""
|
||||
|
@ -27,8 +20,8 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
#list of settings (other than purely gltf settings) whose change should trigger a re-generation of gltf files
|
||||
white_list = [
|
||||
'auto_export',
|
||||
'export_root_path',
|
||||
'export_assets_path',
|
||||
'project_root_path',
|
||||
'assets_path',
|
||||
'export_change_detection',
|
||||
'export_scene_settings',
|
||||
|
||||
|
@ -36,15 +29,15 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
'library_scene_names',
|
||||
|
||||
'export_blueprints',
|
||||
'export_blueprints_path',
|
||||
'blueprints_path',
|
||||
'export_marked_assets',
|
||||
'collection_instances_combine_mode',
|
||||
|
||||
'export_levels_path',
|
||||
'levels_path',
|
||||
'export_separate_dynamic_and_static_objects',
|
||||
|
||||
'export_materials_library',
|
||||
'export_materials_path',
|
||||
'materials_path',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
|
@ -78,15 +71,11 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
export_props[k] = value
|
||||
# we add main & library scene names to our preferences
|
||||
|
||||
export_props['main_scene_names'] = list(map(lambda scene_data: scene_data.name, getattr(self,"main_scenes")))
|
||||
export_props['library_scene_names'] = list(map(lambda scene_data: scene_data.name, getattr(self,"library_scenes")))
|
||||
return export_props
|
||||
|
||||
def save_settings(self, context):
|
||||
print("save settings")
|
||||
auto_export_settings = self.format_settings()
|
||||
self.properties['main_scene_names'] = auto_export_settings['main_scene_names']
|
||||
self.properties['library_scene_names'] = auto_export_settings['library_scene_names']
|
||||
|
||||
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()
|
||||
|
@ -194,88 +183,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
return changed
|
||||
|
||||
def did_objects_change(self):
|
||||
# sigh... you need to save & reset the frame otherwise it saves the values AT THE CURRENT FRAME WHICH CAN DIFFER ACROSS SCENES
|
||||
current_frames = [scene.frame_current for scene in bpy.data.scenes]
|
||||
for scene in bpy.data.scenes:
|
||||
scene.frame_set(0)
|
||||
|
||||
current_scene = bpy.context.window.scene
|
||||
bpy.context.window.scene = bpy.data.scenes[0]
|
||||
#serialize scene at frame 0
|
||||
"""with bpy.context.temp_override(scene=bpy.data.scenes[1]):
|
||||
bpy.context.scene.frame_set(0)"""
|
||||
current = serialize_scene()
|
||||
bpy.context.window.scene = current_scene
|
||||
|
||||
# reset previous frames
|
||||
for (index, scene) in enumerate(bpy.data.scenes):
|
||||
scene.frame_set(int(current_frames[index]))
|
||||
|
||||
previous_stored = bpy.data.texts[".TESTING"] if ".TESTING" in bpy.data.texts else None # bpy.data.texts.new(".TESTING")
|
||||
if previous_stored == None:
|
||||
previous_stored = bpy.data.texts.new(".TESTING")
|
||||
previous_stored.write(current)
|
||||
return {}
|
||||
previous = json.loads(previous_stored.as_string())
|
||||
current = json.loads(current)
|
||||
|
||||
changes_per_scene = {}
|
||||
# TODO : how do we deal with changed scene names ???
|
||||
for scene in current:
|
||||
# print('scene', scene)
|
||||
previous_object_names = list(previous[scene].keys())
|
||||
current_object_names =list(current[scene].keys())
|
||||
#print("previous_object_names", len(previous_object_names), previous_object_names)
|
||||
#print("current_object_names", len(current_object_names), current_object_names)
|
||||
|
||||
"""if len(previous_object_names) > len(current_object_names):
|
||||
print("removed")
|
||||
if len(current_object_names) > len(previous_object_names):
|
||||
print("added")"""
|
||||
added = list(set(current_object_names) - set(previous_object_names))
|
||||
removed = list(set(previous_object_names) - set(current_object_names))
|
||||
"""print("removed", removed)
|
||||
print("added",added)"""
|
||||
for obj in added:
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
changes_per_scene[scene][obj] = bpy.data.objects[obj]
|
||||
# TODO: how do we deal with this, as we obviously do not have data for removed objects ?
|
||||
for obj in removed:
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
changes_per_scene[scene][obj] = None # bpy.data.objects[obj]
|
||||
|
||||
for object_name in list(current[scene].keys()): # todo : exclude directly added/removed objects
|
||||
#print("ob", object_name)
|
||||
if object_name in previous[scene]:
|
||||
# print("object", object_name,"in previous scene, comparing")
|
||||
current_obj = current[scene][object_name]
|
||||
prev_obj = previous[scene][object_name]
|
||||
same = str(current_obj) == str(prev_obj)
|
||||
|
||||
if "Camera" in object_name:
|
||||
pass#print(" current", current_obj, prev_obj)
|
||||
"""if "Fox" in object_name:
|
||||
print(" current", current_obj)
|
||||
print(" previou", prev_obj)
|
||||
print(" same?", same)"""
|
||||
#print("foo", same)
|
||||
if not same:
|
||||
""" print(" current", current_obj)
|
||||
print(" previou", prev_obj)"""
|
||||
if not scene in changes_per_scene:
|
||||
changes_per_scene[scene] = {}
|
||||
|
||||
changes_per_scene[scene][object_name] = bpy.data.objects[object_name]
|
||||
bubble_up_changes(bpy.data.objects[object_name], changes_per_scene[scene])
|
||||
# now bubble up for instances & parents
|
||||
previous_stored.clear()
|
||||
previous_stored.write(json.dumps(current))
|
||||
|
||||
print("changes per scene alternative", changes_per_scene)
|
||||
return changes_per_scene
|
||||
|
||||
pass
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||
|
@ -286,7 +194,6 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
#print("self", self.auto_export)
|
||||
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
|
||||
if self.direct_mode: #Do not auto export when applying settings in the menu, do it on save only
|
||||
# determine changed objects
|
||||
|
@ -310,67 +217,6 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
|||
wm = context.window_manager
|
||||
#wm.fileselect_add(self)
|
||||
return context.window_manager.invoke_props_dialog(self, title="Auto export", width=640)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
"""def modal(self, context, event):
|
||||
|
||||
if event.type == 'SPACE':
|
||||
wm = context.window_manager
|
||||
wm.invoke_popup(self)
|
||||
#wm.invoke_props_dialog(self)
|
||||
|
||||
if event.type in {'ESC'}:
|
||||
return {'CANCELLED'}
|
||||
|
||||
return {'RUNNING_MODAL'}"""
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
operator = self
|
||||
|
||||
controls_enabled = self.auto_export
|
||||
|
||||
layout.prop(self, "auto_export")
|
||||
layout.separator()
|
||||
|
||||
toggle_icon = "TRIA_DOWN" if self.show_general_settings else "TRIA_RIGHT"
|
||||
layout.prop(self, "show_general_settings", text="General", icon=toggle_icon)
|
||||
if self.show_general_settings:
|
||||
section = layout.box()
|
||||
section.enabled = controls_enabled
|
||||
section.prop(operator, "export_scene_settings")
|
||||
toggle_icon = "TRIA_DOWN" if self.show_change_detection_settings else "TRIA_RIGHT"
|
||||
layout.prop(operator, "show_change_detection_settings", text="Change Detection", icon=toggle_icon)
|
||||
if self.show_change_detection_settings:
|
||||
section = layout.box()
|
||||
section.enabled = controls_enabled
|
||||
section.prop(operator, "export_change_detection", text="Use change detection")
|
||||
|
||||
toggle_icon = "TRIA_DOWN" if self.show_blueprint_settings else "TRIA_RIGHT"
|
||||
layout.prop(operator, "show_blueprint_settings", text="Blueprints", icon=toggle_icon)
|
||||
if self.show_blueprint_settings:
|
||||
section = layout.box()
|
||||
section.enabled = controls_enabled
|
||||
section.prop(operator, "export_blueprints")
|
||||
|
||||
section = section.box()
|
||||
section.enabled = controls_enabled and self.export_blueprints
|
||||
|
||||
# collections/blueprints
|
||||
section.prop(operator, "collection_instances_combine_mode")
|
||||
section.prop(operator, "export_marked_assets")
|
||||
section.separator()
|
||||
|
||||
section.prop(operator, "export_separate_dynamic_and_static_objects")
|
||||
section.separator()
|
||||
|
||||
# materials
|
||||
section.prop(operator, "export_materials_library")
|
||||
section = section.box()
|
||||
section.enabled = controls_enabled and self.export_materials_library
|
||||
#section.prop(operator, "export_materials_path")
|
||||
|
||||
|
||||
def cancel(self, context):
|
||||
print("cancel")
|
||||
|
|
|
@ -14,8 +14,8 @@ AutoExportGltfPreferenceNames = [
|
|||
|
||||
'show_general_settings',
|
||||
'auto_export',
|
||||
'export_root_path',
|
||||
'export_assets_path',
|
||||
'project_root_path',
|
||||
'assets_path',
|
||||
'export_scene_settings',
|
||||
|
||||
'show_change_detection_settings',
|
||||
|
@ -31,21 +31,21 @@ AutoExportGltfPreferenceNames = [
|
|||
|
||||
'show_blueprint_settings',
|
||||
'export_blueprints',
|
||||
'export_blueprints_path',
|
||||
'blueprints_path',
|
||||
'export_marked_assets',
|
||||
'collection_instances_combine_mode',
|
||||
|
||||
'export_levels_path',
|
||||
'levels_path',
|
||||
'export_separate_dynamic_and_static_objects',
|
||||
|
||||
'export_materials_library',
|
||||
'export_materials_path',
|
||||
'materials_path',
|
||||
]
|
||||
|
||||
def on_export_output_folder_updated(self, context):
|
||||
#self.export_root_path = os.path.relpath(self.export_root_path)
|
||||
#self.export_assets_path = os.path.join(self.export_root_path, self.export_assets_path)
|
||||
print("on_foo_updated", self.export_root_path, self.export_assets_path)
|
||||
#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__'
|
||||
|
@ -80,7 +80,7 @@ class AutoExportGltfAddonPreferences(AddonPreferences):
|
|||
default=True
|
||||
) # type: ignore
|
||||
|
||||
export_root_path: StringProperty(
|
||||
project_root_path: StringProperty(
|
||||
name = "Project Root Path",
|
||||
description="The root folder of your (Bevy) project (not assets!)",
|
||||
# subtype='DIR_PATH',
|
||||
|
@ -88,7 +88,7 @@ class AutoExportGltfAddonPreferences(AddonPreferences):
|
|||
#update=on_export_output_folder_updated) # type: ignore
|
||||
)
|
||||
|
||||
export_assets_path: StringProperty(
|
||||
assets_path: StringProperty(
|
||||
name='Export folder',
|
||||
description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ',
|
||||
default='./assets',
|
||||
|
@ -139,14 +139,14 @@ class AutoExportGltfAddonPreferences(AddonPreferences):
|
|||
default=True
|
||||
) # type: ignore
|
||||
|
||||
export_blueprints_path: StringProperty(
|
||||
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
|
||||
|
||||
export_levels_path: StringProperty(
|
||||
levels_path: StringProperty(
|
||||
name='Levels path',
|
||||
description='path to export the levels (main scenes) to (relative to the assets folder)',
|
||||
default='levels',
|
||||
|
@ -167,7 +167,7 @@ class AutoExportGltfAddonPreferences(AddonPreferences):
|
|||
default=False
|
||||
) # type: ignore
|
||||
|
||||
export_materials_path: StringProperty(
|
||||
materials_path: StringProperty(
|
||||
name='Materials path',
|
||||
description='path to export the materials libraries to (relative to the assets folder)',
|
||||
default='materials',
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import bpy
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty)
|
||||
|
||||
class AutoExportSettings(PropertyGroup):
|
||||
# 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
|
||||
export_change_detection: BoolProperty(
|
||||
name='Change detection',
|
||||
description='Use change detection to determine what/if should be exported',
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
# scenes
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
""" 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
|
|
@ -0,0 +1,67 @@
|
|||
def draw_settings_ui(layout, auto_export_settings):
|
||||
controls_enabled = auto_export_settings.auto_export
|
||||
|
||||
layout.prop(auto_export_settings, "auto_export")
|
||||
layout.separator()
|
||||
|
||||
header, panel = layout.panel("General", default_closed=False)
|
||||
header.label(text="General")
|
||||
if panel:
|
||||
section = panel.box()
|
||||
section.enabled = controls_enabled
|
||||
|
||||
op = section.operator("EXPORT_SCENE_OT_gltf", text="Gltf Settings (KEEP 'REMEMBER EXPORT SETTINGS' TOGGLED)")#'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____"
|
||||
op.gltf_export_id = "gltf_auto_export" # we specify that we are in a special case
|
||||
|
||||
section.prop(auto_export_settings, "export_scene_settings")
|
||||
|
||||
header, panel = layout.panel("Change Detection", default_closed=False)
|
||||
header.label(text="Change Detection")
|
||||
if panel:
|
||||
section = panel.box()
|
||||
section.enabled = controls_enabled
|
||||
section.prop(auto_export_settings, "export_change_detection", text="Use change detection")
|
||||
|
||||
header, panel = layout.panel("Blueprints", default_closed=False)
|
||||
header.label(text="Blueprints")
|
||||
if panel:
|
||||
section = layout.box()
|
||||
section.enabled = controls_enabled
|
||||
section.prop(auto_export_settings, "export_blueprints")
|
||||
|
||||
section = section.box()
|
||||
section.enabled = controls_enabled and auto_export_settings.export_blueprints
|
||||
|
||||
# collections/blueprints
|
||||
section.prop(auto_export_settings, "collection_instances_combine_mode")
|
||||
section.prop(auto_export_settings, "export_marked_assets")
|
||||
section.separator()
|
||||
|
||||
section.prop(auto_export_settings, "export_separate_dynamic_and_static_objects")
|
||||
section.separator()
|
||||
|
||||
# materials
|
||||
section.prop(auto_export_settings, "export_materials_library")
|
||||
section = section.box()
|
||||
section.enabled = controls_enabled and auto_export_settings.export_materials_library
|
||||
#section.prop(auto_export_settings, "materials_path")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
from typing import Set
|
||||
import bpy
|
||||
######################################################
|
||||
## ui logic & co
|
||||
|
||||
# side panel that opens auto_export specific gltf settings & the auto export settings themselves
|
||||
class GLTF_PT_auto_export_SidePanel(bpy.types.Panel):
|
||||
bl_idname = "GLTF_PT_auto_export_SidePanel"
|
||||
bl_label = "Auto export"
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Auto Export"
|
||||
bl_context = "objectmode"
|
||||
bl_parent_id = "BLENVY_PT_SidePanel"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.window_manager.blenvy.mode == 'SETTINGS'
|
||||
|
||||
"""def draw_header(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text="Auto export ")"""
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text="MAKE SURE TO KEEP 'REMEMBER EXPORT SETTINGS' TOGGLED !!")
|
||||
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____"
|
||||
op.gltf_export_id = "gltf_auto_export" # we specify that we are in a special case
|
||||
|
||||
op = layout.operator("EXPORT_SCENES_OT_auto_gltf", text="Auto Export Settings")
|
||||
op.auto_export = True
|
||||
|
||||
# main ui in the file => export
|
||||
class GLTF_PT_auto_export_main(bpy.types.Panel):
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = ""
|
||||
bl_parent_id = "FILE_PT_operator"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
sfile = context.space_data
|
||||
operator = sfile.active_operator
|
||||
|
||||
return operator.bl_idname == "EXPORT_SCENES_OT_auto_gltf"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
class GLTF_PT_auto_export_root(bpy.types.Panel):
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = "Auto export"
|
||||
bl_parent_id = "GLTF_PT_auto_export_main"
|
||||
#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"
|
||||
|
||||
def draw_header(self, context):
|
||||
sfile = context.space_data
|
||||
operator = sfile.active_operator
|
||||
self.layout.prop(operator, "auto_export", text="")
|
||||
|
||||
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
|
||||
layout.prop(operator, 'will_save_settings')
|
||||
|
||||
class GLTF_PT_auto_export_general(bpy.types.Panel):
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = "General"
|
||||
bl_parent_id = "GLTF_PT_auto_export_root"
|
||||
|
||||
@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
|
||||
layout.prop(operator, "export_assets_path")
|
||||
layout.prop(operator, "export_scene_settings")
|
||||
|
||||
|
||||
class GLTF_PT_auto_export_change_detection(bpy.types.Panel):
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = "Change detection"
|
||||
bl_parent_id = "GLTF_PT_auto_export_root"
|
||||
|
||||
@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_header(self, context):
|
||||
layout = self.layout
|
||||
sfile = context.space_data
|
||||
operator = sfile.active_operator
|
||||
layout.prop(operator, "export_change_detection", text="")
|
||||
|
||||
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
|
||||
layout.prop(operator, "export_change_detection")
|
||||
|
||||
class GLTF_PT_auto_export_blueprints(bpy.types.Panel):
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = "Blueprints"
|
||||
bl_parent_id = "GLTF_PT_auto_export_root"
|
||||
|
||||
@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_header(self, context):
|
||||
layout = self.layout
|
||||
sfile = context.space_data
|
||||
operator = sfile.active_operator
|
||||
layout.prop(operator, "export_blueprints", text="")
|
||||
|
||||
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
|
||||
|
||||
# collections/blueprints
|
||||
layout.prop(operator, "export_blueprints_path")
|
||||
layout.prop(operator, "collection_instances_combine_mode")
|
||||
layout.prop(operator, "export_marked_assets")
|
||||
layout.prop(operator, "export_separate_dynamic_and_static_objects")
|
||||
layout.separator()
|
||||
# materials
|
||||
layout.prop(operator, "export_materials_library")
|
||||
layout.prop(operator, "export_materials_path")
|
||||
|
|
@ -2,12 +2,42 @@ import json
|
|||
import bpy
|
||||
|
||||
def upsert_settings(name, data):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else bpy.data.texts.new(name)
|
||||
stored_settings.clear()
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None#bpy.data.texts.new(name)
|
||||
if stored_settings is None:
|
||||
stored_settings = bpy.data.texts.new(name)
|
||||
stored_settings.write(json.dumps(data))
|
||||
else:
|
||||
current_settings = json.loads(stored_settings.as_string())
|
||||
current_settings = {**current_settings, **data}
|
||||
stored_settings.clear()
|
||||
stored_settings.write(json.dumps(current_settings))
|
||||
|
||||
def load_settings(name):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
|
||||
if stored_settings != None:
|
||||
return json.loads(stored_settings.as_string())
|
||||
return None
|
||||
|
||||
# checks if old & new settings (dicts really) are identical
|
||||
def are_settings_identical(old, new, white_list=None):
|
||||
if old is None and new is None:
|
||||
return True
|
||||
if old is None and new is not None:
|
||||
return False
|
||||
if old is not None and new is None:
|
||||
return False
|
||||
|
||||
old_items = sorted(old.items())
|
||||
new_items = sorted(new.items())
|
||||
if white_list is not None:
|
||||
old_items_override = {}
|
||||
new_items_override = {}
|
||||
for key in white_list:
|
||||
if key in old_items:
|
||||
old_items_override[key] = old_items[key]
|
||||
if key in new_items:
|
||||
new_items_override[key] = new_items[key]
|
||||
old_items = old_items_override
|
||||
new_items = new_items_override
|
||||
|
||||
return old_items != new_items if new is not None else False
|
|
@ -103,10 +103,10 @@ def test_export_complex(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(root_path),
|
||||
#export_blueprints_path = os.path.join("assets", "models", "library"),
|
||||
project_root_path = os.path.abspath(root_path),
|
||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
||||
export_output_folder = os.path.join("assets", "models"), #"./models",
|
||||
#export_levels_path = os.path.join("assets", "models"),
|
||||
#levels_path = os.path.join("assets", "models"),
|
||||
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
|
|
@ -53,10 +53,10 @@ def test_export_external_blueprints(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(root_path),
|
||||
#export_blueprints_path = os.path.join("assets", "models", "library"),
|
||||
project_root_path = os.path.abspath(root_path),
|
||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
||||
#export_output_folder = os.path.join("assets", "models"), #"./models",
|
||||
#export_levels_path = os.path.join("assets", "models"),
|
||||
#levels_path = os.path.join("assets", "models"),
|
||||
|
||||
export_scene_settings=False,
|
||||
export_blueprints=True,
|
||||
|
|
|
@ -82,7 +82,7 @@ def test_export_no_parameters(setup_data):
|
|||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_materials_library=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
)
|
||||
|
||||
|
@ -104,7 +104,7 @@ def test_export_auto_export_parameters_only(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_materials_library=True
|
||||
)
|
||||
|
@ -140,7 +140,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -159,7 +159,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -184,7 +184,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -200,7 +200,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -229,7 +229,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -245,7 +245,7 @@ def test_export_changed_parameters(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
|
|
@ -11,7 +11,7 @@ from .setup_data import setup_data
|
|||
|
||||
def test_components_should_generate_correct_custom_properties(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
type_infos = registry.type_infos
|
||||
|
@ -58,7 +58,7 @@ def test_components_should_generate_correct_custom_properties(setup_data):
|
|||
|
||||
def test_components_should_generate_correct_custom_properties_with_randomized_values(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
type_infos = registry.type_infos
|
||||
|
@ -108,7 +108,7 @@ def test_components_should_generate_correct_custom_properties_with_randomized_va
|
|||
|
||||
def test_components_should_generate_correct_propertyGroup_values_from_custom_properties(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
type_infos = registry.type_infos
|
||||
|
@ -166,7 +166,7 @@ def test_components_should_generate_correct_propertyGroup_values_from_custom_pro
|
|||
|
||||
def test_remove_components(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
type_infos = registry.type_infos
|
||||
|
@ -207,7 +207,7 @@ def test_remove_components(setup_data):
|
|||
def test_copy_paste_components(setup_data):
|
||||
context = bpy.context
|
||||
registry = context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
long_name = "bevy_example::test_components::BasicTest"
|
||||
|
|
|
@ -80,7 +80,7 @@ def test_export_do_not_export_blueprints(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="assets/models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=False,
|
||||
|
@ -107,11 +107,11 @@ def test_export_custom_blueprints_path(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
export_blueprints_path = "assets/other_blueprints"
|
||||
blueprints_path = "assets/other_blueprints"
|
||||
)
|
||||
assert os.path.exists(os.path.join(setup_data["levels_path"], "World.glb")) == True
|
||||
assert os.path.exists(os.path.join(setup_data["root_path"],"assets", "other_blueprints", "Blueprint1.glb")) == True
|
||||
|
@ -133,7 +133,7 @@ def test_export_materials_library(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -160,12 +160,12 @@ def test_export_materials_library_custom_path(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
export_materials_library = True,
|
||||
export_materials_path="assets/other_materials"
|
||||
materials_path="assets/other_materials"
|
||||
)
|
||||
|
||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "Blueprint1.glb")) == True
|
||||
|
@ -192,7 +192,7 @@ def test_export_collection_instances_combine_mode(setup_data): # There is more i
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_blueprints=True,
|
||||
collection_instances_combine_mode = 'Embed'
|
||||
|
@ -219,7 +219,7 @@ def test_export_do_not_export_marked_assets(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -253,7 +253,7 @@ def test_export_separate_dynamic_and_static_objects(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
@ -281,7 +281,7 @@ def test_export_should_not_generate_orphan_data(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
|
|
@ -29,7 +29,7 @@ def run_auto_export(setup_data):
|
|||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
export_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
project_root_path = os.path.abspath(setup_data["root_path"]),
|
||||
export_output_folder="./models",
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
|
|
|
@ -3,7 +3,7 @@ from .setup_data import setup_data
|
|||
|
||||
def test_blend(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
long_name = "bevy_example::test_components::BasicTest"
|
||||
|
|
|
@ -24,7 +24,7 @@ def get_component_propGroup(registry, component_name, component_meta):
|
|||
|
||||
def test_rename_component_single_unit_struct(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
@ -47,7 +47,7 @@ def test_rename_component_single_unit_struct(setup_data):
|
|||
|
||||
def test_rename_component_single_complex_struct(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
@ -70,7 +70,7 @@ def test_rename_component_single_complex_struct(setup_data):
|
|||
|
||||
def test_rename_component_bulk(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
@ -95,7 +95,7 @@ def test_rename_component_bulk(setup_data):
|
|||
|
||||
def test_rename_component_single_error_handling(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
@ -125,7 +125,7 @@ def test_rename_component_single_error_handling(setup_data):
|
|||
|
||||
def test_rename_component_single_error_handling_clean_errors(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
|
Loading…
Reference in New Issue