2018-01-02 16:42:37 +01:00
|
|
|
"""Handle saving and loading project-specific settings."""
|
|
|
|
|
2018-09-04 17:37:07 +02:00
|
|
|
import contextlib
|
2018-01-02 16:42:37 +01:00
|
|
|
import logging
|
2018-12-06 15:46:54 +01:00
|
|
|
import typing
|
2018-01-02 16:42:37 +01:00
|
|
|
|
|
|
|
# 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',
|
|
|
|
)
|
|
|
|
|
2018-11-16 17:12:30 +01:00
|
|
|
# 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',
|
2018-12-06 15:46:54 +01:00
|
|
|
'flamenco_relative_only',
|
2018-11-16 17:12:30 +01:00
|
|
|
)
|
|
|
|
|
2018-01-02 16:42:37 +01:00
|
|
|
log = logging.getLogger(__name__)
|
2018-11-16 16:52:02 +01:00
|
|
|
project_settings_loading = 0 # counter, if > 0 then we're loading stuff.
|
2018-01-02 16:42:37 +01:00
|
|
|
|
|
|
|
|
2018-09-04 17:37:07 +02:00
|
|
|
@contextlib.contextmanager
|
|
|
|
def mark_as_loading():
|
2018-11-16 16:52:02 +01:00
|
|
|
"""Sets project_settings_loading > 0 while the context is active.
|
|
|
|
|
|
|
|
A counter is used to allow for nested mark_as_loading() contexts.
|
|
|
|
"""
|
2018-09-04 17:37:07 +02:00
|
|
|
global project_settings_loading
|
2018-11-16 16:52:02 +01:00
|
|
|
project_settings_loading += 1
|
2018-09-04 17:37:07 +02:00
|
|
|
try:
|
|
|
|
yield
|
|
|
|
finally:
|
2018-11-16 16:52:02 +01:00
|
|
|
project_settings_loading -= 1
|
2018-09-04 17:37:07 +02:00
|
|
|
|
|
|
|
|
2018-12-06 15:46:54 +01:00
|
|
|
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'])
|
|
|
|
|
|
|
|
|
2018-01-02 16:42:37 +01:00
|
|
|
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
|
|
|
|
|
2018-09-04 17:37:07 +02:00
|
|
|
with mark_as_loading():
|
2018-01-02 16:42:37 +01:00
|
|
|
prefs = preferences()
|
|
|
|
project_id = prefs.project.project
|
2020-11-12 12:31:17 +01:00
|
|
|
log.debug('Updating internal state to reflect extensions enabled on current project %s.',
|
|
|
|
project_id)
|
2018-01-02 16:42:37 +01:00
|
|
|
|
|
|
|
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:
|
2018-09-04 17:38:21 +02:00
|
|
|
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 = []
|
2018-01-02 16:42:37 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
if log.isEnabledFor(logging.DEBUG):
|
|
|
|
from pprint import pformat
|
|
|
|
log.debug('loading project-specific settings:\n%s', pformat(ps.to_dict()))
|
|
|
|
|
2018-09-04 17:38:21 +02:00
|
|
|
# Restore simple properties.
|
2018-12-06 15:46:54 +01:00
|
|
|
update_preferences(prefs, PROJECT_SPECIFIC_SIMPLE_PROPS, ps)
|
2018-09-04 17:38:21 +02:00
|
|
|
|
|
|
|
# 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)
|
2018-03-16 14:13:29 +01:00
|
|
|
try:
|
2018-11-16 16:52:02 +01:00
|
|
|
# This will trigger a load of Project+Manager-specfic settings.
|
2018-09-04 17:38:21 +02:00
|
|
|
prefs.flamenco_manager.manager = flamenco_manager_id
|
2018-03-16 14:13:29 +01:00
|
|
|
except TypeError:
|
2018-09-04 17:38:21 +02:00
|
|
|
log.warning('manager %s for this project could not be found', flamenco_manager_id)
|
2018-09-17 18:23:41 +02:00
|
|
|
elif prefs.flamenco_manager.available_managers:
|
2019-03-26 12:35:27 +01:00
|
|
|
prefs.flamenco_manager.manager = prefs.flamenco_manager.available_managers[0]['_id']
|
2018-01-02 16:42:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
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', {})
|
2018-09-04 14:31:08 +02:00
|
|
|
ps = all_settings.get(project_id, {}) # either a dict or bpy.types.IDPropertyGroup
|
2018-01-02 16:42:37 +01:00
|
|
|
|
|
|
|
for name in PROJECT_SPECIFIC_SIMPLE_PROPS:
|
|
|
|
ps[name] = getattr(prefs, name)
|
2018-07-25 15:01:39 +02:00
|
|
|
|
2018-09-04 17:38:21 +02:00
|
|
|
# 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] = {
|
2018-11-16 17:12:30 +01:00
|
|
|
name: getattr(prefs, name) for name in FLAMENCO_PER_PROJECT_PER_MANAGER
|
|
|
|
}
|
2018-09-04 17:38:21 +02:00
|
|
|
ps['flamenco_managers_settings'] = pppm # IDPropertyGroup has no setdefault() method.
|
|
|
|
|
|
|
|
# Store this project's settings in the preferences.
|
2018-01-02 16:42:37 +01:00
|
|
|
all_settings[project_id] = ps
|
|
|
|
prefs['project_settings'] = all_settings
|
2018-07-25 15:01:39 +02:00
|
|
|
|
2018-09-05 13:28:56 +02:00
|
|
|
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))
|