feat(Blenvy): settings coherency pass

* restructured component settings to be used instead of the registry
 * removed settings from registry
 * fixed data access for the above
 * added saving of component parameters
 * added component settings pointer in blenvy core
 * added loading of both auto_export & component settings in blenvy core's load_settings
This commit is contained in:
kaosat.dev 2024-05-26 18:33:06 +02:00
parent ea982d330f
commit b957f0573b
18 changed files with 223 additions and 212 deletions

View File

@ -80,6 +80,7 @@ General things to solve:
- [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
@ -87,6 +88,12 @@ 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
- [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 ?
- [ ] remove hard coded path for standard gltf settings
- [x] remove hard coded path for standard gltf settings
- [ ] load settings on file load
- [x] auto_export
- [ ] components
- [ ] add handling of errors when trying to load settings

View File

@ -26,6 +26,7 @@ from .add_ons.bevy_components.components.lists import GENERIC_LIST_OT_actions, G
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
# auto export
from .add_ons.auto_export import gltf_post_export_callback
@ -67,6 +68,7 @@ classes = [
BLENVY_PT_SidePanel,
# bevy components
ComponentsSettings,
AddComponentOperator,
CopyComponentOperator,
PasteComponentOperator,
@ -110,6 +112,7 @@ classes = [
GENERIC_MAP_OT_actions,
# gltf auto export
AutoExportTracker,
AutoExportSettings,
@ -143,9 +146,6 @@ 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()

View File

@ -26,21 +26,3 @@ 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, presets):
complete_preferences = {}
defaults = {}
for k in presets.__annotations__:
item = presets.__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

View File

@ -1,19 +1,30 @@
import bpy
from bpy_types import (PropertyGroup)
from bpy.props import (EnumProperty, PointerProperty, StringProperty, BoolProperty, CollectionProperty, IntProperty)
from blenvy.settings import upsert_settings, generate_complete_preferences_dict, load_settings
def save_settings(settings, context):
print("save settings", settings, context, dict(settings))
bla = generate_complete_preferences_dict(settings, AutoExportSettings, [])
print("bla", bla)
upsert_settings(settings.settings_save_path, dict(settings))
class AutoExportSettings(PropertyGroup):
settings_save_path = ".blenvy_export_settings" # where to store data in bpy.texts
auto_export: BoolProperty(
name='Auto export',
description='Automatically export to gltf on save',
default=False
default=False,
update=save_settings
) # type: ignore
#### general
change_detection: BoolProperty(
name='Change detection',
description='Use change detection to determine what/if should be exported',
default=True
default=True,
update=save_settings
) # type: ignore
# scenes
@ -22,14 +33,16 @@ class AutoExportSettings(PropertyGroup):
export_scene_settings: BoolProperty(
name='Export scene settings',
description='Export scene settings ie AmbientLighting, Bloom, AO etc',
default=False
default=False,
update=save_settings
) # 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
default=True,
update=save_settings
) # type: ignore
export_separate_dynamic_and_static_objects: BoolProperty(
@ -37,13 +50,15 @@ 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
default=False,
update=save_settings
) # type: ignore
export_materials_library: BoolProperty(
name='Export materials library',
description='remove materials from blueprints and use the material library instead',
default=False
default=False,
update=save_settings
) # type: ignore
@ -63,13 +78,15 @@ 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'
default='Split',
update=save_settings
) # 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
default=True,
update=save_settings
) # type: ignore
dry_run: EnumProperty(
@ -80,7 +97,14 @@ class AutoExportSettings(PropertyGroup):
("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"
default="DISABLED",
) # type: ignore
def load_settings(self):
settings = load_settings(self.settings_save_path)
if settings is not None:
for setting in settings:
print("setting", setting, settings[setting])
setattr(self, setting, settings[setting])

View File

@ -11,7 +11,7 @@ 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 = "object.reload_registry"
bl_idname = "blenvy.reload_components_registry"
bl_label = "Reload Registry"
bl_options = {"UNDO"}
@ -191,10 +191,8 @@ 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'}

View File

@ -5,10 +5,7 @@ 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 blenvy.settings import load_settings
from ..propGroups.prop_groups import generate_propertyGroups_for_components
from ..components.metadata import ComponentMetadata, ensure_metadata_for_all_items
from ..components.metadata import ComponentMetadata
# helper class to store missing bevy types information
class MissingBevyType(bpy.types.PropertyGroup):
@ -16,59 +13,9 @@ 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"
@ -81,25 +28,6 @@ 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
@ -218,22 +146,12 @@ 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
@ -241,6 +159,9 @@ class ComponentsRegistry(PropertyGroup):
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()
@ -252,23 +173,13 @@ 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
f = Path(bpy.path.abspath(path)) # make a path object of abs path
with open(path) as f:
with open(component_settings.schema_path_full) as f:
data = json.load(f)
defs = data["$defs"]
self.registry = json.dumps(defs) # FIXME:meh ?
# 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)
component_settings.start_schema_watcher()
# we load the json once, so we do not need to do it over & over again
@ -279,17 +190,6 @@ 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

View File

@ -5,13 +5,11 @@ from bpy.props import (StringProperty)
from ..utils import get_selection_type
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator, RemoveComponentOperator
from ..components.operators import OT_rename_component, RemoveComponentFromAllItemsOperator
from .operators import(
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_ALL,
COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT,
OT_OpenSchemaFileBrowser,
OT_select_component_name_to_replace,
OT_select_object, ReloadRegistryOperator,
OT_OpenSchemaFileBrowser, ReloadRegistryOperator,
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_ALL,
COMPONENTS_OT_REFRESH_CUSTOM_PROPERTIES_CURRENT)
@ -34,23 +32,24 @@ 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(registry, "schemaPath", text="Registry Schema path")
col.prop(component_settings, "schema_path", text="Registry Schema path")
col = row.column()
col.operator(OT_OpenSchemaFileBrowser.bl_idname, text="Browse for registry schema file (json)")
col.operator("blenvy.open_schemafilebrowser", text="Browse for registry schema file (json)")
layout.separator()
layout.operator(ReloadRegistryOperator.bl_idname, text="reload registry" , icon="FILE_REFRESH")
layout.operator("blenvy.reload_components_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)")
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()

View File

@ -1,7 +1,18 @@
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
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 = ['watcher_active']
def save_settings(settings, context):
print("save settings", settings, context, dict(settings))
settings_dict = dict(settings)
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):
@ -14,15 +25,17 @@ def toggle_watcher(self, context):
else:
self.watcher_active = True
bpy.app.timers.register(watch_schema)
save_settings(self, context)
def watch_schema():
self = bpy.context.window_manager.components_registry
blenvy = bpy.context.window_manager.blenvy
component_settings = blenvy.components
#print("watching schema file for changes")
try:
stamp = os.stat(self.schemaFullPath).st_mtime
stamp = os.stat(component_settings.schema_path_full).st_mtime
stamp = str(stamp)
if stamp != self.schemaTimeStamp and self.schemaTimeStamp != "":
print("FILE CHANGED !!", stamp, self.schemaTimeStamp)
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)
@ -34,17 +47,27 @@ def watch_schema():
# 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
component_settings.schemaTimeStamp = stamp
except Exception as error:
pass
return self.watcher_poll_frequency if self.watcher_enabled else None
return component_settings.watcher_poll_frequency if component_settings.watcher_enabled else None
class ComponentsSettings(PropertyGroup):
schemaPath: StringProperty(
settings_save_path = ".blenvy_components_settings" # where to store data in bpy.texts
schema_path: StringProperty(
name="schema path",
description="path to the registry schema file",
default="registry.json"
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
@ -55,11 +78,45 @@ class ComponentsSettings(PropertyGroup):
description="frequency (s) at wich to poll for changes to the registry file",
min=1,
max=10,
default=1
default=1,
update=save_settings
)# type: ignore
schemaTimeStamp: StringProperty(
name="last timestamp of schema file",
description="",
default=""
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)
if settings is not None:
for setting in settings:
print("setting", setting, settings[setting])
setattr(self, setting, settings[setting])
registry = bpy.context.components_registry
registry.load_schema()
generate_propertyGroups_for_components()
ensure_metadata_for_all_items()

View File

@ -1,19 +1,20 @@
def draw_settings_ui(layout, registry):
def draw_settings_ui(layout, component_settings):
row = layout.row()
col = row.column()
col.enabled = False
col.prop(registry, "schemaPath", text="Registry Schema path")
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="object.reload_registry", text="reload registry" , icon="FILE_REFRESH")
layout.operator(operator="blenvy.reload_components_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)")
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()

