Started working on synchronising settings
This commit is contained in:
parent
58785977e7
commit
efb1456596
@ -66,20 +66,23 @@ def register():
|
||||
blender = reload_mod('blender')
|
||||
gui = reload_mod('gui')
|
||||
async_loop = reload_mod('async_loop')
|
||||
settings_sync = reload_mod('settings_sync')
|
||||
else:
|
||||
from . import blender, gui, async_loop
|
||||
from . import blender, gui, async_loop, settings_sync
|
||||
|
||||
async_loop.setup_asyncio_executor()
|
||||
async_loop.register()
|
||||
|
||||
blender.register()
|
||||
gui.register()
|
||||
settings_sync.register()
|
||||
|
||||
|
||||
def unregister():
|
||||
from . import blender, gui, async_loop
|
||||
from . import blender, gui, async_loop, settings_sync
|
||||
|
||||
gui.unregister()
|
||||
blender.unregister()
|
||||
async_loop.unregister()
|
||||
settings_sync.unregister()
|
||||
|
||||
|
129
blender_cloud/settings_sync.py
Normal file
129
blender_cloud/settings_sync.py
Normal file
@ -0,0 +1,129 @@
|
||||
"""Synchronizes settings & startup file with the Cloud."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import bpy
|
||||
import pillarsdk
|
||||
from pillarsdk import exceptions as sdk_exceptions
|
||||
from .pillar import pillar_call, check_pillar_credentials, PillarError
|
||||
from . import async_loop
|
||||
|
||||
HOME_PROJECT_ENDPOINT = '/bcloud/home-project'
|
||||
SYNC_GROUP_NODE_NAME = 'Blender Sync'
|
||||
SYNC_GROUP_NODE_DESC = 'The [Blender Cloud Addon](https://cloud.blender.org/services' \
|
||||
'#blender-addon) will synchronize your Blender settings here.'
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def get_home_project(params=None) -> pillarsdk.Project:
|
||||
"""Returns the home project."""
|
||||
|
||||
log.debug('Getting home project')
|
||||
try:
|
||||
return await pillar_call(pillarsdk.Project.find_from_endpoint,
|
||||
HOME_PROJECT_ENDPOINT, params=params)
|
||||
except sdk_exceptions.ForbiddenAccess:
|
||||
log.warning('Access to the home project was denied. '
|
||||
'Double-check that you are a cloud subscriber and logged in.')
|
||||
raise
|
||||
|
||||
|
||||
async def get_home_project_id():
|
||||
home_proj = await get_home_project({'projection': {'_id': 1}})
|
||||
home_proj_id = home_proj['_id']
|
||||
return home_proj_id
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
class PILLAR_OT_sync(async_loop.AsyncModalOperatorMixin, bpy.types.Operator):
|
||||
bl_idname = 'pillar.sync'
|
||||
bl_label = 'Synchronise with Blender Cloud'
|
||||
|
||||
log = logging.getLogger('bpy.ops.%s' % bl_idname)
|
||||
|
||||
action = bpy.props.EnumProperty(
|
||||
items=[
|
||||
('PUSH', 'Push', 'Push settings to the Blender Cloud'),
|
||||
('PULL', 'Pull', 'Pull settings from the Blender Cloud'),
|
||||
],
|
||||
name='action',
|
||||
description='Synchronises settings with the Blender Cloud.')
|
||||
|
||||
def invoke(self, context, event):
|
||||
async_loop.AsyncModalOperatorMixin.invoke(self, context, event)
|
||||
|
||||
log.info('Starting synchronisation')
|
||||
self._new_async_task(self.async_execute())
|
||||
self.report({'INFO'}, 'Synchronizing settings with Blender Cloud')
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def modal(self, context, event):
|
||||
result = async_loop.AsyncModalOperatorMixin.modal(self, context, event)
|
||||
if not {'PASS_THROUGH', 'RUNNING_MODAL'}.intersection(result):
|
||||
self.log.info('Stopped')
|
||||
return result
|
||||
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
async def async_execute(self):
|
||||
self.user_id = await check_pillar_credentials()
|
||||
try:
|
||||
group_id = await self.find_sync_group_id()
|
||||
self.log.info('Found group node ID: %s', group_id)
|
||||
except sdk_exceptions.ForbiddenAccess as ex:
|
||||
self.log.exception('Unable to find Group ID')
|
||||
|
||||
self._state = 'QUIT'
|
||||
|
||||
async def find_sync_group_id(self) -> pillarsdk.Node:
|
||||
"""Finds the group node in which to store sync assets.
|
||||
|
||||
If the group node doesn't exist, it creates it.
|
||||
"""
|
||||
|
||||
home_proj_id = await get_home_project_id()
|
||||
|
||||
node_props = {'project': home_proj_id,
|
||||
'node_type': 'group',
|
||||
'parent': None,
|
||||
'name': SYNC_GROUP_NODE_NAME,
|
||||
'user': self.user_id}
|
||||
sync_group = await pillar_call(pillarsdk.Node.find_first, {
|
||||
'where': node_props,
|
||||
'projection': {'_id': 1}
|
||||
})
|
||||
|
||||
if sync_group is None:
|
||||
log.debug('Creating new sync group node')
|
||||
|
||||
# Augment the node properties to form a complete node.
|
||||
node_props['description'] = SYNC_GROUP_NODE_DESC
|
||||
node_props['properties'] = {'status': 'published'}
|
||||
|
||||
sync_group = pillarsdk.Node.new(node_props)
|
||||
created_ok = await pillar_call(sync_group.create)
|
||||
if not created_ok:
|
||||
log.error('Blender Cloud addon: unable to create sync folder on the Cloud.')
|
||||
raise PillarError('Unable to create sync folder on the Cloud')
|
||||
|
||||
return sync_group['_id']
|
||||
|
||||
|
||||
def draw_userpref_header(self: bpy.types.USERPREF_HT_header, context):
|
||||
"""Adds some buttons to the userprefs header."""
|
||||
|
||||
layout = self.layout
|
||||
layout.operator('pillar.sync', icon='FILE_REFRESH',
|
||||
text='Push to Cloud').action = 'PUSH'
|
||||
layout.operator('pillar.sync', icon='FILE_REFRESH',
|
||||
text='Pull from Cloud').action = 'PULL'
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(PILLAR_OT_sync)
|
||||
bpy.types.USERPREF_HT_header.append(draw_userpref_header)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(PILLAR_OT_sync)
|
||||
bpy.types.USERPREF_HT_header.remove(draw_userpref_header)
|
Reference in New Issue
Block a user