- No longer list Attract's RNA classes, these haven't changed in a long time and it's not interesting to see. - Reduced log level when updating internal state. The result of the update is already logged at INFO level.
164 lines
6.0 KiB
Python
164 lines
6.0 KiB
Python
"""Handle saving and loading project-specific settings."""
|
|
|
|
import contextlib
|
|
import logging
|
|
import typing
|
|
|
|
# Names of BlenderCloudPreferences properties that are both project-specific
|
|
# and simple enough to store directly in a dict.
|
|
PROJECT_SPECIFIC_SIMPLE_PROPS = (
|
|
'cloud_project_local_path',
|
|
)
|
|
|
|
# Names of BlenderCloudPreferences properties that are project-specific and
|
|
# Flamenco Manager-specific, and simple enough to store in a dict.
|
|
FLAMENCO_PER_PROJECT_PER_MANAGER = (
|
|
'flamenco_exclude_filter',
|
|
'flamenco_job_file_path',
|
|
'flamenco_job_output_path',
|
|
'flamenco_job_output_strip_components',
|
|
'flamenco_relative_only',
|
|
)
|
|
|
|
log = logging.getLogger(__name__)
|
|
project_settings_loading = 0 # counter, if > 0 then we're loading stuff.
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def mark_as_loading():
|
|
"""Sets project_settings_loading > 0 while the context is active.
|
|
|
|
A counter is used to allow for nested mark_as_loading() contexts.
|
|
"""
|
|
global project_settings_loading
|
|
project_settings_loading += 1
|
|
try:
|
|
yield
|
|
finally:
|
|
project_settings_loading -= 1
|
|
|
|
|
|
def update_preferences(prefs, names_to_update: typing.Iterable[str],
|
|
new_values: typing.Mapping[str, typing.Any]):
|
|
for name in names_to_update:
|
|
if not hasattr(prefs, name):
|
|
log.debug('not setting %r, property cannot be found', name)
|
|
continue
|
|
|
|
if name in new_values:
|
|
log.debug('setting %r = %r', name, new_values[name])
|
|
setattr(prefs, name, new_values[name])
|
|
else:
|
|
# The property wasn't stored, so set the default value instead.
|
|
bl_type, args = getattr(prefs.bl_rna, name)
|
|
log.debug('finding default value for %r', name)
|
|
if 'default' not in args:
|
|
log.debug('no default value for %r, not touching', name)
|
|
continue
|
|
log.debug('found default value for %r = %r', name, args['default'])
|
|
setattr(prefs, name, args['default'])
|
|
|
|
|
|
def handle_project_update(_=None, _2=None):
|
|
"""Handles changing projects, which may cause extensions to be disabled/enabled.
|
|
|
|
Ignores arguments so that it can be used as property update callback.
|
|
"""
|
|
|
|
from .blender import preferences, project_extensions
|
|
|
|
with mark_as_loading():
|
|
prefs = preferences()
|
|
project_id = prefs.project.project
|
|
log.debug('Updating internal state to reflect extensions enabled on current project %s.',
|
|
project_id)
|
|
|
|
project_extensions.cache_clear()
|
|
|
|
from blender_cloud import attract, flamenco
|
|
attract.deactivate()
|
|
flamenco.deactivate()
|
|
|
|
enabled_for = project_extensions(project_id)
|
|
log.info('Project extensions: %s', enabled_for)
|
|
if 'attract' in enabled_for:
|
|
attract.activate()
|
|
if 'flamenco' in enabled_for:
|
|
flamenco.activate()
|
|
|
|
# Load project-specific settings from the last time we visited this project.
|
|
ps = prefs.get('project_settings', {}).get(project_id, {})
|
|
if not ps:
|
|
log.debug('no project-specific settings are available, '
|
|
'only resetting available Flamenco Managers')
|
|
# The Flamenco Manager should really be chosen explicitly out of the available
|
|
# Managers.
|
|
prefs.flamenco_manager.available_managers = []
|
|
return
|
|
|
|
if log.isEnabledFor(logging.DEBUG):
|
|
from pprint import pformat
|
|
log.debug('loading project-specific settings:\n%s', pformat(ps.to_dict()))
|
|
|
|
# Restore simple properties.
|
|
update_preferences(prefs, PROJECT_SPECIFIC_SIMPLE_PROPS, ps)
|
|
|
|
# Restore Flamenco settings.
|
|
prefs.flamenco_manager.available_managers = ps.get('flamenco_available_managers', [])
|
|
flamenco_manager_id = ps.get('flamenco_manager_id')
|
|
if flamenco_manager_id:
|
|
log.debug('setting flamenco manager to %s', flamenco_manager_id)
|
|
try:
|
|
# This will trigger a load of Project+Manager-specfic settings.
|
|
prefs.flamenco_manager.manager = flamenco_manager_id
|
|
except TypeError:
|
|
log.warning('manager %s for this project could not be found', flamenco_manager_id)
|
|
elif prefs.flamenco_manager.available_managers:
|
|
prefs.flamenco_manager.manager = prefs.flamenco_manager.available_managers[0]['_id']
|
|
|
|
|
|
def store(_=None, _2=None):
|
|
"""Remember project-specific settings as soon as one of them changes.
|
|
|
|
Ignores arguments so that it can be used as property update callback.
|
|
|
|
No-op when project_settings_loading=True, to prevent saving project-
|
|
specific settings while they are actually being loaded.
|
|
"""
|
|
from .blender import preferences
|
|
|
|
global project_settings_loading
|
|
if project_settings_loading:
|
|
return
|
|
|
|
prefs = preferences()
|
|
project_id = prefs.project.project
|
|
all_settings = prefs.get('project_settings', {})
|
|
ps = all_settings.get(project_id, {}) # either a dict or bpy.types.IDPropertyGroup
|
|
|
|
for name in PROJECT_SPECIFIC_SIMPLE_PROPS:
|
|
ps[name] = getattr(prefs, name)
|
|
|
|
# Store project-specific Flamenco settings
|
|
ps['flamenco_manager_id'] = prefs.flamenco_manager.manager
|
|
ps['flamenco_available_managers'] = prefs.flamenco_manager.available_managers
|
|
|
|
# Store per-project, per-manager settings for the current Manager.
|
|
pppm = ps.get('flamenco_managers_settings', {})
|
|
pppm[prefs.flamenco_manager.manager] = {
|
|
name: getattr(prefs, name) for name in FLAMENCO_PER_PROJECT_PER_MANAGER
|
|
}
|
|
ps['flamenco_managers_settings'] = pppm # IDPropertyGroup has no setdefault() method.
|
|
|
|
# Store this project's settings in the preferences.
|
|
all_settings[project_id] = ps
|
|
prefs['project_settings'] = all_settings
|
|
|
|
if log.isEnabledFor(logging.DEBUG):
|
|
from pprint import pformat
|
|
if hasattr(all_settings, 'to_dict'):
|
|
to_log = all_settings.to_dict()
|
|
else:
|
|
to_log = all_settings
|
|
log.debug('Saving project-specific settings:\n%s', pformat(to_log))
|