View File

@ -5,27 +5,36 @@ from bpy.props import (EnumProperty, PointerProperty, StringProperty, Collection
from .scene_helpers import SceneSelector
from ..settings import upsert_settings, load_settings
import blenvy.add_ons.auto_export.settings as auto_export_settings
import blenvy.add_ons.bevy_components.settings as component_settings
def update_scene_lists(self, context):
blenvy = self# context.window_manager.blenvy
def update_scene_lists(blenvy, context):
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(self, context):
blenvy = self # context.window_manager.blenvy
def update_asset_folders(blenvy, context):
asset_path_names = ['project_root_path', 'assets_path', 'blueprints_path', 'levels_path', 'materials_path']
for asset_path_name in asset_path_names:
upsert_settings(blenvy.settings_save_path, {asset_path_name: getattr(blenvy, asset_path_name)})
def update_mode(self, context):
blenvy = self
def update_mode(blenvy, context):
upsert_settings(blenvy.settings_save_path, {"mode": blenvy.mode })
def is_scene_ok(self, scene):
try:
print("SELF", self)
return scene.name not in self.main_scenes and scene.name not in self.library_scenes
except:
print("FAILURE")
return True
class BlenvyManager(PropertyGroup):
settings_save_path = ".blenvy_settings" # where to store data in bpy.texts
settings_save_path = ".blenvy_common_settings" # where to store data in bpy.texts
mode: EnumProperty(
items=(
@ -109,27 +118,20 @@ class BlenvyManager(PropertyGroup):
# sub ones
auto_export: PointerProperty(type=auto_export_settings.AutoExportSettings) # type: ignore
#components: PointerProperty(type=bevy_component_settings.ComponentSettings) # type: ignore
components: PointerProperty(type=component_settings.ComponentsSettings) # type: ignore
main_scene_selector: PointerProperty(type=bpy.types.Scene, name="main scene", description="main_scene_picker", poll=is_scene_ok)# type: ignore
library_scene_selector: PointerProperty(type=bpy.types.Scene, name="library scene", description="library_scene_picker", poll=is_scene_ok)# 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")
@ -150,3 +152,9 @@ 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.auto_export.load_settings()

View File

@ -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.main_scene:
new_scene_name = context.window_manager.main_scene.name
if context.window_manager.blenvy.main_scene_selector:
new_scene_name = context.window_manager.blenvy.main_scene_selector.name
else:
if context.window_manager.library_scene:
new_scene_name = context.window_manager.library_scene.name
if context.window_manager.blenvy.library_scene_selector:
new_scene_name = context.window_manager.blenvy.library_scene_selector.name
if new_scene_name:
item = target.add()
item.name = new_scene_name
if self.scene_type == "LEVEL":
context.window_manager.main_scene = None
context.window_manager.blenvy.main_scene_selector = None
else:
context.window_manager.library_scene = None
context.window_manager.blenvy.library_scene_selector = None
setattr(source, target_index, len(target) - 1)

View File

@ -104,7 +104,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
rows = 2
row = section.row()
row.label(text="main scenes")
row.prop(context.window_manager, "main_scene", text='')
row.prop(blenvy, "main_scene_selector", text='')
row = section.row()
row.template_list("SCENE_UL_Blenvy", "level scenes", blenvy, "main_scenes", blenvy, "main_scenes_index", rows=rows)
@ -115,7 +115,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
add_operator.action = 'ADD'
add_operator.scene_type = 'LEVEL'
#add_operator.operator = operator
sub_row.enabled = context.window_manager.main_scene is not None
sub_row.enabled = blenvy.main_scene_selector is not None
sub_row = col.row()
remove_operator = sub_row.operator("scene_list.list_action", icon='REMOVE', text="")
@ -126,7 +126,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel):
# library scenes
row = section.row()
row.label(text="library scenes")
row.prop(context.window_manager, "library_scene", text='')
row.prop(blenvy, "library_scene_selector", text='')
row = section.row()
row.template_list("SCENE_UL_Blenvy", "library scenes", blenvy, "library_scenes", blenvy, "library_scenes_index", rows=rows)
@ -136,7 +136,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 = context.window_manager.library_scene is not None
sub_row.enabled = blenvy.library_scene_selector is not None
sub_row = col.row()
@ -148,7 +148,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, context.window_manager.components_registry)
components_ui.draw_settings_ui(panel, blenvy.components)
header, panel = layout.panel("auto_export", default_closed=False)
header.label(text="Auto Export")

View File

@ -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#bpy.data.texts.new(name)
stored_settings = bpy.data.texts[name] if name in bpy.data.texts else None
if stored_settings is None:
stored_settings = bpy.data.texts.new(name)
stored_settings.write(json.dumps(data))
@ -21,6 +21,41 @@ def load_settings(name):
return None
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=[]):
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)
defaults[k] = default
#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)
print("complete_preferences", complete_preferences)
"""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] = settings[key]"""
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:

