Compare commits
17 Commits
version-1.
...
version-1.
Author | SHA1 | Date | |
---|---|---|---|
a45bf3cd5c | |||
3789742cc8 | |||
58f374e175 | |||
99e90e1008 | |||
dd83d3ee60 | |||
e74e014c66 | |||
01541f181e | |||
a69f4d3fd9 | |||
3ffea46f23 | |||
94c5811e42 | |||
676ad1ed14 | |||
79e6fa37f4 | |||
e06fa3ea75 | |||
fb6352dc7d | |||
97ad8bf5ba | |||
b0f7719add | |||
dada275e32 |
@@ -1,5 +1,13 @@
|
|||||||
# Blender Cloud changelog
|
# Blender Cloud changelog
|
||||||
|
|
||||||
|
## Version 1.13 (2019-04-18)
|
||||||
|
|
||||||
|
- Upgraded BAT to 1.1.1 for a compatibility fix with Blender 2.79
|
||||||
|
- Flamenco: Support for Flamenco Manager settings versioning + for settings version 2.
|
||||||
|
When using Blender Cloud Add-on 1.12 or older, Flamenco Server will automatically convert the
|
||||||
|
Manager settings to version 1.
|
||||||
|
|
||||||
|
|
||||||
## Version 1.12 (2019-03-25)
|
## Version 1.12 (2019-03-25)
|
||||||
|
|
||||||
- Flamenco: Change how progressive render tasks are created. Instead of the artist setting a fixed
|
- Flamenco: Change how progressive render tasks are created. Instead of the artist setting a fixed
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
'name': 'Blender Cloud',
|
'name': 'Blender Cloud',
|
||||||
"author": "Sybren A. Stüvel, Francesco Siddi, Inês Almeida, Antony Riakiotakis",
|
"author": "Sybren A. Stüvel, Francesco Siddi, Inês Almeida, Antony Riakiotakis",
|
||||||
'version': (1, 12, 0),
|
'version': (1, 13, 3),
|
||||||
'blender': (2, 80, 0),
|
'blender': (2, 80, 0),
|
||||||
'location': 'Addon Preferences panel, and Ctrl+Shift+Alt+A anywhere for texture browser',
|
'location': 'Addon Preferences panel, and Ctrl+Shift+Alt+A anywhere for texture browser',
|
||||||
'description': 'Texture library browser and Blender Sync. Requires the Blender ID addon '
|
'description': 'Texture library browser and Blender Sync. Requires the Blender ID addon '
|
||||||
|
@@ -1023,7 +1023,12 @@ def register():
|
|||||||
name="Status")
|
name="Status")
|
||||||
bpy.types.Sequence.atc_order = bpy.props.IntProperty(name="Order")
|
bpy.types.Sequence.atc_order = bpy.props.IntProperty(name="Order")
|
||||||
|
|
||||||
bpy.types.SEQUENCER_PT_edit.append(draw_strip_movie_meta)
|
try:
|
||||||
|
panel = bpy.types.SEQUENCER_PT_info_input
|
||||||
|
except AttributeError:
|
||||||
|
# Blender 2.79 and older:
|
||||||
|
panel = bpy.types.SEQUENCER_PT_edit
|
||||||
|
panel.append(draw_strip_movie_meta)
|
||||||
|
|
||||||
for cls in _rna_classes:
|
for cls in _rna_classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
|
@@ -383,18 +383,17 @@ class BlenderCloudPreferences(AddonPreferences):
|
|||||||
icon='TRIA_UP').action = 'PUSH'
|
icon='TRIA_UP').action = 'PUSH'
|
||||||
|
|
||||||
versions = bss.available_blender_versions
|
versions = bss.available_blender_versions
|
||||||
version = bss.version
|
|
||||||
if bss.status in {'NONE', 'IDLE'}:
|
if bss.status in {'NONE', 'IDLE'}:
|
||||||
if not versions or not version:
|
if not versions:
|
||||||
row_pull.operator('pillar.sync',
|
row_pull.operator('pillar.sync',
|
||||||
text='Find version to load',
|
text='Find version to load',
|
||||||
icon='TRIA_DOWN').action = 'REFRESH'
|
icon='TRIA_DOWN').action = 'REFRESH'
|
||||||
else:
|
else:
|
||||||
props = row_pull.operator('pillar.sync',
|
props = row_pull.operator('pillar.sync',
|
||||||
text='Load %s settings' % version,
|
text='Load %s settings' % bss.version,
|
||||||
icon='TRIA_DOWN')
|
icon='TRIA_DOWN')
|
||||||
props.action = 'PULL'
|
props.action = 'PULL'
|
||||||
props.blender_version = version
|
props.blender_version = bss.version
|
||||||
row_pull.operator('pillar.sync',
|
row_pull.operator('pillar.sync',
|
||||||
text='',
|
text='',
|
||||||
icon=SYNC_SELECT_VERSION_ICON).action = 'SELECT'
|
icon=SYNC_SELECT_VERSION_ICON).action = 'SELECT'
|
||||||
@@ -450,7 +449,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
|||||||
manager_box = manager_split.row(align=True)
|
manager_box = manager_split.row(align=True)
|
||||||
|
|
||||||
if bcp.status in {'NONE', 'IDLE'}:
|
if bcp.status in {'NONE', 'IDLE'}:
|
||||||
if not bcp.available_managers or not bcp.manager:
|
if not bcp.available_managers:
|
||||||
manager_box.operator('flamenco.managers',
|
manager_box.operator('flamenco.managers',
|
||||||
text='Find Flamenco Managers',
|
text='Find Flamenco Managers',
|
||||||
icon='FILE_REFRESH')
|
icon='FILE_REFRESH')
|
||||||
|
@@ -199,18 +199,26 @@ class FLAMENCO_OT_fmanagers(async_loop.AsyncModalOperatorMixin,
|
|||||||
from ..blender import preferences
|
from ..blender import preferences
|
||||||
|
|
||||||
prefs = preferences()
|
prefs = preferences()
|
||||||
|
mypref = self.mypref
|
||||||
|
|
||||||
self.log.info('Going to fetch managers for user %s', self.user_id)
|
self.log.info('Going to fetch managers for user %s', self.user_id)
|
||||||
|
|
||||||
self.mypref.status = 'FETCHING'
|
mypref.status = 'FETCHING'
|
||||||
params = {'where': '{"projects" : "%s"}' % prefs.project.project}
|
params = {'where': '{"projects" : "%s"}' % prefs.project.project}
|
||||||
managers = await pillar_call(Manager.all, params)
|
managers = await pillar_call(Manager.all, params)
|
||||||
|
|
||||||
# We need to convert to regular dicts before storing in ID properties.
|
# We need to convert to regular dicts before storing in ID properties.
|
||||||
# Also don't store more properties than we need.
|
# Also don't store more properties than we need.
|
||||||
as_list = [{'_id': p['_id'], 'name': p['name']} for p in managers['_items']]
|
as_list = [{'_id': man['_id'], 'name': man['name']}
|
||||||
|
for man in managers['_items']]
|
||||||
|
|
||||||
|
current_manager = mypref.manager
|
||||||
|
mypref.available_managers = as_list
|
||||||
|
|
||||||
|
# Prevent warnings about the current manager not being in the EnumProperty items.
|
||||||
|
if as_list and not any(man['_id'] == current_manager for man in as_list):
|
||||||
|
mypref.manager = as_list[0]['_id']
|
||||||
|
|
||||||
self.mypref.available_managers = as_list
|
|
||||||
self.quit()
|
self.quit()
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import functools
|
import functools
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import typing
|
||||||
|
|
||||||
from pillarsdk.resource import List, Find, Create
|
from pillarsdk.resource import List, Find, Create
|
||||||
|
|
||||||
@@ -9,8 +10,28 @@ class Manager(List, Find):
|
|||||||
path = 'flamenco/managers'
|
path = 'flamenco/managers'
|
||||||
PurePlatformPath = pathlib.PurePath
|
PurePlatformPath = pathlib.PurePath
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache(maxsize=1)
|
||||||
def _sorted_path_replacements(self) -> list:
|
def _path_replacements(self) -> list:
|
||||||
|
"""Defer to _path_replacements_vN() to get path replacement vars.
|
||||||
|
|
||||||
|
Returns a list of tuples (variable name, variable value).
|
||||||
|
"""
|
||||||
|
settings_version = self.settings_version or 1
|
||||||
|
try:
|
||||||
|
settings_func = getattr(self, '_path_replacements_v%d' % settings_version)
|
||||||
|
except AttributeError:
|
||||||
|
raise RuntimeError('This manager has unsupported settings version %d; '
|
||||||
|
'upgrade Blender Cloud add-on')
|
||||||
|
|
||||||
|
def longest_value_first(item):
|
||||||
|
var_name, var_value = item
|
||||||
|
return -len(var_value), var_value, var_name
|
||||||
|
|
||||||
|
replacements = settings_func()
|
||||||
|
replacements.sort(key=longest_value_first)
|
||||||
|
return replacements
|
||||||
|
|
||||||
|
def _path_replacements_v1(self) -> typing.List[typing.Tuple[str, str]]:
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
if self.path_replacement is None:
|
if self.path_replacement is None:
|
||||||
@@ -18,14 +39,35 @@ class Manager(List, Find):
|
|||||||
|
|
||||||
items = self.path_replacement.to_dict().items()
|
items = self.path_replacement.to_dict().items()
|
||||||
|
|
||||||
def by_length(item):
|
|
||||||
return -len(item[0]), item[0]
|
|
||||||
|
|
||||||
this_platform = platform.system().lower()
|
this_platform = platform.system().lower()
|
||||||
return [(varname, platform_replacements[this_platform])
|
return [(varname, platform_replacements[this_platform])
|
||||||
for varname, platform_replacements in sorted(items, key=by_length)
|
for varname, platform_replacements in items
|
||||||
if this_platform in platform_replacements]
|
if this_platform in platform_replacements]
|
||||||
|
|
||||||
|
def _path_replacements_v2(self) -> typing.List[typing.Tuple[str, str]]:
|
||||||
|
import platform
|
||||||
|
|
||||||
|
if not self.variables:
|
||||||
|
return []
|
||||||
|
|
||||||
|
this_platform = platform.system().lower()
|
||||||
|
audiences = {'users', 'all'}
|
||||||
|
|
||||||
|
replacements = []
|
||||||
|
for var_name, variable in self.variables.to_dict().items():
|
||||||
|
# Path replacement requires bidirectional variables.
|
||||||
|
if variable.get('direction') != 'twoway':
|
||||||
|
continue
|
||||||
|
|
||||||
|
for var_value in variable.get('values', []):
|
||||||
|
if var_value.get('audience') not in audiences:
|
||||||
|
continue
|
||||||
|
if var_value.get('platform', '').lower() != this_platform:
|
||||||
|
continue
|
||||||
|
|
||||||
|
replacements.append((var_name, var_value.get('value')))
|
||||||
|
return replacements
|
||||||
|
|
||||||
def replace_path(self, some_path: pathlib.PurePath) -> str:
|
def replace_path(self, some_path: pathlib.PurePath) -> str:
|
||||||
"""Performs path variable replacement.
|
"""Performs path variable replacement.
|
||||||
|
|
||||||
@@ -35,7 +77,7 @@ class Manager(List, Find):
|
|||||||
assert isinstance(some_path, pathlib.PurePath), \
|
assert isinstance(some_path, pathlib.PurePath), \
|
||||||
'some_path should be a PurePath, not %r' % some_path
|
'some_path should be a PurePath, not %r' % some_path
|
||||||
|
|
||||||
for varname, path in self._sorted_path_replacements():
|
for varname, path in self._path_replacements():
|
||||||
replacement = self.PurePlatformPath(path)
|
replacement = self.PurePlatformPath(path)
|
||||||
try:
|
try:
|
||||||
relpath = some_path.relative_to(replacement)
|
relpath = some_path.relative_to(replacement)
|
||||||
@@ -57,7 +99,6 @@ class Job(List, Find, Create):
|
|||||||
|
|
||||||
def patch(self, payload: dict, api=None):
|
def patch(self, payload: dict, api=None):
|
||||||
import pillarsdk.utils
|
import pillarsdk.utils
|
||||||
import json
|
|
||||||
|
|
||||||
api = api or self.api
|
api = api or self.api
|
||||||
|
|
||||||
|
@@ -114,7 +114,7 @@ def handle_project_update(_=None, _2=None):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
log.warning('manager %s for this project could not be found', flamenco_manager_id)
|
log.warning('manager %s for this project could not be found', flamenco_manager_id)
|
||||||
elif prefs.flamenco_manager.available_managers:
|
elif prefs.flamenco_manager.available_managers:
|
||||||
prefs.flamenco_manager.manager = prefs.flamenco_manager.available_managers[0]
|
prefs.flamenco_manager.manager = prefs.flamenco_manager.available_managers[0]['_id']
|
||||||
|
|
||||||
|
|
||||||
def store(_=None, _2=None):
|
def store(_=None, _2=None):
|
||||||
|
@@ -416,11 +416,20 @@ class PILLAR_OT_sync(pillar.PillarOperatorMixin,
|
|||||||
bss = bpy.context.window_manager.blender_sync_status
|
bss = bpy.context.window_manager.blender_sync_status
|
||||||
bss.available_blender_versions = versions
|
bss.available_blender_versions = versions
|
||||||
|
|
||||||
if versions:
|
if not versions:
|
||||||
# There are versions to sync, so we can remove the status message.
|
# There are versions to sync, so we can remove the status message.
|
||||||
# However, if there aren't any, the status message shows why, and
|
# However, if there aren't any, the status message shows why, and
|
||||||
# shouldn't be erased.
|
# shouldn't be erased.
|
||||||
self.bss_report({'INFO'}, '')
|
return
|
||||||
|
|
||||||
|
# Prevent warnings that the current value of the EnumProperty isn't valid.
|
||||||
|
current_version = '%d.%d' % bpy.app.version[:2]
|
||||||
|
if current_version in versions:
|
||||||
|
bss.version = current_version
|
||||||
|
else:
|
||||||
|
bss.version = versions[0]
|
||||||
|
|
||||||
|
self.bss_report({'INFO'}, '')
|
||||||
|
|
||||||
async def download_settings_file(self, fname: str, temp_dir: str):
|
async def download_settings_file(self, fname: str, temp_dir: str):
|
||||||
config_dir = pathlib.Path(bpy.utils.user_resource('CONFIG'))
|
config_dir = pathlib.Path(bpy.utils.user_resource('CONFIG'))
|
||||||
|
@@ -105,3 +105,8 @@ def bind_texture(texture: bpy.types.Image):
|
|||||||
"""Bind a Blender image to a GL texture slot."""
|
"""Bind a Blender image to a GL texture slot."""
|
||||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode)
|
bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode)
|
||||||
|
|
||||||
|
|
||||||
|
def load_texture(texture: bpy.types.Image) -> int:
|
||||||
|
"""Load the texture, return OpenGL error code."""
|
||||||
|
return texture.gl_load()
|
||||||
|
@@ -88,3 +88,8 @@ def aabox_with_texture(v1: Float2, v2: Float2):
|
|||||||
def bind_texture(texture: bpy.types.Image):
|
def bind_texture(texture: bpy.types.Image):
|
||||||
"""Bind a Blender image to a GL texture slot."""
|
"""Bind a Blender image to a GL texture slot."""
|
||||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode[0])
|
bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode[0])
|
||||||
|
|
||||||
|
|
||||||
|
def load_texture(texture: bpy.types.Image) -> int:
|
||||||
|
"""Load the texture, return OpenGL error code."""
|
||||||
|
return texture.gl_load(filter=bgl.GL_NEAREST, mag=bgl.GL_NEAREST)
|
||||||
|
@@ -164,7 +164,7 @@ class MenuItem:
|
|||||||
|
|
||||||
texture = self.icon
|
texture = self.icon
|
||||||
if texture:
|
if texture:
|
||||||
err = texture.gl_load(filter=bgl.GL_NEAREST, mag=bgl.GL_NEAREST)
|
err = draw.load_texture(texture)
|
||||||
assert not err, 'OpenGL error: %i' % err
|
assert not err, 'OpenGL error: %i' % err
|
||||||
|
|
||||||
# ------ TEXTURE ---------#
|
# ------ TEXTURE ---------#
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Primary requirements:
|
# Primary requirements:
|
||||||
-e git+https://github.com/sybrenstuvel/cachecontrol.git@sybren-filecache-delete-crash-fix#egg=CacheControl
|
-e git+https://github.com/sybrenstuvel/cachecontrol.git@sybren-filecache-delete-crash-fix#egg=CacheControl
|
||||||
lockfile==0.12.2
|
lockfile==0.12.2
|
||||||
pillarsdk==1.7.0
|
pillarsdk==1.8.0
|
||||||
wheel==0.29.0
|
wheel==0.29.0
|
||||||
blender-asset-tracer==1.1
|
blender-asset-tracer==1.1.1
|
||||||
|
|
||||||
# Secondary requirements:
|
# Secondary requirements:
|
||||||
asn1crypto==0.24.0
|
asn1crypto==0.24.0
|
||||||
|
2
setup.py
2
setup.py
@@ -236,7 +236,7 @@ setup(
|
|||||||
'wheels': BuildWheels},
|
'wheels': BuildWheels},
|
||||||
name='blender_cloud',
|
name='blender_cloud',
|
||||||
description='The Blender Cloud addon allows browsing the Blender Cloud from Blender.',
|
description='The Blender Cloud addon allows browsing the Blender Cloud from Blender.',
|
||||||
version='1.12.0',
|
version='1.13.3',
|
||||||
author='Sybren A. Stüvel',
|
author='Sybren A. Stüvel',
|
||||||
author_email='sybren@stuvel.eu',
|
author_email='sybren@stuvel.eu',
|
||||||
packages=find_packages('.'),
|
packages=find_packages('.'),
|
||||||
|
Reference in New Issue
Block a user