mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-26 21:37:01 +00:00
Compare commits
No commits in common. "2470736f81533a1f2d89bf86fdbe3020d954379a" and "008f6b3a88a51f1b35fc83ad46d7dbbb6b72dcf7" have entirely different histories.
2470736f81
...
008f6b3a88
@ -66,21 +66,16 @@ Components:
|
||||
- [ ] handle missing types in registry for keys & values
|
||||
|
||||
- [ ] Add correct upgrade handling from individual component to bevy_components
|
||||
- [ ] Settings handling:
|
||||
- [ ] move saveable settings out to a settings file
|
||||
- [ ] update save & load
|
||||
- [ ] add handling of polling frequency & enabling
|
||||
|
||||
|
||||
General things to solve:
|
||||
- [x] save settings
|
||||
- [x] load settings
|
||||
- [ ] add blueprints data
|
||||
- [ ] add_blueprints_data
|
||||
|
||||
- [x] rename all path stuff using the old naming convention : "blueprints_path_full"
|
||||
- [x] generate the full paths directly when setting them in the UI
|
||||
- [x] problem : how to deal with defaults: do it on start/load ?
|
||||
- [x] filter out scenes that have already been used in scenes list
|
||||
|
||||
General issues:
|
||||
- there is no safeguard for naming collisions for naming across blender files
|
||||
@ -88,12 +83,6 @@ General issues:
|
||||
- "parents" can only be blueprints
|
||||
- they normally need/have unique export paths (otherwise, user error, perhaps show it ?)
|
||||
- perhaps a simple hashing of the parent's path would be enought
|
||||
- [ ] addon-prefs => settings
|
||||
|
||||
|
||||
- [x] addon-prefs => settings
|
||||
- [x] generate_gltf_export_preferences => should not use add-on prefs at all ? since we are not overriding gltf settings that way anymore ?
|
||||
- [x] remove hard coded path for standard gltf settings
|
||||
- [x] load settings on file load
|
||||
- [x] auto_export
|
||||
- [x] components
|
||||
- [ ] add handling of errors when trying to load settings
|
||||
- [ ] generate_gltf_export_preferences => should not use add-on prefs at all ? since we are not overriding gltf settings that way anymore ?
|
@ -17,21 +17,23 @@ from bpy.props import (StringProperty)
|
||||
|
||||
|
||||
# components management
|
||||
from .add_ons.bevy_components.components.operators import CopyComponentOperator, Fix_Component_Operator, OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator, GenerateComponent_From_custom_property_Operator, PasteComponentOperator, AddComponentOperator, RenameHelper, Toggle_ComponentVisibility
|
||||
from .add_ons.bevy_components.registry.registry import ComponentsRegistry,MissingBevyType
|
||||
from .add_ons.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 .add_ons.bevy_components.registry.ui import (BEVY_COMPONENTS_PT_Configuration, BEVY_COMPONENTS_PT_AdvancedToolsPanel, BEVY_COMPONENTS_PT_MissingTypesPanel, MISSING_TYPES_UL_List)
|
||||
from .add_ons.bevy_components.components.metadata import (ComponentMetadata, ComponentsMeta)
|
||||
from .add_ons.bevy_components.components.lists import GENERIC_LIST_OT_actions, Generic_LIST_OT_AddItem, Generic_LIST_OT_RemoveItem, Generic_LIST_OT_SelectItem
|
||||
from .add_ons.bevy_components.components.maps import GENERIC_MAP_OT_actions
|
||||
from .add_ons.bevy_components.components.definitions_list import (ComponentDefinitionsList, ClearComponentDefinitionsList)
|
||||
from .add_ons.bevy_components.components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
|
||||
from .add_ons.bevy_components.settings import ComponentsSettings
|
||||
from .bevy_components.components.operators import CopyComponentOperator, Fix_Component_Operator, OT_rename_component, RemoveComponentFromAllItemsOperator, 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_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)
|
||||
from .bevy_components.components.lists import GENERIC_LIST_OT_actions, Generic_LIST_OT_AddItem, Generic_LIST_OT_RemoveItem, Generic_LIST_OT_SelectItem
|
||||
from .bevy_components.components.maps import GENERIC_MAP_OT_actions
|
||||
from .bevy_components.components.definitions_list import (ComponentDefinitionsList, ClearComponentDefinitionsList)
|
||||
from .bevy_components.components.ui import (BEVY_COMPONENTS_PT_ComponentsPanel)
|
||||
|
||||
# auto export
|
||||
from .add_ons.auto_export import gltf_post_export_callback
|
||||
from .add_ons.auto_export.export.tracker import AutoExportTracker
|
||||
from .add_ons.auto_export.settings import AutoExportSettings
|
||||
from .gltf_auto_export import gltf_post_export_callback
|
||||
from .gltf_auto_export.auto_export.operators import AutoExportGLTF
|
||||
from .gltf_auto_export.auto_export.tracker import AutoExportTracker
|
||||
from .gltf_auto_export.settings import AutoExportSettings
|
||||
|
||||
# asset management
|
||||
from .assets.ui import Blenvy_assets
|
||||
@ -68,7 +70,6 @@ classes = [
|
||||
BLENVY_PT_SidePanel,
|
||||
|
||||
# bevy components
|
||||
ComponentsSettings,
|
||||
AddComponentOperator,
|
||||
CopyComponentOperator,
|
||||
PasteComponentOperator,
|
||||
@ -112,8 +113,8 @@ classes = [
|
||||
|
||||
GENERIC_MAP_OT_actions,
|
||||
|
||||
|
||||
# gltf auto export
|
||||
AutoExportGLTF,
|
||||
AutoExportTracker,
|
||||
AutoExportSettings,
|
||||
|
||||
@ -145,7 +146,9 @@ def post_save(scene, depsgraph):
|
||||
|
||||
@persistent
|
||||
def post_load(file_name):
|
||||
print("POST LOAD")
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
if registry is not None:
|
||||
registry.load_settings()
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
if blenvy is not None:
|
||||
blenvy.load_settings()
|
||||
|
@ -1,131 +0,0 @@
|
||||
import os
|
||||
import bpy
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty)
|
||||
from blenvy.settings import load_settings, upsert_settings, generate_complete_preferences_dict
|
||||
from .propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
from .components.metadata import ensure_metadata_for_all_items
|
||||
|
||||
# list of settings we do NOT want to save
|
||||
settings_black_list = ['settings_save_enabled', 'watcher_active']
|
||||
|
||||
def save_settings(settings, context):
|
||||
if settings.settings_save_enabled:
|
||||
settings_dict = generate_complete_preferences_dict(settings, ComponentsSettings, [])
|
||||
print("save settings", settings, context,settings_dict)
|
||||
upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list})
|
||||
|
||||
# helper function to deal with timer
|
||||
def toggle_watcher(self, context):
|
||||
#print("toggling watcher", self.watcher_enabled, watch_schema, self, bpy.app.timers)
|
||||
if not self.watcher_enabled:
|
||||
try:
|
||||
bpy.app.timers.unregister(watch_schema)
|
||||
except Exception as error:
|
||||
pass
|
||||
else:
|
||||
self.watcher_active = True
|
||||
bpy.app.timers.register(watch_schema)
|
||||
save_settings(self, context)
|
||||
|
||||
def watch_schema():
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
component_settings = blenvy.components
|
||||
#print("watching schema file for changes")
|
||||
try:
|
||||
stamp = os.stat(component_settings.schema_path_full).st_mtime
|
||||
stamp = str(stamp)
|
||||
if stamp != component_settings.schemaTimeStamp and component_settings.schemaTimeStamp != "":
|
||||
print("FILE CHANGED !!", stamp, component_settings.schemaTimeStamp)
|
||||
# see here for better ways : https://stackoverflow.com/questions/11114492/check-if-a-file-is-not-open-nor-being-used-by-another-process
|
||||
"""try:
|
||||
os.rename(path, path)
|
||||
#return False
|
||||
except OSError: # file is in use
|
||||
print("in use")
|
||||
#return True"""
|
||||
#bpy.ops.object.reload_registry()
|
||||
# we need to add an additional delay as the file might not have loaded yet
|
||||
bpy.app.timers.register(lambda: bpy.ops.object.reload_registry(), first_interval=1)
|
||||
component_settings.schemaTimeStamp = stamp
|
||||
except Exception as error:
|
||||
pass
|
||||
return component_settings.watcher_poll_frequency if component_settings.watcher_enabled else None
|
||||
|
||||
|
||||
class ComponentsSettings(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_components_settings" # where to store data in bpy.texts
|
||||
settings_save_enabled: BoolProperty(name="settings save enabled", default=True)# type: ignore
|
||||
|
||||
schema_path: StringProperty(
|
||||
name="schema path",
|
||||
description="path to the registry schema file",
|
||||
default="registry.json",
|
||||
update=save_settings
|
||||
)# type: ignore
|
||||
|
||||
schema_path_full: StringProperty(
|
||||
name="schema full path",
|
||||
description="path to the registry schema file",
|
||||
get=lambda self: os.path.abspath(os.path.join(os.path.dirname(bpy.data.filepath), self.schema_path))
|
||||
) # type: ignore
|
||||
|
||||
watcher_enabled: BoolProperty(name="Watcher_enabled", default=True, update=toggle_watcher)# type: ignore
|
||||
watcher_active: BoolProperty(name = "Flag for watcher status", default = False)# type: ignore
|
||||
|
||||
watcher_poll_frequency: IntProperty(
|
||||
name="watcher poll frequency",
|
||||
description="frequency (s) at wich to poll for changes to the registry file",
|
||||
min=1,
|
||||
max=10,
|
||||
default=1,
|
||||
update=save_settings
|
||||
)# type: ignore
|
||||
|
||||
schemaTimeStamp: StringProperty(
|
||||
name="last timestamp of schema file",
|
||||
description="",
|
||||
default="",
|
||||
update=save_settings
|
||||
)# type: ignore
|
||||
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
pass
|
||||
#bpy.context.window_manager.blenvy.components.watcher_active = False
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
bpy.context.window_manager.blenvy.components.watcher_active = False
|
||||
try:
|
||||
bpy.app.timers.unregister(watch_schema)
|
||||
except Exception as error:
|
||||
pass
|
||||
|
||||
def start_schema_watcher(self):
|
||||
# start timer
|
||||
if not self.watcher_active and self.watcher_enabled:
|
||||
self.watcher_active = True
|
||||
print("registering function", watch_schema)
|
||||
bpy.app.timers.register(watch_schema)
|
||||
|
||||
def load_settings(self):
|
||||
settings = load_settings(self.settings_save_path)
|
||||
print("component settings", settings)
|
||||
if settings is not None:
|
||||
self.settings_save_enabled = False # we disable auto_saving of our settings
|
||||
try:
|
||||
for setting in settings:
|
||||
print("setting", setting, settings[setting])
|
||||
setattr(self, setting, settings[setting])
|
||||
except:pass
|
||||
try:
|
||||
registry = bpy.context.components_registry
|
||||
registry.load_schema()
|
||||
generate_propertyGroups_for_components()
|
||||
ensure_metadata_for_all_items()
|
||||
except:pass
|
||||
|
||||
self.settings_save_enabled = True
|
@ -1,20 +0,0 @@
|
||||
def draw_settings_ui(layout, component_settings):
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.enabled = False
|
||||
col.prop(component_settings, "schema_path", 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="blenvy.reload_components_registry", text="reload registry" , icon="FILE_REFRESH")
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
|
||||
row.prop(component_settings, "watcher_enabled", text="enable registry file polling")
|
||||
row.prop(component_settings, "watcher_poll_frequency", text="registry file poll frequency (s)")
|
||||
|
||||
layout.separator()
|
||||
layout.separator()
|
@ -4,12 +4,12 @@ import bpy
|
||||
|
||||
from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list
|
||||
|
||||
def scan_assets(scene, blueprints_data, settings):
|
||||
project_root_path = getattr(settings, "project_root_path")
|
||||
export_output_folder = getattr(settings,"export_output_folder")
|
||||
levels_path = getattr(settings,"levels_path")
|
||||
blueprints_path = getattr(settings, "blueprints_path")
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension")
|
||||
def scan_assets(scene, blueprints_data, addon_prefs):
|
||||
project_root_path = getattr(addon_prefs, "project_root_path")
|
||||
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
||||
levels_path = getattr(addon_prefs,"levels_path")
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
|
||||
relative_blueprints_path = os.path.relpath(blueprints_path, project_root_path)
|
||||
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, None)
|
||||
@ -61,9 +61,9 @@ def get_userTextures():
|
||||
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
|
||||
print("textures", textures)
|
||||
|
||||
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
|
||||
blueprints_path = getattr(settings, "blueprints_path")
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension")
|
||||
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, addon_prefs):
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
assets_list = []
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
|
||||
assets_list.append({"name": child_blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True,"internal":blueprint.local, "parent": blueprint.name})
|
||||
|
||||
# and add sub stuff
|
||||
sub_assets_lists = get_blueprint_assets_tree(child_blueprint, blueprints_data, parent=child_blueprint.name, settings=settings)
|
||||
sub_assets_lists = get_blueprint_assets_tree(child_blueprint, blueprints_data, parent=child_blueprint.name, addon_prefs=addon_prefs)
|
||||
assets_list += sub_assets_lists
|
||||
|
||||
direct_assets = get_user_assets_as_list(blueprint.collection)
|
||||
@ -90,9 +90,9 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
|
||||
assets_list += direct_assets
|
||||
return assets_list
|
||||
|
||||
def get_main_scene_assets_tree(main_scene, blueprints_data, settings):
|
||||
blueprints_path = getattr(settings, "blueprints_path")
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension")
|
||||
def get_main_scene_assets_tree(main_scene, blueprints_data, addon_prefs):
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_main_scene.get(main_scene.name, None)
|
||||
|
||||
assets_list = get_user_assets_as_list(main_scene)
|
||||
@ -109,7 +109,7 @@ def get_main_scene_assets_tree(main_scene, blueprints_data, settings):
|
||||
if blueprint_exported_path is not None and not does_asset_exist(assets_list, blueprint_exported_path):
|
||||
assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True, "internal":blueprint.local, "parent": None})
|
||||
|
||||
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, settings=settings)
|
||||
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, addon_prefs=addon_prefs)
|
||||
|
||||
print("TOTAL ASSETS", assets_list)
|
||||
return assets_list
|
||||
|
@ -52,6 +52,7 @@ class OT_add_bevy_asset(Operator):
|
||||
) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
assets = []
|
||||
blueprint_assets = self.target_type == 'BLUEPRINT'
|
||||
target = None
|
||||
if blueprint_assets:
|
||||
@ -60,9 +61,7 @@ class OT_add_bevy_asset(Operator):
|
||||
target = bpy.data.scenes[self.target_name]
|
||||
assets = get_user_assets(target)
|
||||
asset = {"name": self.asset_name, "type": self.asset_type, "path": self.asset_path}
|
||||
print('assets', assets, target)
|
||||
if not does_asset_exist(target, asset):
|
||||
print("add asset", target, asset)
|
||||
upsert_asset(target, asset)
|
||||
|
||||
#assets.append({"name": self.asset_name, "type": self.asset_type, "path": self.asset_path, "internal": False})
|
||||
@ -203,7 +202,7 @@ class OT_test_bevy_assets(Operator):
|
||||
blenvy = context.window_manager.blenvy
|
||||
settings = blenvy
|
||||
blueprints_registry = context.window_manager.blueprints_registry
|
||||
blueprints_registry.refresh_blueprints()
|
||||
blueprints_registry.add_blueprints_data()
|
||||
blueprints_data = blueprints_registry.blueprints_data
|
||||
|
||||
for scene in blenvy.main_scenes:
|
||||
|
@ -74,7 +74,7 @@ class Blenvy_assets(bpy.types.Panel):
|
||||
|
||||
asset_registry = context.window_manager.assets_registry
|
||||
blueprints_registry = context.window_manager.blueprints_registry
|
||||
#blueprints_registry.refresh_blueprints()
|
||||
blueprints_registry.add_blueprints_data()
|
||||
blueprints_data = blueprints_registry.blueprints_data
|
||||
|
||||
name = "world"
|
||||
@ -85,12 +85,9 @@ class Blenvy_assets(bpy.types.Panel):
|
||||
settings = SimpleNamespace(**settings)
|
||||
|
||||
if panel:
|
||||
#print("dfs")
|
||||
for scene_selector in blenvy.main_scenes:
|
||||
scene = bpy.data.scenes[scene_selector.name]
|
||||
for scene in blenvy.main_scenes:
|
||||
#get_main_scene_assets_tree(scene, blueprints_data, settings)
|
||||
user_assets = get_user_assets(scene)
|
||||
#print("user assets", user_assets, scene)
|
||||
row = panel.row()
|
||||
scene_assets_panel = draw_assets(layout=row, name=scene.name, title=f"{scene.name} Assets", asset_registry=asset_registry, user_assets=user_assets, target_type="SCENE", target_name=scene.name)
|
||||
"""if scene.name in blueprints_data.blueprint_instances_per_main_scene:
|
||||
|
@ -4,14 +4,14 @@ from bpy_types import (Operator)
|
||||
from bpy.props import (StringProperty)
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
from blenvy.settings import upsert_settings
|
||||
from ...settings import upsert_settings
|
||||
|
||||
from ..components.metadata import apply_customProperty_values_to_item_propertyGroups, apply_propertyGroup_values_to_item_customProperties, ensure_metadata_for_all_items
|
||||
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
|
||||
class ReloadRegistryOperator(Operator):
|
||||
"""Reloads registry (schema file) from disk, generates propertyGroups for components & ensures all objects have metadata """
|
||||
bl_idname = "blenvy.reload_components_registry"
|
||||
bl_idname = "object.reload_registry"
|
||||
bl_label = "Reload Registry"
|
||||
bl_options = {"UNDO"}
|
||||
|
||||
@ -191,8 +191,10 @@ class OT_OpenSchemaFileBrowser(Operator, ImportHelper):
|
||||
folder_path = os.path.dirname(file_path)
|
||||
relative_path = os.path.relpath(self.filepath, folder_path)
|
||||
|
||||
registry = context.window_manager.components_registry
|
||||
registry.schemaPath = relative_path
|
||||
|
||||
blenvy = context.window_manager.blenvy
|
||||
blenvy.components.schema_path = relative_path
|
||||
upsert_settings(blenvy.settings_save_path, {"components_schemaPath": relative_path})
|
||||
|
||||
return {'FINISHED'}
|
||||
@ -204,14 +206,14 @@ class OT_select_object(Operator):
|
||||
bl_label = "Select object"
|
||||
bl_options = {"UNDO"}
|
||||
|
||||
target_name: StringProperty(
|
||||
name="target name",
|
||||
description="target to select's name ",
|
||||
object_name: StringProperty(
|
||||
name="object_name",
|
||||
description="object to select's name ",
|
||||
) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
if self.target_name:
|
||||
object = bpy.data.objects[self.target_name]
|
||||
if self.object_name:
|
||||
object = bpy.data.objects[self.object_name]
|
||||
scenes_of_object = list(object.users_scene)
|
||||
if len(scenes_of_object) > 0:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
@ -5,7 +5,10 @@ import uuid
|
||||
from pathlib import Path
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||
from ..components.metadata import ComponentMetadata
|
||||
|
||||
from ...settings import load_settings
|
||||
from ..propGroups.prop_groups import generate_propertyGroups_for_components
|
||||
from ..components.metadata import ComponentMetadata, ensure_metadata_for_all_items
|
||||
|
||||
# helper class to store missing bevy types information
|
||||
class MissingBevyType(bpy.types.PropertyGroup):
|
||||
@ -13,9 +16,58 @@ class MissingBevyType(bpy.types.PropertyGroup):
|
||||
name="type",
|
||||
) # type: ignore
|
||||
|
||||
# helper function to deal with timer
|
||||
def toggle_watcher(self, context):
|
||||
#print("toggling watcher", self.watcher_enabled, watch_schema, self, bpy.app.timers)
|
||||
if not self.watcher_enabled:
|
||||
try:
|
||||
bpy.app.timers.unregister(watch_schema)
|
||||
except Exception as error:
|
||||
pass
|
||||
else:
|
||||
self.watcher_active = True
|
||||
bpy.app.timers.register(watch_schema)
|
||||
|
||||
def watch_schema():
|
||||
self = bpy.context.window_manager.components_registry
|
||||
# print("watching schema file for changes")
|
||||
try:
|
||||
stamp = os.stat(self.schemaFullPath).st_mtime
|
||||
stamp = str(stamp)
|
||||
if stamp != self.schemaTimeStamp and self.schemaTimeStamp != "":
|
||||
print("FILE CHANGED !!", stamp, self.schemaTimeStamp)
|
||||
# see here for better ways : https://stackoverflow.com/questions/11114492/check-if-a-file-is-not-open-nor-being-used-by-another-process
|
||||
"""try:
|
||||
os.rename(path, path)
|
||||
#return False
|
||||
except OSError: # file is in use
|
||||
print("in use")
|
||||
#return True"""
|
||||
#bpy.ops.object.reload_registry()
|
||||
# we need to add an additional delay as the file might not have loaded yet
|
||||
bpy.app.timers.register(lambda: bpy.ops.object.reload_registry(), first_interval=1)
|
||||
|
||||
self.schemaTimeStamp = stamp
|
||||
except Exception as error:
|
||||
pass
|
||||
return self.watcher_poll_frequency if self.watcher_enabled else None
|
||||
|
||||
|
||||
# this is where we store the information for all available components
|
||||
class ComponentsRegistry(PropertyGroup):
|
||||
|
||||
settings_save_path = ".bevy_components_settings" # where to store data in bpy.texts
|
||||
|
||||
schemaPath: bpy.props.StringProperty(
|
||||
name="schema path",
|
||||
description="path to the registry schema file",
|
||||
default="registry.json"
|
||||
)# type: ignore
|
||||
schemaFullPath : bpy.props.StringProperty(
|
||||
name="schema full path",
|
||||
description="path to the registry schema file",
|
||||
)# type: ignore
|
||||
|
||||
registry: bpy.props. StringProperty(
|
||||
name="registry",
|
||||
description="component registry"
|
||||
@ -28,6 +80,25 @@ class ComponentsRegistry(PropertyGroup):
|
||||
|
||||
disable_all_object_updates: BoolProperty(name="disable_object_updates", default=False) # type: ignore
|
||||
|
||||
## file watcher
|
||||
watcher_enabled: BoolProperty(name="Watcher_enabled", default=True, update=toggle_watcher)# type: ignore
|
||||
watcher_active: BoolProperty(name = "Flag for watcher status", default = False)# type: ignore
|
||||
|
||||
watcher_poll_frequency: IntProperty(
|
||||
name="watcher poll frequency",
|
||||
description="frequency (s) at wich to poll for changes to the registry file",
|
||||
min=1,
|
||||
max=10,
|
||||
default=1
|
||||
)# type: ignore
|
||||
|
||||
schemaTimeStamp: StringProperty(
|
||||
name="last timestamp of schema file",
|
||||
description="",
|
||||
default=""
|
||||
)# type: ignore
|
||||
|
||||
|
||||
missing_types_list: CollectionProperty(name="missing types list", type=MissingBevyType)# type: ignore
|
||||
missing_types_list_index: IntProperty(name = "Index for missing types list", default = 0)# type: ignore
|
||||
|
||||
@ -146,22 +217,29 @@ class ComponentsRegistry(PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
bpy.types.WindowManager.components_registry = PointerProperty(type=ComponentsRegistry)
|
||||
bpy.context.window_manager.components_registry.watcher_active = False
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
bpy.context.window_manager.components_registry.watcher_active = False
|
||||
|
||||
for propgroup_name in cls.component_propertyGroups.keys():
|
||||
try:
|
||||
delattr(ComponentMetadata, propgroup_name)
|
||||
#print("unregistered propertyGroup", propgroup_name)
|
||||
except Exception as error:
|
||||
pass
|
||||
#print("failed to remove", error, "ComponentMetadata")
|
||||
|
||||
try:
|
||||
bpy.app.timers.unregister(watch_schema)
|
||||
except Exception as error:
|
||||
pass
|
||||
|
||||
del bpy.types.WindowManager.components_registry
|
||||
|
||||
def load_schema(self):
|
||||
print("load schema", self)
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
component_settings = blenvy.components
|
||||
|
||||
# cleanup previous data if any
|
||||
self.propGroupIdCounter = 0
|
||||
self.long_names_to_propgroup_names.clear()
|
||||
@ -173,13 +251,23 @@ class ComponentsRegistry(PropertyGroup):
|
||||
self.invalid_components.clear()
|
||||
|
||||
# now prepare paths to load data
|
||||
file_path = bpy.data.filepath
|
||||
# Get the folder
|
||||
folder_path = os.path.dirname(file_path)
|
||||
path = os.path.join(folder_path, self.schemaPath)
|
||||
self.schemaFullPath = path
|
||||
|
||||
with open(component_settings.schema_path_full) as f:
|
||||
f = Path(bpy.path.abspath(path)) # make a path object of abs path
|
||||
with open(path) as f:
|
||||
data = json.load(f)
|
||||
defs = data["$defs"]
|
||||
self.registry = json.dumps(defs) # FIXME:meh ?
|
||||
|
||||
component_settings.start_schema_watcher()
|
||||
# start timer
|
||||
if not self.watcher_active and self.watcher_enabled:
|
||||
self.watcher_active = True
|
||||
print("registering function", watch_schema)
|
||||
bpy.app.timers.register(watch_schema)
|
||||
|
||||
|
||||
# we load the json once, so we do not need to do it over & over again
|
||||
@ -190,6 +278,17 @@ class ComponentsRegistry(PropertyGroup):
|
||||
def has_type_infos(self):
|
||||
return len(self.type_infos.keys()) != 0
|
||||
|
||||
def load_settings(self):
|
||||
print("loading settings")
|
||||
settings = load_settings(self.settings_save_path)
|
||||
|
||||
if settings!= None:
|
||||
self.schemaPath = settings["components_schemaPath"]
|
||||
self.load_schema()
|
||||
generate_propertyGroups_for_components()
|
||||
ensure_metadata_for_all_items()
|
||||
|
||||
|
||||
# we keep a list of component propertyGroup around
|
||||
def register_component_propertyGroup(self, name, propertyGroup):
|
||||
self.component_propertyGroups[name] = propertyGroup
|
@ -3,13 +3,13 @@ import bpy
|
||||
from bpy_types import (UIList)
|
||||
from bpy.props import (StringProperty)
|
||||
|
||||
from ..utils import get_selection_type
|
||||
|
||||
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator
|
||||
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator
|
||||
from .operators import(
|
||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
|
||||
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT,
|
||||
OT_OpenSchemaFileBrowser, ReloadRegistryOperator,
|
||||
OT_OpenSchemaFileBrowser,
|
||||
OT_select_component_name_to_replace,
|
||||
OT_select_object, ReloadRegistryOperator,
|
||||
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL,
|
||||
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT)
|
||||
|
||||
@ -32,24 +32,23 @@ class BEVY_COMPONENTS_PT_Configuration(bpy.types.Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
registry = context.window_manager.components_registry
|
||||
blenvy = context.window_manager.blenvy
|
||||
component_settings = blenvy.components
|
||||
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.enabled = False
|
||||
col.prop(component_settings, "schema_path", text="Registry Schema path")
|
||||
col.prop(registry, "schemaPath", text="Registry Schema path")
|
||||
col = row.column()
|
||||
col.operator("blenvy.open_schemafilebrowser", text="Browse for registry schema file (json)")
|
||||
col.operator(OT_OpenSchemaFileBrowser.bl_idname, text="Browse for registry schema file (json)")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("blenvy.reload_components_registry", text="reload registry" , icon="FILE_REFRESH")
|
||||
layout.operator(ReloadRegistryOperator.bl_idname, text="reload registry" , icon="FILE_REFRESH")
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
|
||||
row.prop(component_settings, "watcher_enabled", text="enable registry file polling")
|
||||
row.prop(component_settings, "watcher_poll_frequency", text="registry file poll frequency (s)")
|
||||
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()
|
||||
@ -79,7 +78,7 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
|
||||
col.label(text=item)
|
||||
|
||||
|
||||
def draw_invalid_or_unregistered(self, layout, status, component_name, target):
|
||||
def draw_invalid_or_unregistered(self, layout, status, component_name, object):
|
||||
available_components = bpy.context.window_manager.components_list
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry_has_type_infos = registry.has_type_infos()
|
||||
@ -90,8 +89,8 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
|
||||
col.label(text=component_name)
|
||||
|
||||
col = row.column()
|
||||
operator = col.operator("object.select", text=target.name)
|
||||
operator.target_name = target.name
|
||||
operator = col.operator(OT_select_object.bl_idname, text=object.name)
|
||||
operator.object_name = object.name
|
||||
|
||||
col = row.column()
|
||||
col.label(text=status)
|
||||
@ -100,24 +99,22 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
|
||||
col.prop(available_components, "list", text="")
|
||||
|
||||
col = row.column()
|
||||
operator = col.operator("object.rename_bevy_component", text="", icon="SHADERFX") #rename
|
||||
operator = col.operator(OT_rename_component.bl_idname, text="", icon="SHADERFX") #rename
|
||||
new_name = registry.type_infos[available_components.list]['long_name'] if available_components.list in registry.type_infos else ""
|
||||
operator.original_name = component_name
|
||||
operator.target_objects = json.dumps([target.name])
|
||||
operator.target_objects = json.dumps([object.name])
|
||||
operator.new_name = new_name
|
||||
col.enabled = registry_has_type_infos and component_name != "" and component_name != new_name
|
||||
|
||||
|
||||
col = row.column()
|
||||
operator = col.operator("object.remove_bevy_component", text="", icon="X")
|
||||
operator.item_name = target.name
|
||||
operator = col.operator(RemoveComponentOperator.bl_idname, text="", icon="X")
|
||||
operator.object_name = object.name
|
||||
operator.component_name = component_name
|
||||
operator.item_type = get_selection_type(target)
|
||||
|
||||
|
||||
col = row.column()
|
||||
col = row.column()
|
||||
operator = col.operator("object.select_component_name_to_replace", text="", icon="EYEDROPPER") #text="select for rename",
|
||||
operator = col.operator(OT_select_component_name_to_replace.bl_idname, text="", icon="EYEDROPPER") #text="select for rename",
|
||||
operator.component_name = component_name
|
||||
|
||||
def draw(self, context):
|
19
tools/blenvy/bevy_components/ui.py
Normal file
19
tools/blenvy/bevy_components/ui.py
Normal file
@ -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()
|
@ -25,12 +25,12 @@ def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
||||
blueprint.collection["export_path"] = blueprint_exported_path
|
||||
|
||||
def inject_blueprints_list_into_main_scene(scene, blueprints_data, settings):
|
||||
project_root_path = getattr(settings, "project_root_path")
|
||||
assets_path = getattr(settings,"assets_path")
|
||||
levels_path = getattr(settings,"levels_path")
|
||||
blueprints_path = getattr(settings, "blueprints_path")
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension")
|
||||
def inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs):
|
||||
project_root_path = getattr(addon_prefs, "project_root_path")
|
||||
assets_path = getattr(addon_prefs,"assets_path")
|
||||
levels_path = getattr(addon_prefs,"levels_path")
|
||||
blueprints_path = getattr(addon_prefs, "blueprints_path")
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
|
||||
# print("injecting assets/blueprints data into scene")
|
||||
assets_list_name = f"assets_list_{scene.name}_components"
|
||||
|
@ -8,20 +8,9 @@ from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||
|
||||
from ..settings import load_settings
|
||||
from ..core.scene_helpers import get_main_and_library_scenes
|
||||
from ..gltf_auto_export.helpers.helpers_scenes import get_scenes
|
||||
from .blueprints_scan import blueprints_scan
|
||||
|
||||
|
||||
|
||||
def refresh_blueprints():
|
||||
try:
|
||||
blueprints_registry = bpy.context.window_manager.blueprints_registry
|
||||
blueprints_registry.refresh_blueprints()
|
||||
#print('refresh blueprints')
|
||||
except:pass
|
||||
|
||||
return 3
|
||||
|
||||
# this is where we store the information for all available Blueprints
|
||||
class BlueprintsRegistry(PropertyGroup):
|
||||
blueprints_data = {}
|
||||
@ -51,25 +40,17 @@ class BlueprintsRegistry(PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
bpy.types.WindowManager.blueprints_registry = PointerProperty(type=BlueprintsRegistry)
|
||||
bpy.app.timers.register(refresh_blueprints)
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
try:
|
||||
bpy.app.timers.unregister(refresh_blueprints)
|
||||
except: pass
|
||||
|
||||
del bpy.types.WindowManager.blueprints_registry
|
||||
|
||||
|
||||
def add_blueprint(self, blueprint):
|
||||
self.blueprints_list.append(blueprint)
|
||||
|
||||
def refresh_blueprints(self):
|
||||
def add_blueprints_data(self):
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
settings = blenvy
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
||||
blueprints_data = blueprints_scan(level_scenes, library_scenes, settings)
|
||||
addon_prefs = blenvy
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
blueprints_data = blueprints_scan(level_scenes, library_scenes, addon_prefs)
|
||||
self.blueprints_data = blueprints_data
|
||||
"""for blueprint in blueprints_data.blueprints:
|
||||
self.add_blueprint(blueprint)"""
|
||||
|
@ -7,8 +7,8 @@ from .blueprint import Blueprint
|
||||
# - marked as asset
|
||||
# - with the "auto_export" flag
|
||||
# https://blender.stackexchange.com/questions/167878/how-to-get-all-collections-of-the-current-scene
|
||||
def blueprints_scan(main_scenes, library_scenes, settings):
|
||||
export_marked_assets = getattr(settings.auto_export, "export_marked_assets")
|
||||
def blueprints_scan(main_scenes, library_scenes, addon_prefs):
|
||||
export_marked_assets = getattr(addon_prefs.auto_export,"export_marked_assets")
|
||||
|
||||
blueprints = {}
|
||||
blueprints_from_objects = {}
|
||||
|
@ -14,18 +14,15 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.window_manager.blenvy.mode == 'BLUEPRINTS' if 'blenvy' in context.window_manager else False
|
||||
return context.window_manager.blenvy.mode == 'BLUEPRINTS'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
asset_registry = context.window_manager.assets_registry
|
||||
blueprint_registry = context.window_manager.blueprints_registry
|
||||
|
||||
blueprint_registry.refresh_blueprints()
|
||||
|
||||
for blueprint in blueprint_registry.blueprints_data.blueprints:
|
||||
for blueprint in context.window_manager.blueprints_registry.blueprints_list:
|
||||
row = layout.row()
|
||||
row.label(icon="RIGHTARROW")
|
||||
row.label(text=blueprint.name)
|
||||
|
@ -1,48 +1,31 @@
|
||||
import os
|
||||
import bpy
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (BoolProperty, EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, CollectionProperty, IntProperty)
|
||||
from .scene_helpers import SceneSelector
|
||||
from ..settings import upsert_settings, load_settings, generate_complete_preferences_dict
|
||||
import blenvy.add_ons.auto_export.settings as auto_export_settings
|
||||
import blenvy.add_ons.bevy_components.settings as component_settings
|
||||
from ..settings import upsert_settings, load_settings
|
||||
import blenvy.gltf_auto_export.settings as auto_export_settings
|
||||
|
||||
|
||||
# list of settings we do NOT want to save
|
||||
settings_black_list = ['settings_save_enabled', 'main_scene_selector', 'main_scenes', 'main_scenes_index', 'library_scene_selector', 'library_scenes', 'library_scenes_index',
|
||||
#'project_root_path_full', 'assets_path_full', ''
|
||||
]
|
||||
|
||||
def save_settings(settings, context):
|
||||
if settings.settings_save_enabled:
|
||||
settings_dict = generate_complete_preferences_dict(settings, BlenvyManager, [])
|
||||
print("save settings", settings, context, settings_dict)
|
||||
# upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list})
|
||||
|
||||
def update_scene_lists(blenvy, context):
|
||||
def update_scene_lists(self, context):
|
||||
blenvy = self# context.window_manager.blenvy
|
||||
blenvy.main_scene_names = [scene.name for scene in blenvy.main_scenes] # FIXME: unsure
|
||||
blenvy.library_scene_names = [scene.name for scene in blenvy.library_scenes] # FIXME: unsure
|
||||
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(blenvy, context):
|
||||
def update_asset_folders(self, context):
|
||||
blenvy = self # 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(blenvy, context):
|
||||
def update_mode(self, context):
|
||||
blenvy = self
|
||||
upsert_settings(blenvy.settings_save_path, {"mode": blenvy.mode })
|
||||
|
||||
def is_scene_already_in_use(self, scene):
|
||||
try:
|
||||
return scene.name not in self.main_scenes and scene.name not in self.library_scenes
|
||||
except:
|
||||
return True
|
||||
|
||||
class BlenvyManager(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_common_settings" # where to store data in bpy.texts
|
||||
settings_save_enabled = BoolProperty(name="settings save enabled", default=True)
|
||||
settings_save_path = ".blenvy_settings" # where to store data in bpy.texts
|
||||
|
||||
mode: EnumProperty(
|
||||
items=(
|
||||
@ -118,29 +101,37 @@ class BlenvyManager(PropertyGroup):
|
||||
|
||||
main_scenes: CollectionProperty(name="main scenes", type=SceneSelector) # type: ignore
|
||||
main_scenes_index: IntProperty(name = "Index for main scenes list", default = 0, update=update_scene_lists) # type: ignore
|
||||
#main_scene_names = [] # FIXME: unsure
|
||||
main_scene_names = [] # FIXME: unsure
|
||||
|
||||
library_scenes: CollectionProperty(name="library scenes", type=SceneSelector) # type: ignore
|
||||
library_scenes_index: IntProperty(name = "Index for library scenes list", default = 0, update=update_scene_lists) # type: ignore
|
||||
#library_scene_names = [] # FIXME: unsure
|
||||
library_scene_names = [] # FIXME: unsure
|
||||
|
||||
# sub ones
|
||||
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
|
||||
components: PointerProperty(type=component_settings.ComponentsSettings) # type: ignore
|
||||
#components: PointerProperty(type=bevy_component_settings.ComponentSettings) # type: ignore
|
||||
|
||||
main_scene_selector: PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
||||
library_scene_selector: PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=is_scene_already_in_use)# type: ignore
|
||||
def is_scene_ok(self, scene):
|
||||
try:
|
||||
operator = bpy.context.space_data.active_operator
|
||||
return scene.name not in operator.main_scenes and scene.name not in operator.library_scenes
|
||||
except:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
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.blenvy = PointerProperty(type=BlenvyManager)
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
del bpy.types.WindowManager.blenvy
|
||||
del bpy.types.WindowManager.main_scene
|
||||
del bpy.types.WindowManager.library_scene
|
||||
|
||||
def load_settings(self):
|
||||
print("LOAD SETTINGS")
|
||||
settings = load_settings(self.settings_save_path)
|
||||
if settings is not None:
|
||||
if "mode" in settings:
|
||||
@ -158,9 +149,3 @@ class BlenvyManager(PropertyGroup):
|
||||
for asset_path_name in asset_path_names:
|
||||
if asset_path_name in settings:
|
||||
setattr(self, asset_path_name, settings[asset_path_name])
|
||||
|
||||
# now load auto_export settings
|
||||
self.auto_export.load_settings()
|
||||
|
||||
# now load component settings
|
||||
self.components.load_settings()
|
||||
|
@ -8,7 +8,7 @@ class OT_switch_bevy_tooling(Operator):
|
||||
"""Switch bevy tooling"""
|
||||
bl_idname = "bevy.tooling_switch"
|
||||
bl_label = "Switch bevy tooling"
|
||||
#bl_options = {}
|
||||
bl_options = {"UNDO"}
|
||||
|
||||
|
||||
tool: EnumProperty(
|
||||
|
@ -7,23 +7,6 @@ class SceneSelector(bpy.types.PropertyGroup):
|
||||
display: bpy.props.BoolProperty() # type: ignore
|
||||
|
||||
|
||||
# convenience utility to get lists of scenes
|
||||
def get_main_and_library_scenes(settings):
|
||||
level_scene_names= getattr(settings, "main_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
|
||||
library_scene_names = getattr(settings, "library_scene_names", []) #list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
|
||||
|
||||
level_scene_names= list(map(lambda scene: scene.name, getattr(settings,"main_scenes")))
|
||||
library_scene_names = list(map(lambda scene: scene.name, getattr(settings,"library_scenes")))
|
||||
|
||||
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
|
||||
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
||||
|
||||
level_scenes = list(map(lambda name: bpy.data.scenes[name], level_scene_names))
|
||||
library_scenes = list(map(lambda name: bpy.data.scenes[name], library_scene_names))
|
||||
|
||||
return [level_scene_names, level_scenes, library_scene_names, library_scenes]
|
||||
|
||||
|
||||
def add_scene_property(scene, scene_component_name, property_data, limit_to=None):
|
||||
root_collection = scene.collection
|
||||
scene_property = None
|
||||
|
@ -95,19 +95,19 @@ class SCENES_LIST_OT_actions(Operator):
|
||||
if self.action == 'ADD':
|
||||
new_scene_name = None
|
||||
if self.scene_type == "LEVEL":
|
||||
if context.window_manager.blenvy.main_scene_selector:
|
||||
new_scene_name = context.window_manager.blenvy.main_scene_selector.name
|
||||
if context.window_manager.main_scene:
|
||||
new_scene_name = context.window_manager.main_scene.name
|
||||
else:
|
||||
if context.window_manager.blenvy.library_scene_selector:
|
||||
new_scene_name = context.window_manager.blenvy.library_scene_selector.name
|
||||
if context.window_manager.library_scene:
|
||||
new_scene_name = context.window_manager.library_scene.name
|
||||
if new_scene_name:
|
||||
item = target.add()
|
||||
item.name = new_scene_name
|
||||
|
||||
if self.scene_type == "LEVEL":
|
||||
context.window_manager.blenvy.main_scene_selector = None
|
||||
context.window_manager.main_scene = None
|
||||
else:
|
||||
context.window_manager.blenvy.library_scene_selector = None
|
||||
context.window_manager.library_scene = None
|
||||
|
||||
setattr(source, target_index, len(target) - 1)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import bpy
|
||||
import blenvy.add_ons.bevy_components.ui as components_ui
|
||||
import blenvy.add_ons.auto_export.ui as auto_export_ui
|
||||
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
|
||||
######################################################
|
||||
|
||||
@ -104,7 +105,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
rows = 2
|
||||
row = section.row()
|
||||
row.label(text="main scenes")
|
||||
row.prop(blenvy, "main_scene_selector", text='')
|
||||
row.prop(context.window_manager, "main_scene", text='')
|
||||
|
||||
row = section.row()
|
||||
row.template_list("SCENE_UL_Blenvy", "level scenes", blenvy, "main_scenes", blenvy, "main_scenes_index", rows=rows)
|
||||
@ -115,7 +116,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
add_operator.action = 'ADD'
|
||||
add_operator.scene_type = 'LEVEL'
|
||||
#add_operator.operator = operator
|
||||
sub_row.enabled = blenvy.main_scene_selector is not None
|
||||
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="")
|
||||
@ -126,7 +127,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
# library scenes
|
||||
row = section.row()
|
||||
row.label(text="library scenes")
|
||||
row.prop(blenvy, "library_scene_selector", text='')
|
||||
row.prop(context.window_manager, "library_scene", text='')
|
||||
|
||||
row = section.row()
|
||||
row.template_list("SCENE_UL_Blenvy", "library scenes", blenvy, "library_scenes", blenvy, "library_scenes_index", rows=rows)
|
||||
@ -136,7 +137,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
add_operator = sub_row.operator("scene_list.list_action", icon='ADD', text="")
|
||||
add_operator.action = 'ADD'
|
||||
add_operator.scene_type = 'LIBRARY'
|
||||
sub_row.enabled = blenvy.library_scene_selector is not None
|
||||
sub_row.enabled = context.window_manager.library_scene is not None
|
||||
|
||||
|
||||
sub_row = col.row()
|
||||
@ -148,7 +149,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
|
||||
header, panel = layout.panel("components", default_closed=False)
|
||||
header.label(text="Components")
|
||||
if panel:
|
||||
components_ui.draw_settings_ui(panel, blenvy.components)
|
||||
components_ui.draw_settings_ui(panel, context.window_manager.components_registry)
|
||||
|
||||
header, panel = layout.panel("auto_export", default_closed=False)
|
||||
header.label(text="Auto Export")
|
||||
|
@ -4,7 +4,7 @@ import bpy
|
||||
from .helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_gltf
|
||||
|
||||
def cleanup_file():
|
||||
gltf_filepath = bpy.context.window_manager.auto_export_tracker.dummy_file_path
|
||||
gltf_filepath = "/home/ckaos/projects/bevy/Blender_bevy_components_worklflow/testing/bevy_example/assets/____dummy____.glb"
|
||||
if os.path.exists(gltf_filepath):
|
||||
os.remove(gltf_filepath)
|
||||
return None
|
||||
@ -14,39 +14,38 @@ def cleanup_file():
|
||||
def gltf_post_export_callback(data):
|
||||
#print("post_export", data)
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
tracker = bpy.context.window_manager.auto_export_tracker
|
||||
tracker.export_finished()
|
||||
bpy.context.window_manager.auto_export_tracker.export_finished()
|
||||
|
||||
gltf_settings_backup = tracker.gltf_settings_backup
|
||||
gltf_settings_backup = blenvy.auto_export.gltf_settings_backup
|
||||
gltf_filepath = data["gltf_filepath"]
|
||||
gltf_export_id = data['gltf_export_id']
|
||||
if gltf_export_id == "gltf_auto_export":
|
||||
# some more absurdity: apparently the file is not QUITE done when the export callback is called, so we have to introduce this timer to remove the temporary file correctly
|
||||
tracker.dummy_file_path = gltf_filepath
|
||||
bpy.context.window_manager.auto_export_tracker.dummy_file_path = gltf_filepath
|
||||
try:
|
||||
bpy.app.timers.unregister(cleanup_file)
|
||||
except:pass
|
||||
bpy.app.timers.register(cleanup_file, first_interval=2)
|
||||
bpy.app.timers.register(cleanup_file, first_interval=1)
|
||||
|
||||
# get the parameters
|
||||
scene = bpy.context.scene
|
||||
if "glTF2ExportSettings" in scene:
|
||||
settings = scene["glTF2ExportSettings"]
|
||||
gltf_export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||
# now write new settings
|
||||
gltf_export_settings.clear()
|
||||
export_settings.clear()
|
||||
|
||||
current_gltf_settings = generate_complete_preferences_dict_gltf(dict(settings))
|
||||
gltf_export_settings.write(json.dumps(current_gltf_settings))
|
||||
export_settings.write(json.dumps(current_gltf_settings))
|
||||
# now reset the original gltf_settings
|
||||
if gltf_settings_backup != "":
|
||||
scene["glTF2ExportSettings"] = json.loads(gltf_settings_backup)
|
||||
else:
|
||||
if "glTF2ExportSettings" in scene:
|
||||
del scene["glTF2ExportSettings"]
|
||||
tracker.gltf_settings_backup = ""
|
||||
blenvy.auto_export.gltf_settings_backup = ""
|
||||
|
||||
# the absurd length one has to go through to RESET THE OPERATOR because it has global state !!!!! AAAAAHHH
|
||||
last_operator = tracker.last_operator
|
||||
last_operator = bpy.context.window_manager.auto_export_tracker.last_operator
|
||||
last_operator.filepath = ""
|
||||
last_operator.gltf_export_id = ""
|
@ -3,22 +3,23 @@ import os
|
||||
import bpy
|
||||
import traceback
|
||||
|
||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
||||
from blenvy.blueprints.blueprints_scan import blueprints_scan
|
||||
from blenvy.blueprints.blueprint_helpers import inject_export_path_into_internal_blueprints
|
||||
from ..helpers.helpers_scenes import (get_scenes, )
|
||||
|
||||
from .get_blueprints_to_export import get_blueprints_to_export
|
||||
from .get_levels_to_export import get_levels_to_export
|
||||
from .export_gltf import get_standard_exporter_settings
|
||||
from .get_standard_exporter_settings import get_standard_exporter_settings
|
||||
|
||||
from .export_main_scenes import export_main_scene
|
||||
from .export_blueprints import export_blueprints
|
||||
from .export_materials import cleanup_materials, export_materials
|
||||
from ..modules.export_materials import cleanup_materials, export_materials
|
||||
from ..modules.bevy_scene_components import remove_scene_components, upsert_scene_components
|
||||
|
||||
from ...blueprints.blueprints_scan import blueprints_scan
|
||||
from ...blueprints.blueprint_helpers import inject_export_path_into_internal_blueprints
|
||||
|
||||
|
||||
"""this is the main 'central' function for all auto export """
|
||||
def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
||||
# have the export parameters (not auto export, just gltf export) have changed: if yes (for example switch from glb to gltf, compression or not, animations or not etc), we need to re-export everything
|
||||
print ("changed_export_parameters", changed_export_parameters)
|
||||
try:
|
||||
@ -26,34 +27,41 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
file_path = bpy.data.filepath
|
||||
# Get the folder
|
||||
blend_file_path = os.path.dirname(file_path)
|
||||
# get the preferences for our addon
|
||||
project_root_path = getattr(addon_prefs, "project_root_path")
|
||||
assets_path = getattr(addon_prefs,"assets_path")
|
||||
|
||||
#should we use change detection or not
|
||||
change_detection = getattr(settings.auto_export, "change_detection")
|
||||
export_scene_settings = getattr(settings.auto_export,"export_scene_settings")
|
||||
do_export_blueprints = getattr(settings.auto_export,"export_blueprints")
|
||||
export_materials_library = getattr(settings.auto_export,"export_materials_library")
|
||||
change_detection = getattr(addon_prefs.auto_export, "change_detection")
|
||||
export_scene_settings = getattr(addon_prefs.auto_export,"export_scene_settings")
|
||||
do_export_blueprints = getattr(addon_prefs.auto_export,"export_blueprints")
|
||||
export_materials_library = getattr(addon_prefs.auto_export,"export_materials_library")
|
||||
|
||||
# standard gltf export settings are stored differently
|
||||
standard_gltf_exporter_settings = get_standard_exporter_settings()
|
||||
gltf_extension = standard_gltf_exporter_settings.get("export_format", 'GLB')
|
||||
gltf_extension = '.glb' if gltf_extension == 'GLB' else '.gltf'
|
||||
settings.export_gltf_extension = gltf_extension
|
||||
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
||||
# generate the actual complete output paths
|
||||
"""addon_prefs.assets_path_full = os.path.join(blend_file_path, project_root_path, assets_path)
|
||||
addon_prefs.blueprints_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"blueprints_path"))
|
||||
addon_prefs.levels_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"levels_path"))
|
||||
addon_prefs.materials_path_full = os.path.join(addon_prefs.assets_path_full, getattr(addon_prefs,"materials_path"))"""
|
||||
addon_prefs.export_gltf_extension = gltf_extension
|
||||
|
||||
bpy.context.window_manager.blueprints_registry.refresh_blueprints()
|
||||
blueprints_data = bpy.context.window_manager.blueprints_registry.blueprints_data
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
|
||||
blueprints_data = blueprints_scan(level_scenes, library_scenes, addon_prefs)
|
||||
blueprints_per_scene = blueprints_data.blueprints_per_scenes
|
||||
internal_blueprints = [blueprint.name for blueprint in blueprints_data.internal_blueprints]
|
||||
external_blueprints = [blueprint.name for blueprint in blueprints_data.external_blueprints]
|
||||
|
||||
# we inject the blueprints export path
|
||||
blueprints_path = getattr(settings,"blueprints_path")
|
||||
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.refresh_blueprints()
|
||||
print("YO YO")
|
||||
#bpy.context.window_manager.blueprints_registry.add_blueprints_data()
|
||||
|
||||
if export_scene_settings:
|
||||
# inject/ update scene components
|
||||
@ -67,15 +75,15 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
if do_export_blueprints:
|
||||
print("EXPORTING")
|
||||
# get blueprints/collections infos
|
||||
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings)
|
||||
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs)
|
||||
|
||||
# get level/main scenes infos
|
||||
(main_scenes_to_export) = get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings)
|
||||
(main_scenes_to_export) = get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs)
|
||||
|
||||
# since materials export adds components we need to call this before blueprints are exported
|
||||
# export materials & inject materials components into relevant objects
|
||||
if export_materials_library:
|
||||
export_materials(blueprints_data.blueprint_names, library_scenes, settings)
|
||||
export_materials(blueprints_data.blueprint_names, library_scenes, addon_prefs)
|
||||
|
||||
# update the list of tracked exports
|
||||
exports_total = len(blueprints_to_export) + len(main_scenes_to_export) + (1 if export_materials_library else 0)
|
||||
@ -107,13 +115,13 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
print("export MAIN scenes")
|
||||
for scene_name in main_scenes_to_export:
|
||||
print(" exporting scene:", scene_name)
|
||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, blueprints_data)
|
||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, addon_prefs, blueprints_data)
|
||||
|
||||
# now deal with blueprints/collections
|
||||
do_export_library_scene = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
|
||||
if do_export_library_scene:
|
||||
print("export LIBRARY")
|
||||
export_blueprints(blueprints_to_export, settings, blueprints_data)
|
||||
export_blueprints(blueprints_to_export, addon_prefs, blueprints_data)
|
||||
|
||||
# reset current scene from backup
|
||||
bpy.context.window.scene = old_current_scene
|
||||
@ -126,7 +134,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
|
||||
else:
|
||||
for scene_name in main_scene_names:
|
||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, [])
|
||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, addon_prefs, [])
|
||||
|
||||
|
||||
|
||||
@ -140,7 +148,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
||||
|
||||
finally:
|
||||
# FIXME: error handling ? also redundant
|
||||
[main_scene_names, main_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
||||
[main_scene_names, main_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
|
||||
if export_scene_settings:
|
||||
# inject/ update scene components
|
@ -7,32 +7,32 @@ from .export_gltf import (generate_gltf_export_preferences)
|
||||
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
|
||||
|
||||
|
||||
def export_blueprints(blueprints, settings, blueprints_data):
|
||||
blueprints_path_full = getattr(settings, "blueprints_path_full")
|
||||
gltf_export_preferences = generate_gltf_export_preferences(settings)
|
||||
def export_blueprints(blueprints, addon_prefs, blueprints_data):
|
||||
blueprints_path_full = getattr(addon_prefs, "blueprints_path_full")
|
||||
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
|
||||
|
||||
try:
|
||||
# save current active collection
|
||||
active_collection = bpy.context.view_layer.active_layer_collection
|
||||
export_materials_library = getattr(settings.auto_export, "export_materials_library")
|
||||
export_materials_library = getattr(addon_prefs.auto_export, "export_materials_library")
|
||||
|
||||
for blueprint in blueprints:
|
||||
print("exporting collection", blueprint.name)
|
||||
gltf_output_path = os.path.join(blueprints_path_full, blueprint.name)
|
||||
gltf_export_settings = { **gltf_export_preferences, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
|
||||
export_settings = { **gltf_export_preferences, 'use_active_scene': True, 'use_active_collection': True, 'use_active_collection_with_nested':True}
|
||||
|
||||
# if we are using the material library option, do not export materials, use placeholder instead
|
||||
if export_materials_library:
|
||||
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
|
||||
export_settings['export_materials'] = 'PLACEHOLDER'
|
||||
|
||||
collection = bpy.data.collections[blueprint.name]
|
||||
# do the actual export
|
||||
generate_and_export(
|
||||
settings,
|
||||
addon_prefs,
|
||||
temp_scene_name=TEMPSCENE_PREFIX+collection.name,
|
||||
gltf_export_settings=gltf_export_settings,
|
||||
export_settings=export_settings,
|
||||
gltf_output_path=gltf_output_path,
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(collection, temp_collection, blueprints_data=blueprints_data, addon_prefs=addon_prefs),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=collection, temp_scene=temp_scene, **params)
|
||||
)
|
||||
|
@ -2,13 +2,10 @@ import json
|
||||
import os
|
||||
import bpy
|
||||
|
||||
from blenvy.settings import load_settings
|
||||
from .get_standard_exporter_settings import get_standard_exporter_settings
|
||||
from .preferences import (AutoExportGltfPreferenceNames)
|
||||
|
||||
def get_standard_exporter_settings():
|
||||
standard_gltf_exporter_settings = load_settings(".blenvy_gltf_settings")
|
||||
return standard_gltf_exporter_settings if standard_gltf_exporter_settings is not None else {}
|
||||
|
||||
def generate_gltf_export_preferences(settings):
|
||||
def generate_gltf_export_preferences(addon_prefs):
|
||||
# default values
|
||||
gltf_export_preferences = dict(
|
||||
# export_format= 'GLB', #'GLB', 'GLTF_SEPARATE', 'GLTF_EMBEDDED'
|
||||
@ -46,10 +43,10 @@ def generate_gltf_export_preferences(settings):
|
||||
#export_optimize_animation_size=False
|
||||
)
|
||||
|
||||
"""for key in settings.__annotations__.keys():
|
||||
for key in addon_prefs.__annotations__.keys():
|
||||
if str(key) not in AutoExportGltfPreferenceNames:
|
||||
#print("overriding setting", key, "value", getattr(settings,key))
|
||||
pass#gltf_export_preferences[key] = getattr(settings, key)"""
|
||||
#print("overriding setting", key, "value", getattr(addon_prefs,key))
|
||||
pass#gltf_export_preferences[key] = getattr(addon_prefs, key)
|
||||
|
||||
|
||||
standard_gltf_exporter_settings = get_standard_exporter_settings()
|
||||
@ -73,8 +70,8 @@ def generate_gltf_export_preferences(settings):
|
||||
|
||||
|
||||
#https://docs.blender.org/api/current/bpy.ops.export_scene.html#bpy.ops.export_scene.gltf
|
||||
def export_gltf (path, gltf_export_settings):
|
||||
settings = {**gltf_export_settings, "filepath": path}
|
||||
def export_gltf (path, export_settings):
|
||||
settings = {**export_settings, "filepath": path}
|
||||
# print("export settings",settings)
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
bpy.ops.export_scene.gltf(**settings)
|
@ -1,23 +1,23 @@
|
||||
import os
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
from blenvy.blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
||||
|
||||
from ..constants import TEMPSCENE_PREFIX
|
||||
from ..helpers.generate_and_export import generate_and_export
|
||||
from .export_gltf import (generate_gltf_export_preferences, export_gltf)
|
||||
from ..modules.bevy_dynamic import is_object_dynamic, is_object_static
|
||||
from ..helpers.helpers_scenes import clear_hollow_scene, copy_hollowed_collection_into
|
||||
from ...blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
||||
|
||||
def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
||||
gltf_export_preferences = generate_gltf_export_preferences(settings)
|
||||
assets_path_full = getattr(settings,"assets_path_full")
|
||||
levels_path_full = getattr(settings,"levels_path_full")
|
||||
def export_main_scene(scene, blend_file_path, addon_prefs, blueprints_data):
|
||||
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
|
||||
assets_path_full = getattr(addon_prefs,"assets_path_full")
|
||||
levels_path_full = getattr(addon_prefs,"levels_path_full")
|
||||
|
||||
export_blueprints = getattr(settings.auto_export,"export_blueprints")
|
||||
export_separate_dynamic_and_static_objects = getattr(settings.auto_export, "export_separate_dynamic_and_static_objects")
|
||||
export_blueprints = getattr(addon_prefs.auto_export,"export_blueprints")
|
||||
export_separate_dynamic_and_static_objects = getattr(addon_prefs.auto_export, "export_separate_dynamic_and_static_objects")
|
||||
|
||||
gltf_export_settings = { **gltf_export_preferences,
|
||||
export_settings = { **gltf_export_preferences,
|
||||
'use_active_scene': True,
|
||||
'use_active_collection':True,
|
||||
'use_active_collection_with_nested':True,
|
||||
@ -29,46 +29,45 @@ def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
||||
if export_blueprints :
|
||||
gltf_output_path = os.path.join(levels_path_full, scene.name)
|
||||
|
||||
#inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
||||
#inject_blueprints_list_into_main_scene(scene, blueprints_data, addon_prefs)
|
||||
if export_separate_dynamic_and_static_objects:
|
||||
#print("SPLIT STATIC AND DYNAMIC")
|
||||
# first export static objects
|
||||
generate_and_export(
|
||||
settings,
|
||||
addon_prefs,
|
||||
temp_scene_name=TEMPSCENE_PREFIX,
|
||||
gltf_export_settings=gltf_export_settings,
|
||||
export_settings=export_settings,
|
||||
gltf_output_path=gltf_output_path,
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_static, settings=settings),
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_static, addon_prefs=addon_prefs),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
||||
)
|
||||
|
||||
# then export all dynamic objects
|
||||
gltf_output_path = os.path.join(levels_path_full, scene.name+ "_dynamic")
|
||||
generate_and_export(
|
||||
settings,
|
||||
addon_prefs,
|
||||
temp_scene_name=TEMPSCENE_PREFIX,
|
||||
gltf_export_settings=gltf_export_settings,
|
||||
export_settings=export_settings,
|
||||
gltf_output_path=gltf_output_path,
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_dynamic, settings=settings),
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_dynamic, addon_prefs=addon_prefs),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
||||
)
|
||||
|
||||
else:
|
||||
#print("NO SPLIT")
|
||||
generate_and_export(
|
||||
settings,
|
||||
addon_prefs,
|
||||
temp_scene_name=TEMPSCENE_PREFIX,
|
||||
gltf_export_settings=gltf_export_settings,
|
||||
export_settings=export_settings,
|
||||
gltf_output_path=gltf_output_path,
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, settings=settings),
|
||||
tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, addon_prefs=addon_prefs),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
||||
)
|
||||
|
||||
else:
|
||||
gltf_output_path = os.path.join(assets_path_full, scene.name)
|
||||
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
|
||||
if settings.auto_export.dry_run == "DISABLED":
|
||||
export_gltf(gltf_output_path, gltf_export_settings)
|
||||
export_gltf(gltf_output_path, export_settings)
|
||||
|
||||
remove_blueprints_list_from_main_scene(scene)
|
||||
|
@ -1,15 +1,16 @@
|
||||
|
||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
||||
from blenvy.blueprints.blueprint_helpers import find_blueprints_not_on_disk
|
||||
import bpy
|
||||
import os
|
||||
from ..helpers.helpers_scenes import (get_scenes, )
|
||||
from ...blueprints.blueprint_helpers import find_blueprints_not_on_disk
|
||||
|
||||
# TODO: this should also take the split/embed mode into account: if a nested collection changes AND embed is active, its container collection should also be exported
|
||||
def get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
|
||||
blueprints_path_full = getattr(settings,"blueprints_path_full", "")
|
||||
change_detection = getattr(settings.auto_export, "change_detection")
|
||||
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
||||
def get_blueprints_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs):
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension", ".glb")
|
||||
blueprints_path_full = getattr(addon_prefs,"blueprints_path_full", "")
|
||||
change_detection = getattr(addon_prefs.auto_export, "change_detection")
|
||||
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
|
||||
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
internal_blueprints = blueprints_data.internal_blueprints
|
||||
blueprints_to_export = internal_blueprints # just for clarity
|
||||
|
@ -1,5 +1,6 @@
|
||||
from blenvy.core.scene_helpers import get_main_and_library_scenes
|
||||
from blenvy.blueprints.blueprint_helpers import check_if_blueprint_on_disk
|
||||
import bpy
|
||||
from ...blueprints.blueprint_helpers import check_if_blueprint_on_disk
|
||||
from ..helpers.helpers_scenes import (get_scenes, )
|
||||
|
||||
# IF collection_instances_combine_mode is not 'split' check for each scene if any object in changes_per_scene has an instance in the scene
|
||||
def changed_object_in_scene(scene_name, changes_per_scene, blueprints_data, collection_instances_combine_mode):
|
||||
@ -35,14 +36,14 @@ def changed_object_in_scene(scene_name, changes_per_scene, blueprints_data, coll
|
||||
|
||||
|
||||
# this also takes the split/embed mode into account: if a collection instance changes AND embed is active, its container level/world should also be exported
|
||||
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, settings):
|
||||
export_gltf_extension = getattr(settings, "export_gltf_extension")
|
||||
levels_path_full = getattr(settings, "levels_path_full")
|
||||
def get_levels_to_export(changes_per_scene, changed_export_parameters, blueprints_data, addon_prefs):
|
||||
export_gltf_extension = getattr(addon_prefs, "export_gltf_extension")
|
||||
levels_path_full = getattr(addon_prefs, "levels_path_full")
|
||||
|
||||
change_detection = getattr(settings.auto_export, "change_detection")
|
||||
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
||||
change_detection = getattr(addon_prefs.auto_export, "change_detection")
|
||||
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
|
||||
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_main_and_library_scenes(settings)
|
||||
[main_scene_names, level_scenes, library_scene_names, library_scenes] = get_scenes(addon_prefs)
|
||||
|
||||
# determine list of main scenes to export
|
||||
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
@ -0,0 +1,14 @@
|
||||
import bpy
|
||||
import json
|
||||
|
||||
def get_standard_exporter_settings():
|
||||
standard_gltf_exporter_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
|
||||
if standard_gltf_exporter_settings != None:
|
||||
try:
|
||||
standard_gltf_exporter_settings = json.loads(standard_gltf_exporter_settings.as_string())
|
||||
except:
|
||||
standard_gltf_exporter_settings = {}
|
||||
else:
|
||||
standard_gltf_exporter_settings = {}
|
||||
|
||||
return standard_gltf_exporter_settings
|
228
tools/blenvy/gltf_auto_export/auto_export/operators.py
Normal file
228
tools/blenvy/gltf_auto_export/auto_export/operators.py
Normal file
@ -0,0 +1,228 @@
|
||||
import json
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
#from ..ui.main import GLTF_PT_auto_export_general, GLTF_PT_auto_export_main, GLTF_PT_auto_export_root
|
||||
|
||||
from .preferences import (AutoExportGltfAddonPreferences, AutoExportGltfPreferenceNames)
|
||||
from .auto_export import auto_export
|
||||
from ..helpers.generate_complete_preferences_dict import generate_complete_preferences_dict_auto
|
||||
|
||||
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences):#, ExportHelper):
|
||||
"""auto export gltf"""
|
||||
#bl_idname = "object.xxx"
|
||||
bl_idname = "export_scenes.auto_gltf"
|
||||
bl_label = "Apply settings"
|
||||
bl_options = {'PRESET'} # we do not add UNDO otherwise it leads to an invisible operation that resets the state of the saved serialized scene, breaking compares for normal undo/redo operations
|
||||
# ExportHelper mixin class uses this
|
||||
#filename_ext = ''
|
||||
#filepath: bpy.props.StringProperty(subtype="FILE_PATH", default="") # type: ignore
|
||||
|
||||
#list of settings (other than purely gltf settings) whose change should trigger a re-generation of gltf files
|
||||
white_list = [
|
||||
'auto_export',
|
||||
'project_root_path',
|
||||
'assets_path',
|
||||
'change_detection',
|
||||
'export_scene_settings',
|
||||
|
||||
'main_scene_names',
|
||||
'library_scene_names',
|
||||
|
||||
'export_blueprints',
|
||||
'blueprints_path',
|
||||
'export_marked_assets',
|
||||
'collection_instances_combine_mode',
|
||||
|
||||
'levels_path',
|
||||
'export_separate_dynamic_and_static_objects',
|
||||
|
||||
'export_materials_library',
|
||||
'materials_path',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
pass
|
||||
|
||||
def format_settings(self):
|
||||
# find all props to save
|
||||
exceptional = [
|
||||
# options that don't start with 'export_'
|
||||
'collection_instances_combine_mode',
|
||||
]
|
||||
all_props = self.properties
|
||||
export_props = {
|
||||
x: getattr(self, x) for x in dir(all_props)
|
||||
if (x.startswith("export_") or x in exceptional) and all_props.get(x) is not None
|
||||
}
|
||||
# we inject all that we need, the above is not sufficient
|
||||
for (k, v) in self.properties.items():
|
||||
if k in self.white_list or k not in AutoExportGltfPreferenceNames:
|
||||
value = v
|
||||
# FIXME: really weird having to do this
|
||||
if k == "collection_instances_combine_mode":
|
||||
value = self.collection_instances_combine_mode
|
||||
if k == "export_materials":
|
||||
value = self.export_materials
|
||||
export_props[k] = value
|
||||
# we add main & library scene names to our preferences
|
||||
|
||||
return export_props
|
||||
|
||||
def save_settings(self, context):
|
||||
print("save settings")
|
||||
auto_export_settings = self.format_settings()
|
||||
|
||||
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||
stored_settings.clear()
|
||||
|
||||
auto_export_settings = generate_complete_preferences_dict_auto(auto_export_settings)
|
||||
stored_settings.write(json.dumps(auto_export_settings))
|
||||
print("saved settings", auto_export_settings)
|
||||
#print("saving settings", bpy.data.texts[".gltf_auto_export_settings"].as_string(), "raw", json.dumps(export_props))
|
||||
|
||||
def load_settings(self, context):
|
||||
print("loading settings")
|
||||
settings = None
|
||||
try:
|
||||
settings = bpy.data.texts[".gltf_auto_export_settings"].as_string()
|
||||
settings = json.loads(settings)
|
||||
except: pass
|
||||
|
||||
self.will_save_settings = False
|
||||
if settings:
|
||||
#print("loading settings in invoke AutoExportGLTF", settings)
|
||||
try:
|
||||
for (k, v) in settings.items():
|
||||
#print("loading setting", k, v)
|
||||
setattr(self, k, v)
|
||||
self.will_save_settings = True
|
||||
|
||||
# Update filter if user saved settings
|
||||
if hasattr(self, 'export_format'):
|
||||
self.filter_glob = '*.glb' if self.export_format == 'GLB' else '*.gltf'
|
||||
|
||||
# inject scenes data
|
||||
if hasattr(self, 'main_scene_names'):
|
||||
main_scenes = self.main_scenes
|
||||
main_scenes.clear()
|
||||
for item_name in self.main_scene_names:
|
||||
item = main_scenes.add()
|
||||
item.name = item_name
|
||||
|
||||
if hasattr(self, 'library_scene_names'):
|
||||
library_scenes = self.library_scenes
|
||||
library_scenes.clear()
|
||||
for item_name in self.library_scene_names:
|
||||
item = library_scenes.add()
|
||||
item.name = item_name
|
||||
|
||||
except Exception as error:
|
||||
print("error", error)
|
||||
self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
|
||||
bpy.data.texts.remove(bpy.data.texts[".gltf_auto_export_settings"])
|
||||
else:
|
||||
self.will_save_settings = True
|
||||
|
||||
"""
|
||||
This should ONLY be run when actually doing exports/aka calling auto_export function, because we only care about the difference in settings between EXPORTS
|
||||
"""
|
||||
def did_export_settings_change(self):
|
||||
return True
|
||||
# compare both the auto export settings & the gltf settings
|
||||
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else None
|
||||
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else None
|
||||
|
||||
current_auto_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else None
|
||||
current_gltf_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else None
|
||||
|
||||
#check if params have changed
|
||||
|
||||
# if there were no setting before, it is new, we need export
|
||||
changed = False
|
||||
if previous_auto_settings == None:
|
||||
#print("previous settings missing, exporting")
|
||||
changed = True
|
||||
elif previous_gltf_settings == None:
|
||||
#print("previous gltf settings missing, exporting")
|
||||
previous_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||
previous_gltf_settings.write(json.dumps({}))
|
||||
if current_gltf_settings == None:
|
||||
current_gltf_settings = bpy.data.texts.new(".blenvy_gltf_settings")
|
||||
current_gltf_settings.write(json.dumps({}))
|
||||
|
||||
changed = True
|
||||
|
||||
else:
|
||||
auto_settings_changed = sorted(json.loads(previous_auto_settings.as_string()).items()) != sorted(json.loads(current_auto_settings.as_string()).items()) if current_auto_settings != None else False
|
||||
gltf_settings_changed = sorted(json.loads(previous_gltf_settings.as_string()).items()) != sorted(json.loads(current_gltf_settings.as_string()).items()) if current_gltf_settings != None else False
|
||||
|
||||
"""print("auto settings previous", sorted(json.loads(previous_auto_settings.as_string()).items()))
|
||||
print("auto settings current", sorted(json.loads(current_auto_settings.as_string()).items()))
|
||||
print("auto_settings_changed", auto_settings_changed)
|
||||
|
||||
print("gltf settings previous", sorted(json.loads(previous_gltf_settings.as_string()).items()))
|
||||
print("gltf settings current", sorted(json.loads(current_gltf_settings.as_string()).items()))
|
||||
print("gltf_settings_changed", gltf_settings_changed)"""
|
||||
|
||||
changed = auto_settings_changed or gltf_settings_changed
|
||||
# now write the current settings to the "previous settings"
|
||||
if current_auto_settings != None:
|
||||
previous_auto_settings = bpy.data.texts[".gltf_auto_export_settings_previous"] if ".gltf_auto_export_settings_previous" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings_previous")
|
||||
previous_auto_settings.clear()
|
||||
previous_auto_settings.write(current_auto_settings.as_string()) # TODO : check if this is always valid
|
||||
|
||||
if current_gltf_settings != None:
|
||||
previous_gltf_settings = bpy.data.texts[".blenvy_gltf_settings_previous"] if ".blenvy_gltf_settings_previous" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings_previous")
|
||||
previous_gltf_settings.clear()
|
||||
previous_gltf_settings.write(current_gltf_settings.as_string())
|
||||
|
||||
return changed
|
||||
|
||||
def did_objects_change(self):
|
||||
# FIXME: add it back
|
||||
return {}
|
||||
|
||||
def execute(self, context):
|
||||
print("execute auto export", context.window_manager.blenvy.auto_export)
|
||||
blenvy = context.window_manager.blenvy
|
||||
auto_export_settings = blenvy.auto_export
|
||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||
if self.direct_mode:
|
||||
self.load_settings(context)
|
||||
if self.will_save_settings:
|
||||
self.save_settings(context)
|
||||
#print("self", self.auto_export)
|
||||
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled
|
||||
print("auto export")
|
||||
#changes_per_scene = context.window_manager.auto_export_tracker.changed_objects_per_scene
|
||||
#& do the export
|
||||
# determine changed objects
|
||||
changes_per_scene = self.did_objects_change()
|
||||
# determine changed parameters
|
||||
params_changed = self.did_export_settings_change()
|
||||
auto_export(changes_per_scene, params_changed, blenvy)
|
||||
# cleanup
|
||||
# reset the list of changes in the tracker
|
||||
bpy.context.window_manager.auto_export_tracker.clear_changes()
|
||||
print("AUTO EXPORT DONE")
|
||||
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=0.1)
|
||||
else:
|
||||
print("auto export disabled, skipping")
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
print("invoke")
|
||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||
self.load_settings(context)
|
||||
return context.window_manager.invoke_props_dialog(self, title="Auto export", width=640)
|
||||
|
||||
def cancel(self, context):
|
||||
print("cancel")
|
||||
#bpy.context.window_manager.auto_export_tracker.enable_change_detection()
|
||||
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||
|
201
tools/blenvy/gltf_auto_export/auto_export/preferences.py
Normal file
201
tools/blenvy/gltf_auto_export/auto_export/preferences.py
Normal file
@ -0,0 +1,201 @@
|
||||
|
||||
import os
|
||||
from bpy.types import AddonPreferences
|
||||
from bpy.props import (BoolProperty,
|
||||
IntProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
CollectionProperty
|
||||
)
|
||||
|
||||
AutoExportGltfPreferenceNames = [
|
||||
'will_save_settings',
|
||||
'direct_mode',# specific to main auto_export operator
|
||||
|
||||
'show_general_settings',
|
||||
'auto_export',
|
||||
'project_root_path',
|
||||
'assets_path',
|
||||
'export_scene_settings',
|
||||
|
||||
'show_change_detection_settings',
|
||||
'change_detection',
|
||||
|
||||
'show_scene_settings',
|
||||
'main_scenes',
|
||||
'library_scenes',
|
||||
'main_scenes_index',
|
||||
'library_scenes_index',
|
||||
'main_scene_names',
|
||||
'library_scene_names',
|
||||
|
||||
'show_blueprint_settings',
|
||||
'export_blueprints',
|
||||
'blueprints_path',
|
||||
'export_marked_assets',
|
||||
'collection_instances_combine_mode',
|
||||
|
||||
'levels_path',
|
||||
'export_separate_dynamic_and_static_objects',
|
||||
|
||||
'export_materials_library',
|
||||
'materials_path',
|
||||
]
|
||||
|
||||
def on_export_output_folder_updated(self, context):
|
||||
#self.project_root_path = os.path.relpath(self.project_root_path)
|
||||
#self.assets_path = os.path.join(self.project_root_path, self.assets_path)
|
||||
print("on_foo_updated", self.project_root_path, self.assets_path)
|
||||
|
||||
class AutoExportGltfAddonPreferences(AddonPreferences):
|
||||
# this must match the add-on name, use '__package__'
|
||||
# when defining this in a submodule of a python package.
|
||||
bl_idname = __package__
|
||||
bl_options = {'PRESET'}
|
||||
|
||||
#### these are for the operator
|
||||
will_save_settings: BoolProperty(
|
||||
name='Remember Export Settings',
|
||||
description='Store glTF export settings in the Blender project',
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
# use when operator is called directly, works a bit differently than inside the ui
|
||||
direct_mode: BoolProperty(
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
|
||||
auto_export: BoolProperty(
|
||||
name='Auto export',
|
||||
description='Automatically export to gltf on save',
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
#### general
|
||||
# for UI only, workaround for lacking panels
|
||||
show_general_settings: BoolProperty(
|
||||
name="show_general settings",
|
||||
description="show/hide general settings (UI only: has no impact on exports)",
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
project_root_path: StringProperty(
|
||||
name = "Project Root Path",
|
||||
description="The root folder of your (Bevy) project (not assets!)",
|
||||
# subtype='DIR_PATH',
|
||||
default='../'
|
||||
#update=on_export_output_folder_updated) # type: ignore
|
||||
)
|
||||
|
||||
assets_path: StringProperty(
|
||||
name='Export folder',
|
||||
description='The root folder for all exports(relative to the root folder/path) Defaults to "assets" ',
|
||||
default='./assets',
|
||||
#subtype='DIR_PATH',
|
||||
options={'HIDDEN'}
|
||||
# update=on_export_output_folder_updated
|
||||
) # type: ignore
|
||||
|
||||
# for UI only, workaround for lacking panels
|
||||
show_change_detection_settings: BoolProperty(
|
||||
name="show change detection settings",
|
||||
description="show/hide change detection settings (UI only: has no impact on exports)",
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
change_detection: BoolProperty(
|
||||
name='Change detection',
|
||||
description='Use change detection to determine what/if should be exported',
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
# scenes
|
||||
# for UI only, workaround for lacking panels
|
||||
show_scene_settings: BoolProperty(
|
||||
name="show scene settings",
|
||||
description="show/hide scene settings (UI only: has no impact on exports)",
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
# scene components
|
||||
export_scene_settings: BoolProperty(
|
||||
name='Export scene settings',
|
||||
description='Export scene settings ie AmbientLighting, Bloom, AO etc',
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
# blueprint settings
|
||||
# for UI only, workaround for lacking panels
|
||||
show_blueprint_settings: BoolProperty(
|
||||
name="show blueprint settings",
|
||||
description="show/hide blueprint settings (UI only: has no impact on exports)",
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
export_blueprints: BoolProperty(
|
||||
name='Export Blueprints',
|
||||
description='Replaces collection instances with an Empty with a BlueprintName custom property, and enabled a lot more features !',
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
blueprints_path: StringProperty(
|
||||
name='Blueprints path',
|
||||
description='path to export the blueprints to (relative to the assets folder)',
|
||||
default='blueprints',
|
||||
#subtype='DIR_PATH'
|
||||
) # type: ignore
|
||||
|
||||
levels_path: StringProperty(
|
||||
name='Levels path',
|
||||
description='path to export the levels (main scenes) to (relative to the assets folder)',
|
||||
default='levels',
|
||||
#subtype='DIR_PATH'
|
||||
) # type: ignore
|
||||
|
||||
export_separate_dynamic_and_static_objects: BoolProperty(
|
||||
name="Export levels' dynamic and static objects seperatly",
|
||||
description="""For MAIN scenes only (aka levels), toggle this to generate 2 files per level:
|
||||
- one with all dynamic data: collection or instances marked as dynamic/ saveable
|
||||
- one with all static data: anything else that is NOT marked as dynamic""",
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
export_materials_library: BoolProperty(
|
||||
name='Export materials library',
|
||||
description='remove materials from blueprints and use the material library instead',
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
materials_path: StringProperty(
|
||||
name='Materials path',
|
||||
description='path to export the materials libraries to (relative to the assets folder)',
|
||||
default='materials',
|
||||
#subtype='DIR_PATH'
|
||||
) # type: ignore
|
||||
|
||||
""" combine mode can be
|
||||
- 'Split' (default): replace with an empty, creating links to sub blueprints
|
||||
- 'Embed' : treat it as an embeded object and do not replace it with an empty
|
||||
- 'EmbedExternal': embed any instance of a non local collection (ie external assets)
|
||||
|
||||
- 'Inject': inject components from sub collection instances into the curent object => this is now a seperate custom property that you can apply to a collecion instance
|
||||
"""
|
||||
|
||||
collection_instances_combine_mode : EnumProperty(
|
||||
name='Collection instances',
|
||||
items=(
|
||||
('Split', 'Split', 'replace collection instances with an empty + blueprint, creating links to sub blueprints (Default, Recomended)'),
|
||||
('Embed', 'Embed', 'treat collection instances as embeded objects and do not replace them with an empty'),
|
||||
('EmbedExternal', 'EmbedExternal', 'treat instances of external (not specifified in the current blend file) collections (aka assets etc) as embeded objects and do not replace them with empties'),
|
||||
#('Inject', 'Inject', 'inject components from sub collection instances into the curent object')
|
||||
),
|
||||
default='Split'
|
||||
) # type: ignore
|
||||
|
||||
export_marked_assets: BoolProperty(
|
||||
name='Auto export marked assets',
|
||||
description='Collections that have been marked as assets will be systematically exported, even if not in use in another scene',
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
@ -1,21 +1,22 @@
|
||||
import bpy
|
||||
|
||||
from .project_diff import get_changes_per_scene, project_diff, serialize_current
|
||||
from ...settings import are_settings_identical
|
||||
from .auto_export import auto_export
|
||||
from .settings_diff import get_setting_changes
|
||||
|
||||
# prepare export by gather the changes to the scenes & settings
|
||||
def prepare_and_export():
|
||||
print("prepare and export")
|
||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||
auto_export_settings = blenvy.auto_export
|
||||
if auto_export_settings.auto_export: # only do the actual exporting if auto export is actually enabled
|
||||
|
||||
# determine changed objects
|
||||
per_scene_changes = get_changes_per_scene()
|
||||
# determine changed parameters
|
||||
setting_changes = get_setting_changes(auto_export_settings)
|
||||
setting_changes = get_setting_changes()
|
||||
# do the actual export
|
||||
auto_export(per_scene_changes, setting_changes, blenvy)
|
||||
|
@ -1,10 +1,9 @@
|
||||
import bpy
|
||||
|
||||
from blenvy.settings import are_settings_identical, load_settings, upsert_settings
|
||||
from ...settings import are_settings_identical, load_settings, upsert_settings
|
||||
|
||||
# which settings are specific to auto_export # TODO: can we infer this ?
|
||||
auto_export_parameter_names = [
|
||||
# blenvy core
|
||||
'project_root_path',
|
||||
'assets_path',
|
||||
'blueprints_path',
|
||||
@ -13,7 +12,6 @@ auto_export_parameter_names = [
|
||||
#'main_scene_names',
|
||||
#'library_scene_names',
|
||||
|
||||
# auto export
|
||||
'export_scene_settings',
|
||||
'export_blueprints',
|
||||
'export_separate_dynamic_and_static_objects',
|
||||
@ -22,14 +20,13 @@ auto_export_parameter_names = [
|
||||
'export_marked_assets'
|
||||
]
|
||||
|
||||
def get_setting_changes(auto_export_settings):
|
||||
print("get setting changes", dict(auto_export_settings))
|
||||
def get_setting_changes():
|
||||
previous_gltf_settings = load_settings(".blenvy_gltf_settings_previous")
|
||||
current_gltf_settings = load_settings(".blenvy_gltf_settings")
|
||||
gltf_settings_changed = not are_settings_identical(previous_gltf_settings, current_gltf_settings)
|
||||
|
||||
previous_export_settings = load_settings(".blenvy_export_settings_previous")
|
||||
current_export_settings = dict(auto_export_settings) #load_settings(".blenvy_export_settings")
|
||||
current_export_settings = load_settings(".blenvy_export_settings")
|
||||
export_settings_changed = not are_settings_identical(previous_export_settings, current_export_settings)
|
||||
|
||||
# if there were no setting before, it is new, we need export
|
||||
@ -40,7 +37,7 @@ def get_setting_changes(auto_export_settings):
|
||||
|
||||
# write the new settings to the old settings
|
||||
upsert_settings(".blenvy_gltf_settings_previous", current_gltf_settings)
|
||||
upsert_settings(".blenvy_export_settings_previous", current_export_settings)
|
||||
upsert_settings(".blenvy_export_settings_previous", current_gltf_settings)
|
||||
|
||||
return gltf_settings_changed or export_settings_changed
|
||||
|
@ -14,18 +14,9 @@ class AutoExportTracker(PropertyGroup):
|
||||
change_detection_enabled = True
|
||||
export_params_changed = False
|
||||
|
||||
gltf_settings_backup = None
|
||||
last_operator = None
|
||||
|
||||
|
||||
dummy_file_path: StringProperty()# type: ignore
|
||||
# special property for gltf settings
|
||||
gltf_settings_backup: StringProperty(
|
||||
name="gltf settings backup",
|
||||
description="backup for existing gltf settings so that we can restore them"
|
||||
) # type: ignore
|
||||
|
||||
|
||||
|
||||
dummy_file_path = ""
|
||||
|
||||
exports_total : IntProperty(
|
||||
name='exports_total',
|
||||
@ -86,7 +77,7 @@ class AutoExportTracker(PropertyGroup):
|
||||
scene = bpy.context.scene
|
||||
if "glTF2ExportSettings" in scene:
|
||||
existing_setting = scene["glTF2ExportSettings"]
|
||||
bpy.context.window_manager.auto_export_tracker.gltf_settings_backup = json.dumps(dict(existing_setting))
|
||||
bpy.context.window_manager.gltf_settings_backup = json.dumps(dict(existing_setting))
|
||||
|
||||
# we force saving params
|
||||
active_operator.will_save_settings = True
|
@ -1,16 +1,16 @@
|
||||
import bpy
|
||||
from blenvy.core.helpers_collections import (set_active_collection)
|
||||
from ..export.export_gltf import export_gltf
|
||||
from ..auto_export.export_gltf import export_gltf
|
||||
from ...core.helpers_collections import (set_active_collection)
|
||||
|
||||
"""
|
||||
generates a temporary scene, fills it with data, cleans up after itself
|
||||
* named using temp_scene_name
|
||||
* filled using the tempScene_filler
|
||||
* written on disk to gltf_output_path, with the gltf export parameters in gltf_export_settings
|
||||
* written on disk to gltf_output_path, with the gltf export parameters in export_settings
|
||||
* cleaned up using tempScene_cleaner
|
||||
|
||||
"""
|
||||
def generate_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
|
||||
def generate_and_export(addon_prefs, export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
|
||||
|
||||
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
|
||||
temp_root_collection = temp_scene.collection
|
||||
@ -41,8 +41,7 @@ def generate_and_export(settings, gltf_export_settings, gltf_output_path, temp_s
|
||||
scene_filler_data = tempScene_filler(temp_root_collection)
|
||||
# export the temporary scene
|
||||
try:
|
||||
if settings.auto_export.dry_run == "DISABLED":
|
||||
export_gltf(gltf_output_path, gltf_export_settings)
|
||||
export_gltf(gltf_output_path, export_settings)
|
||||
except Exception as error:
|
||||
print("failed to export gltf !", error)
|
||||
raise error
|
@ -1,4 +1,5 @@
|
||||
|
||||
from ..auto_export.preferences import AutoExportGltfAddonPreferences
|
||||
from io_scene_gltf2 import (ExportGLTF2_Base)
|
||||
|
||||
# given the input (actual) gltf settings, filters out any invalid/useless params & params that are equal to defaults
|
||||
@ -26,3 +27,21 @@ def generate_complete_preferences_dict_gltf(settings):
|
||||
complete_preferences = dict(filter(filter_out, dict(complete_preferences).items()))
|
||||
return complete_preferences
|
||||
|
||||
# given the input (actual) auto settings, filters out any invalid/useless params & params that are equal to defaults
|
||||
def generate_complete_preferences_dict_auto(settings):
|
||||
complete_preferences = {}
|
||||
defaults = {}
|
||||
|
||||
for k in AutoExportGltfAddonPreferences.__annotations__:
|
||||
item = AutoExportGltfAddonPreferences.__annotations__[k]
|
||||
default = item.keywords.get('default', None)
|
||||
#complete_preferences[k] = default
|
||||
defaults[k] = default
|
||||
|
||||
for key in list(settings.keys()):
|
||||
if key in defaults:
|
||||
if settings[key] != defaults[key]: # only write out values different from defaults
|
||||
complete_preferences[key] = settings[key]
|
||||
else:
|
||||
complete_preferences[key] = settings[key]
|
||||
return complete_preferences
|
@ -1,6 +1,6 @@
|
||||
import json
|
||||
import bpy
|
||||
from blenvy.core.object_makers import (make_empty)
|
||||
from ...core.object_makers import (make_empty)
|
||||
|
||||
|
||||
# these are mostly for when using this add-on together with the bevy_components add-on
|
||||
@ -145,8 +145,8 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
||||
duplicate_object(child, copy, combine_mode, destination_collection, blueprints_data, nester+" ")
|
||||
|
||||
# copies the contents of a collection into another one while replacing library instances with empties
|
||||
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, blueprints_data=None, settings={}):
|
||||
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
||||
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, blueprints_data=None, addon_prefs={}):
|
||||
collection_instances_combine_mode = getattr(addon_prefs.auto_export, "collection_instances_combine_mode")
|
||||
|
||||
for object in source_collection.objects:
|
||||
if object.name.endswith("____bak"): # some objects could already have been handled, ignore them
|
||||
@ -172,7 +172,7 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par
|
||||
parent_empty = collection_placeholder,
|
||||
filter = filter,
|
||||
blueprints_data = blueprints_data,
|
||||
settings=settings
|
||||
addon_prefs=addon_prefs
|
||||
)
|
||||
return {}
|
||||
|
||||
@ -204,3 +204,20 @@ def clear_hollow_scene(temp_scene, original_root_collection):
|
||||
|
||||
# reset original names
|
||||
restore_original_names(original_root_collection)
|
||||
|
||||
# convenience utility to get lists of scenes
|
||||
def get_scenes(addon_prefs):
|
||||
level_scene_names= getattr(addon_prefs, "main_scene_names", []) #list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes")))
|
||||
library_scene_names = getattr(addon_prefs, "library_scene_names", []) #list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
|
||||
|
||||
level_scene_names= list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes")))
|
||||
library_scene_names = list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
|
||||
|
||||
print("level_scene_names", level_scene_names)
|
||||
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
|
||||
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
||||
|
||||
level_scenes = list(map(lambda name: bpy.data.scenes[name], level_scene_names))
|
||||
library_scenes = list(map(lambda name: bpy.data.scenes[name], library_scene_names))
|
||||
|
||||
return [level_scene_names, level_scenes, library_scene_names, library_scenes]
|
@ -155,7 +155,7 @@ class glTF2ExportUserExtension:
|
||||
self.Extension = Extension
|
||||
self.properties = bpy.context.scene.ExampleExtensionProperties
|
||||
|
||||
def gather_node_hook(self, gltf2_object, blender_object, gltf_export_settings):
|
||||
def gather_node_hook(self, gltf2_object, blender_object, export_settings):
|
||||
if self.properties.enabled:
|
||||
if gltf2_object.extensions is None:
|
||||
gltf2_object.extensions = {}
|
||||
@ -193,7 +193,7 @@ def did_export_parameters_change(current_params, previous_params):
|
||||
bpy.context.window.scene = library_scene
|
||||
with bpy.context.temp_override(scene=library_scene):
|
||||
print("active scene", bpy.context.scene)
|
||||
export_gltf(gltf_output_path, gltf_export_settings)
|
||||
export_gltf(gltf_output_path, export_settings)
|
||||
bpy.context.window.scene = original_scene"""
|
||||
|
||||
"""
|
||||
@ -296,16 +296,16 @@ def duplicate_object2(object, original_name):
|
||||
settings = scene["glTF2ExportSettings"]
|
||||
formatted_settings = dict(settings)
|
||||
|
||||
gltf_export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||
export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings")
|
||||
|
||||
#check if params have changed
|
||||
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(gltf_export_settings.as_string()).items()) != sorted(formatted_settings.items())
|
||||
bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(export_settings.as_string()).items()) != sorted(formatted_settings.items())
|
||||
|
||||
print("gltf NEW settings", formatted_settings, "OLD settings", gltf_export_settings, "CHANGED ?", bpy.context.window_manager.gltf_settings_changed)
|
||||
print("gltf NEW settings", formatted_settings, "OLD settings", export_settings, "CHANGED ?", bpy.context.window_manager.gltf_settings_changed)
|
||||
|
||||
# now write new settings
|
||||
gltf_export_settings.clear()
|
||||
gltf_export_settings.write(json.dumps(formatted_settings))
|
||||
export_settings.clear()
|
||||
export_settings.write(json.dumps(formatted_settings))
|
||||
|
||||
|
||||
# now reset the original gltf_settings
|
@ -1,6 +1,6 @@
|
||||
|
||||
import bpy
|
||||
from blenvy.core.object_makers import make_empty
|
||||
from ...core.object_makers import make_empty
|
||||
|
||||
# TODO: replace this with placing scene level custom properties once support for that has been added to bevy_gltf
|
||||
def upsert_scene_components(main_scenes):
|
@ -2,11 +2,11 @@ import os
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
|
||||
from blenvy.core.helpers_collections import (traverse_tree)
|
||||
from blenvy.core.object_makers import make_cube
|
||||
from blenvy.materials.materials_helpers import get_all_materials
|
||||
from ...core.helpers_collections import (traverse_tree)
|
||||
from ...core.object_makers import make_cube
|
||||
from ...materials.materials_helpers import get_all_materials
|
||||
from ..helpers.generate_and_export import generate_and_export
|
||||
from .export_gltf import (generate_gltf_export_preferences)
|
||||
from ..auto_export.export_gltf import (generate_gltf_export_preferences)
|
||||
|
||||
def clear_material_info(collection_names, library_scenes):
|
||||
for scene in library_scenes:
|
||||
@ -59,14 +59,14 @@ def clear_materials_scene(temp_scene):
|
||||
|
||||
# exports the materials used inside the current project:
|
||||
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
|
||||
def export_materials(collections, library_scenes, settings):
|
||||
gltf_export_preferences = generate_gltf_export_preferences(settings)
|
||||
materials_path_full = getattr(settings,"materials_path_full")
|
||||
def export_materials(collections, library_scenes, addon_prefs):
|
||||
gltf_export_preferences = generate_gltf_export_preferences(addon_prefs)
|
||||
materials_path_full = getattr(addon_prefs,"materials_path_full")
|
||||
|
||||
used_material_names = get_all_materials(collections, library_scenes)
|
||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||
|
||||
gltf_export_settings = { **gltf_export_preferences,
|
||||
export_settings = { **gltf_export_preferences,
|
||||
'use_active_scene': True,
|
||||
'use_active_collection':True,
|
||||
'use_active_collection_with_nested':True,
|
||||
@ -80,9 +80,9 @@ def export_materials(collections, library_scenes, settings):
|
||||
print(" exporting Materials to", gltf_output_path, ".gltf/glb")
|
||||
|
||||
generate_and_export(
|
||||
settings=settings,
|
||||
gltf_export_settings=gltf_export_settings,
|
||||
addon_prefs,
|
||||
temp_scene_name="__materials_scene",
|
||||
export_settings=export_settings,
|
||||
gltf_output_path=gltf_output_path,
|
||||
tempScene_filler= lambda temp_collection: generate_materials_scene_content(temp_collection, used_material_names),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_materials_scene(temp_scene=temp_scene)
|
@ -1,35 +1,19 @@
|
||||
import bpy
|
||||
from bpy_types import (PropertyGroup)
|
||||
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty)
|
||||
from blenvy.settings import load_settings, upsert_settings, generate_complete_preferences_dict
|
||||
|
||||
# list of settings we do NOT want to save
|
||||
settings_black_list = ['settings_save_enabled', 'dry_run']
|
||||
|
||||
def save_settings(settings, context):
|
||||
if settings.settings_save_enabled:
|
||||
settings_dict = generate_complete_preferences_dict(settings, AutoExportSettings, [])
|
||||
print("save settings", settings, context, settings_dict)
|
||||
upsert_settings(settings.settings_save_path, {key: settings_dict[key] for key in settings_dict.keys() if key not in settings_black_list})
|
||||
|
||||
class AutoExportSettings(PropertyGroup):
|
||||
|
||||
settings_save_path = ".blenvy_export_settings" # where to store data in bpy.texts
|
||||
settings_save_enabled = BoolProperty(name="settings save enabled", default=True)
|
||||
|
||||
auto_export: BoolProperty(
|
||||
name='Auto export',
|
||||
description='Automatically export to gltf on save',
|
||||
default=False,
|
||||
update=save_settings
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
#### general
|
||||
change_detection: BoolProperty(
|
||||
name='Change detection',
|
||||
description='Use change detection to determine what/if should be exported',
|
||||
default=True,
|
||||
update=save_settings
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
# scenes
|
||||
@ -38,16 +22,14 @@ class AutoExportSettings(PropertyGroup):
|
||||
export_scene_settings: BoolProperty(
|
||||
name='Export scene settings',
|
||||
description='Export scene settings ie AmbientLighting, Bloom, AO etc',
|
||||
default=False,
|
||||
update=save_settings
|
||||
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,
|
||||
update=save_settings
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
export_separate_dynamic_and_static_objects: BoolProperty(
|
||||
@ -55,15 +37,13 @@ class AutoExportSettings(PropertyGroup):
|
||||
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,
|
||||
update=save_settings
|
||||
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,
|
||||
update=save_settings
|
||||
default=False
|
||||
) # type: ignore
|
||||
|
||||
|
||||
@ -83,39 +63,28 @@ class AutoExportSettings(PropertyGroup):
|
||||
('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',
|
||||
update=save_settings
|
||||
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,
|
||||
update=save_settings
|
||||
default=True
|
||||
) # type: ignore
|
||||
|
||||
dry_run: EnumProperty(
|
||||
name="dry run",
|
||||
description="debug/ develop helper to enable everything but the actual exporting of files",
|
||||
items=(
|
||||
("DISABLED", "Disabled","Run exports normally (no Dry run)"),
|
||||
("NO_EXPORT", "No export", "do not actually export gltf files"),
|
||||
("NO_PREPARE", "No prepare", "do not actually export gltf files AND do not prepare the exports either (ie no creating fake scenes etc)"),
|
||||
),
|
||||
default="DISABLED",
|
||||
)
|
||||
) # type: ignore
|
||||
|
||||
# special property for gltf settings
|
||||
gltf_settings_backup: StringProperty(
|
||||
name="gltf settings backup",
|
||||
description="backup for existing gltf settings so that we can restore them"
|
||||
) # type: ignore
|
||||
|
||||
|
||||
def load_settings(self):
|
||||
settings = load_settings(self.settings_save_path)
|
||||
if settings is not None:
|
||||
self.settings_save_enabled = False # we disable auto_saving of our settings
|
||||
try:
|
||||
for setting in settings:
|
||||
print("setting", setting, settings[setting])
|
||||
setattr(self, setting, settings[setting])
|
||||
except: pass
|
||||
# TODO: remove setting if there was a failure
|
||||
|
||||
self.settings_save_enabled = True
|
||||
|
@ -2,7 +2,7 @@ import json
|
||||
import bpy
|
||||
|
||||
def upsert_settings(name, data):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
|
||||
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))
|
||||
@ -14,43 +14,10 @@ def upsert_settings(name, data):
|
||||
|
||||
def load_settings(name):
|
||||
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
|
||||
if stored_settings is not None:
|
||||
try:
|
||||
return json.loads(stored_settings.as_string())
|
||||
except:
|
||||
return None
|
||||
if stored_settings != None:
|
||||
return json.loads(stored_settings.as_string())
|
||||
return None
|
||||
|
||||
|
||||
# given the input (actual) settings, filters out any invalid/useless params & params that are equal to defaults
|
||||
def generate_complete_preferences_dict(settings, presets, ignore_list=[], preset_defaults=True):
|
||||
complete_preferences = {}
|
||||
defaults = {}
|
||||
|
||||
def filter_out(pair):
|
||||
key, value = pair
|
||||
if key in ignore_list:
|
||||
return False
|
||||
return True
|
||||
|
||||
for k in presets.__annotations__:
|
||||
item = presets.__annotations__[k]
|
||||
default = item.keywords.get('default', None)
|
||||
if default is not None:
|
||||
defaults[k] = default
|
||||
if preset_defaults:
|
||||
complete_preferences[k] = default
|
||||
# print("defaults", defaults)
|
||||
|
||||
|
||||
for key in list(settings.keys()):
|
||||
if key in defaults and settings[key] != defaults[key]: # only write out values different from defaults
|
||||
complete_preferences[key] = getattr(settings, key, None)
|
||||
complete_preferences = dict(filter(filter_out, dict(complete_preferences).items()))
|
||||
|
||||
return complete_preferences
|
||||
|
||||
|
||||
# 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:
|
||||
|
@ -5,9 +5,9 @@ import pytest
|
||||
def setup_data(request):
|
||||
print("\nSetting up resources...")
|
||||
|
||||
schema_path = "../../testing/bevy_example/assets/registry.json"
|
||||
schemaPath = "../../testing/bevy_example/assets/registry.json"
|
||||
|
||||
yield {"schema_path": schema_path}
|
||||
yield {"schema_path": schemaPath}
|
||||
|
||||
def finalizer():
|
||||
print("\nPerforming teardown...")
|
||||
|
@ -9,7 +9,7 @@ import filecmp
|
||||
from PIL import Image
|
||||
from pixelmatch.contrib.PIL import pixelmatch
|
||||
|
||||
from blenvy.auto_export.export.prepare_and_export import prepare_and_export
|
||||
from blenvy.gltf_auto_export.auto_export.prepare_and_export import prepare_and_export
|
||||
|
||||
@pytest.fixture
|
||||
def setup_data(request):
|
||||
|
@ -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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
long_name = "bevy_example::test_components::BasicTest"
|
||||
|
@ -3,7 +3,7 @@ from .setup_data import setup_data
|
||||
|
||||
def test_blend(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
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.schema_path = setup_data["components_schemaPath"]
|
||||
registry.schemaPath = setup_data["components_schemaPath"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
rename_component_operator = bpy.ops.object.rename_bevy_component
|
||||
|
@ -5,7 +5,7 @@ from .setup_data import setup_data
|
||||
|
||||
def test_shuffler(setup_data):
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
registry.schema_path = setup_data["schema_path"]
|
||||
registry.schemaPath = setup_data["schema_path"]
|
||||
bpy.ops.object.reload_registry()
|
||||
|
||||
type_infos = registry.type_infos
|
||||
|
Loading…
Reference in New Issue
Block a user