View File

@ -5,9 +5,9 @@ import pytest
def setup_data(request):
print("\nSetting up resources...")
schemaPath = "../../testing/bevy_example/assets/registry.json"
schema_path = "../../testing/bevy_example/assets/registry.json"
yield {"schema_path": schemaPath}
yield {"schema_path": schema_path}
def finalizer():
print("\nPerforming teardown...")

View File

@ -11,7 +11,7 @@ from .setup_data import setup_data
def test_components_should_generate_correct_custom_properties(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
type_infos = registry.type_infos
@ -58,7 +58,7 @@ def test_components_should_generate_correct_custom_properties(setup_data):
def test_components_should_generate_correct_custom_properties_with_randomized_values(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
type_infos = registry.type_infos
@ -108,7 +108,7 @@ def test_components_should_generate_correct_custom_properties_with_randomized_va
def test_components_should_generate_correct_propertyGroup_values_from_custom_properties(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
type_infos = registry.type_infos
@ -166,7 +166,7 @@ def test_components_should_generate_correct_propertyGroup_values_from_custom_pro
def test_remove_components(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
type_infos = registry.type_infos
@ -207,7 +207,7 @@ def test_remove_components(setup_data):
def test_copy_paste_components(setup_data):
context = bpy.context
registry = context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
long_name = "bevy_example::test_components::BasicTest"

View File

@ -3,7 +3,7 @@ from .setup_data import setup_data
def test_blend(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
long_name = "bevy_example::test_components::BasicTest"

View File

@ -24,7 +24,7 @@ def get_component_propGroup(registry, component_name, component_meta):
def test_rename_component_single_unit_struct(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
rename_component_operator = bpy.ops.object.rename_bevy_component
@ -47,7 +47,7 @@ def test_rename_component_single_unit_struct(setup_data):
def test_rename_component_single_complex_struct(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
rename_component_operator = bpy.ops.object.rename_bevy_component
@ -70,7 +70,7 @@ def test_rename_component_single_complex_struct(setup_data):
def test_rename_component_bulk(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
rename_component_operator = bpy.ops.object.rename_bevy_component
@ -95,7 +95,7 @@ def test_rename_component_bulk(setup_data):
def test_rename_component_single_error_handling(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
rename_component_operator = bpy.ops.object.rename_bevy_component
@ -125,7 +125,7 @@ def test_rename_component_single_error_handling(setup_data):
def test_rename_component_single_error_handling_clean_errors(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["components_schemaPath"]
registry.schema_path = setup_data["components_schemaPath"]
bpy.ops.object.reload_registry()
rename_component_operator = bpy.ops.object.rename_bevy_component

View File

@ -5,7 +5,7 @@ from .setup_data import setup_data
def test_shuffler(setup_data):
registry = bpy.context.window_manager.components_registry
registry.schemaPath = setup_data["schema_path"]
registry.schema_path = setup_data["schema_path"]
bpy.ops.object.reload_registry()
type_infos = registry.type_infos