Compare commits
12 Commits
version-1.
...
version-1.
Author | SHA1 | Date | |
---|---|---|---|
405b823c81 | |||
9e952035d3 | |||
d77acfb9c8 | |||
70de9741df | |||
cc37e73bc6 | |||
e32e75e3db | |||
6fa5ab5481 | |||
379580de86 | |||
db30b3df76 | |||
5de99baaef | |||
2184b39d27 | |||
23b1f7de7d |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,5 +1,29 @@
|
||||
# Blender Cloud changelog
|
||||
|
||||
## Version 1.17 (2021-02-04)
|
||||
|
||||
- Upgrade BAT to version 1.3.1, which brings compatibility with Geometry Nodes and
|
||||
fixes some issues on Windows.
|
||||
|
||||
|
||||
## Version 1.16 (2020-03-03)
|
||||
|
||||
- Fixed Windows compatibility issue with the handling of Shaman URLs.
|
||||
|
||||
|
||||
## Version 1.15 (2019-12-12)
|
||||
|
||||
- Avoid creating BAT pack when the to-be-rendered file is already inside the job storage
|
||||
directory. This assumes that the paths are already correct for the Flamenco Workers.
|
||||
|
||||
|
||||
## Version 1.14 (2019-10-10)
|
||||
|
||||
- Upgraded BAT to 1.2 for missing smoke caches, compatibility with Blender 2.81, and some
|
||||
Windows-specific fixes.
|
||||
- Removed warnings on the terminal when running Blender 2.80+
|
||||
|
||||
|
||||
## Version 1.13 (2019-04-18)
|
||||
|
||||
- Upgraded BAT to 1.1.1 for a compatibility fix with Blender 2.79
|
||||
|
@@ -21,7 +21,7 @@
|
||||
bl_info = {
|
||||
'name': 'Blender Cloud',
|
||||
"author": "Sybren A. Stüvel, Francesco Siddi, Inês Almeida, Antony Riakiotakis",
|
||||
'version': (1, 13, 5),
|
||||
'version': (1, 17),
|
||||
'blender': (2, 80, 0),
|
||||
'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 '
|
||||
|
@@ -47,6 +47,7 @@ if "bpy" in locals():
|
||||
pillar = importlib.reload(pillar)
|
||||
async_loop = importlib.reload(async_loop)
|
||||
blender = importlib.reload(blender)
|
||||
compatibility = importlib.reload(compatibility)
|
||||
else:
|
||||
import bpy
|
||||
|
||||
@@ -54,7 +55,7 @@ else:
|
||||
from . import draw_27 as draw
|
||||
else:
|
||||
from . import draw
|
||||
from .. import pillar, async_loop, blender
|
||||
from .. import pillar, async_loop, blender, compatibility
|
||||
|
||||
import bpy
|
||||
import pillarsdk
|
||||
@@ -252,7 +253,7 @@ class ATTRACT_PT_tools(AttractPollMixin, Panel):
|
||||
icon='RENDER_STILL')
|
||||
|
||||
# Group more dangerous operations.
|
||||
dangerous_sub = layout.split(**blender.factor(0.6), align=True)
|
||||
dangerous_sub = layout.split(**compatibility.factor(0.6), align=True)
|
||||
dangerous_sub.operator('attract.strip_unlink',
|
||||
text='Unlink %s' % noun,
|
||||
icon='PANEL_CLOSE')
|
||||
@@ -408,6 +409,7 @@ class ATTRACT_OT_shot_fetch_update(AttractOperatorMixin, Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class ATTRACT_OT_shot_relink(AttractOperatorMixin, Operator):
|
||||
bl_idname = "attract.shot_relink"
|
||||
bl_label = "Relink With Attract"
|
||||
@@ -477,6 +479,7 @@ class ATTRACT_OT_shot_open_in_browser(AttractOperatorMixin, Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class ATTRACT_OT_shot_delete(AttractOperatorMixin, Operator):
|
||||
bl_idname = 'attract.shot_delete'
|
||||
bl_label = 'Delete Shot'
|
||||
@@ -915,6 +918,7 @@ class ATTRACT_OT_copy_id_to_clipboard(AttractOperatorMixin, Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class ATTRACT_OT_project_open_in_browser(Operator):
|
||||
bl_idname = 'attract.project_open_in_browser'
|
||||
bl_label = 'Open Project in Browser'
|
||||
@@ -1003,7 +1007,6 @@ def deactivate():
|
||||
|
||||
_rna_classes = [cls for cls in locals().values()
|
||||
if isinstance(cls, type) and cls.__name__.startswith('ATTRACT')]
|
||||
log.info('RNA classes:\n%s', '\n'.join([repr(cls) for cls in _rna_classes]))
|
||||
|
||||
|
||||
def register():
|
||||
|
@@ -30,7 +30,7 @@ from bpy.types import AddonPreferences, Operator, WindowManager, Scene, Property
|
||||
from bpy.props import StringProperty, EnumProperty, PointerProperty, BoolProperty, IntProperty
|
||||
import rna_prop_ui
|
||||
|
||||
from . import pillar, async_loop, flamenco, project_specific
|
||||
from . import compatibility, pillar, async_loop, flamenco, project_specific
|
||||
from .utils import pyside_cache, redraw
|
||||
|
||||
PILLAR_WEB_SERVER_URL = os.environ.get('BCLOUD_SERVER', 'https://cloud.blender.org/')
|
||||
@@ -40,23 +40,6 @@ ADDON_NAME = 'blender_cloud'
|
||||
log = logging.getLogger(__name__)
|
||||
icons = None
|
||||
|
||||
if bpy.app.version < (2, 80):
|
||||
SYNC_SELECT_VERSION_ICON = 'DOTSDOWN'
|
||||
else:
|
||||
SYNC_SELECT_VERSION_ICON = 'DOWNARROW_HLT'
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
def factor(factor: float) -> dict:
|
||||
"""Construct keyword argument for UILayout.split().
|
||||
|
||||
On Blender 2.8 this returns {'factor': factor}, and on earlier Blenders it returns
|
||||
{'percentage': factor}.
|
||||
"""
|
||||
if bpy.app.version < (2, 80, 0):
|
||||
return {'percentage': factor}
|
||||
return {'factor': factor}
|
||||
|
||||
|
||||
@pyside_cache('version')
|
||||
def blender_syncable_versions(self, context):
|
||||
@@ -69,6 +52,7 @@ def blender_syncable_versions(self, context):
|
||||
return [(v, v, '') for v in versions]
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class SyncStatusProperties(PropertyGroup):
|
||||
status = EnumProperty(
|
||||
items=[
|
||||
@@ -156,6 +140,7 @@ def project_extensions(project_id) -> set:
|
||||
return set(proj.get('enabled_for', ()))
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class BlenderCloudProjectGroup(PropertyGroup):
|
||||
status = EnumProperty(
|
||||
items=[
|
||||
@@ -185,6 +170,7 @@ class BlenderCloudProjectGroup(PropertyGroup):
|
||||
project_specific.handle_project_update()
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class BlenderCloudPreferences(AddonPreferences):
|
||||
bl_idname = ADDON_NAME
|
||||
|
||||
@@ -257,7 +243,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
name='Relative Paths Only',
|
||||
description='When enabled, only assets that are referred to with a relative path are '
|
||||
'packed, and assets referred to by an absolute path are excluded from the '
|
||||
'BAT pack. When disabled, all assets are packed.',
|
||||
'BAT pack. When disabled, all assets are packed',
|
||||
default=False,
|
||||
update=project_specific.store,
|
||||
)
|
||||
@@ -331,7 +317,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
bss = context.window_manager.blender_sync_status
|
||||
bsync_box = layout.box()
|
||||
bsync_box.enabled = msg_icon != 'ERROR'
|
||||
row = bsync_box.row().split(**factor(0.33))
|
||||
row = bsync_box.row().split(**compatibility.factor(0.33))
|
||||
row.label(text='Blender Sync with Blender Cloud', icon_value=icon('CLOUD'))
|
||||
|
||||
icon_for_level = {
|
||||
@@ -374,7 +360,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
layout.enabled = bss.status in {'NONE', 'IDLE'}
|
||||
|
||||
buttons = layout.column()
|
||||
row_buttons = buttons.row().split(**factor(0.5))
|
||||
row_buttons = buttons.row().split(**compatibility.factor(0.5))
|
||||
row_push = row_buttons.row()
|
||||
row_pull = row_buttons.row(align=True)
|
||||
|
||||
@@ -396,7 +382,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
props.blender_version = bss.version
|
||||
row_pull.operator('pillar.sync',
|
||||
text='',
|
||||
icon=SYNC_SELECT_VERSION_ICON).action = 'SELECT'
|
||||
icon=compatibility.SYNC_SELECT_VERSION_ICON).action = 'SELECT'
|
||||
else:
|
||||
row_pull.label(text='Cloud Sync is running.')
|
||||
|
||||
@@ -444,7 +430,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
header_row = flamenco_box.row(align=True)
|
||||
header_row.label(text='Flamenco:', icon_value=icon('CLOUD'))
|
||||
|
||||
manager_split = flamenco_box.split(**factor(0.32), align=True)
|
||||
manager_split = flamenco_box.split(**compatibility.factor(0.32), align=True)
|
||||
manager_split.label(text='Manager:')
|
||||
manager_box = manager_split.row(align=True)
|
||||
|
||||
@@ -461,7 +447,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
else:
|
||||
manager_box.label(text='Fetching available managers.')
|
||||
|
||||
path_split = flamenco_box.split(**factor(0.32), align=True)
|
||||
path_split = flamenco_box.split(**compatibility.factor(0.32), align=True)
|
||||
path_split.label(text='Job File Path:')
|
||||
path_box = path_split.row(align=True)
|
||||
path_box.prop(self, 'flamenco_job_file_path', text='')
|
||||
@@ -469,7 +455,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
props.path = self.flamenco_job_file_path
|
||||
|
||||
job_output_box = flamenco_box.column(align=True)
|
||||
path_split = job_output_box.split(**factor(0.32), align=True)
|
||||
path_split = job_output_box.split(**compatibility.factor(0.32), align=True)
|
||||
path_split.label(text='Job Output Path:')
|
||||
path_box = path_split.row(align=True)
|
||||
path_box.prop(self, 'flamenco_job_output_path', text='')
|
||||
@@ -477,7 +463,7 @@ class BlenderCloudPreferences(AddonPreferences):
|
||||
props.path = self.flamenco_job_output_path
|
||||
job_output_box.prop(self, 'flamenco_exclude_filter')
|
||||
|
||||
prop_split = job_output_box.split(**factor(0.32), align=True)
|
||||
prop_split = job_output_box.split(**compatibility.factor(0.32), align=True)
|
||||
prop_split.label(text='Strip Components:')
|
||||
prop_split.prop(self, 'flamenco_job_output_strip_components', text='')
|
||||
|
||||
@@ -561,6 +547,7 @@ class PILLAR_OT_subscribe(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class PILLAR_OT_project_open_in_browser(Operator):
|
||||
bl_idname = 'pillar.project_open_in_browser'
|
||||
bl_label = 'Open in Browser'
|
||||
|
70
blender_cloud/compatibility.py
Normal file
70
blender_cloud/compatibility.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""Compatibility functions to support Blender 2.79 and 2.80+ in one code base."""
|
||||
import functools
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
if bpy.app.version < (2, 80):
|
||||
SYNC_SELECT_VERSION_ICON = 'DOTSDOWN'
|
||||
else:
|
||||
SYNC_SELECT_VERSION_ICON = 'DOWNARROW_HLT'
|
||||
|
||||
|
||||
# Get references to all property definition functions in bpy.props,
|
||||
# so that they can be used to replace 'x = IntProperty()' to 'x: IntProperty()'
|
||||
# dynamically when working on Blender 2.80+
|
||||
__all_prop_funcs = {
|
||||
getattr(bpy.props, propname)
|
||||
for propname in dir(bpy.props)
|
||||
if propname.endswith('Property')
|
||||
}
|
||||
|
||||
def convert_properties(class_):
|
||||
"""Class decorator to avoid warnings in Blender 2.80+
|
||||
|
||||
This decorator replaces property definitions like this:
|
||||
|
||||
someprop = bpy.props.IntProperty()
|
||||
|
||||
to annotations, as introduced in Blender 2.80:
|
||||
|
||||
someprop: bpy.props.IntProperty()
|
||||
|
||||
No-op if running on Blender 2.79 or older.
|
||||
"""
|
||||
|
||||
if bpy.app.version < (2, 80):
|
||||
return class_
|
||||
|
||||
if not hasattr(class_, '__annotations__'):
|
||||
class_.__annotations__ = {}
|
||||
|
||||
attrs_to_delete = []
|
||||
for name, value in class_.__dict__.items():
|
||||
if not isinstance(value, tuple) or len(value) != 2:
|
||||
continue
|
||||
|
||||
prop_func, kwargs = value
|
||||
if prop_func not in __all_prop_funcs:
|
||||
continue
|
||||
|
||||
# This is a property definition, replace it with annotation.
|
||||
attrs_to_delete.append(name)
|
||||
class_.__annotations__[name] = value
|
||||
|
||||
for attr_name in attrs_to_delete:
|
||||
delattr(class_, attr_name)
|
||||
|
||||
return class_
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
def factor(factor: float) -> dict:
|
||||
"""Construct keyword argument for UILayout.split().
|
||||
|
||||
On Blender 2.8 this returns {'factor': factor}, and on earlier Blenders it returns
|
||||
{'percentage': factor}.
|
||||
"""
|
||||
if bpy.app.version < (2, 80, 0):
|
||||
return {'percentage': factor}
|
||||
return {'factor': factor}
|
@@ -34,12 +34,13 @@ if "bpy" in locals():
|
||||
bat_interface = importlib.reload(bat_interface)
|
||||
sdk = importlib.reload(sdk)
|
||||
blender = importlib.reload(blender)
|
||||
compatibility = importlib.reload(compatibility)
|
||||
except NameError:
|
||||
from . import bat_interface, sdk
|
||||
from .. import blender
|
||||
from .. import blender, compatibility
|
||||
else:
|
||||
from . import bat_interface, sdk
|
||||
from .. import blender
|
||||
from .. import blender, compatibility
|
||||
|
||||
import bpy
|
||||
from bpy.types import AddonPreferences, Operator, WindowManager, Scene, PropertyGroup
|
||||
@@ -138,6 +139,7 @@ def silently_quit_blender():
|
||||
bpy.ops.wm.quit_blender()
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class FlamencoManagerGroup(PropertyGroup):
|
||||
manager = EnumProperty(
|
||||
items=available_managers,
|
||||
@@ -238,6 +240,41 @@ def guess_output_file_extension(output_format: str, scene) -> str:
|
||||
return '.' + container.lower()
|
||||
|
||||
|
||||
def is_shaman_url(path_or_url: str) -> bool:
|
||||
"""Check whether the given string is a Shaman URL.
|
||||
|
||||
:param path_or_url: A string that may represent a filesystem path or a URL.
|
||||
May not be a pathlib.Path, as that would break URL notation on Windows.
|
||||
"""
|
||||
assert isinstance(path_or_url, str)
|
||||
return any(path_or_url.startswith(scheme) for scheme in SHAMAN_URL_SCHEMES)
|
||||
|
||||
|
||||
def is_file_inside_job_storage(prefs, current_file: typing.Union[str, Path]) -> bool:
|
||||
"""Check whether current blend file is inside the storage path.
|
||||
|
||||
:return: True when 'current_file' is inside the Flamenco
|
||||
job storage directory already. In this case it won't be
|
||||
BAT-packed, as it's assumed the job storage dir is
|
||||
accessible by the workers already.
|
||||
"""
|
||||
|
||||
if isinstance(current_file, str):
|
||||
# Shaman URLs are always remote, so the current file cannot be in there.
|
||||
if is_shaman_url(current_file):
|
||||
return False
|
||||
current_file = Path(current_file)
|
||||
|
||||
flamenco_job_file_path = Path(prefs.flamenco_job_file_path).absolute().resolve()
|
||||
current_file = current_file.absolute().resolve()
|
||||
try:
|
||||
current_file.relative_to(flamenco_job_file_path)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
||||
pillar.AuthenticatedPillarOperatorMixin,
|
||||
FlamencoPollMixin,
|
||||
@@ -565,7 +602,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
||||
|
||||
self.log.debug('projdir: %s', projdir)
|
||||
|
||||
if any(prefs.flamenco_job_file_path.startswith(scheme) for scheme in SHAMAN_URL_SCHEMES):
|
||||
if is_shaman_url(prefs.flamenco_job_file_path):
|
||||
endpoint, _ = bat_interface.parse_shaman_endpoint(prefs.flamenco_job_file_path)
|
||||
self.log.info('Sending BAT pack to Shaman at %s', endpoint)
|
||||
try:
|
||||
@@ -593,6 +630,11 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
||||
outfile = PurePath('{shaman}') / outfile
|
||||
return None, outfile, missing_sources
|
||||
|
||||
if is_file_inside_job_storage(prefs, filepath):
|
||||
# The blend file is contained in the job storage path, no need to copy anything.
|
||||
# Since BAT doesn't run, we also don't know whether files are missing.
|
||||
return filepath.parent, filepath, []
|
||||
|
||||
# Create a unique directory that is still more or less identifyable.
|
||||
# This should work better than a random ID.
|
||||
unique_dir = '%s-%s-%s' % (datetime.now().isoformat('-').replace(':', ''),
|
||||
@@ -729,6 +771,7 @@ class FLAMENCO_OT_abort(Operator, FlamencoPollMixin):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class FLAMENCO_OT_explore_file_path(FlamencoPollMixin,
|
||||
Operator):
|
||||
"""Opens the Flamenco job storage path in a file explorer.
|
||||
@@ -796,6 +839,7 @@ class FLAMENCO_OT_disable_output_path_override(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class FLAMENCO_OT_set_recommended_sample_cap(Operator):
|
||||
bl_idname = 'flamenco.set_recommended_sample_cap'
|
||||
bl_label = 'Set Recommended Maximum Sample Count'
|
||||
@@ -962,7 +1006,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
|
||||
prefs = preferences()
|
||||
|
||||
labeled_row = layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Manager:')
|
||||
prop_btn_row = labeled_row.row(align=True)
|
||||
|
||||
@@ -980,7 +1024,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
else:
|
||||
prop_btn_row.label(text='Fetching available managers.')
|
||||
|
||||
labeled_row = layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Job Type:')
|
||||
labeled_row.prop(context.scene, 'flamenco_render_job_type', text='')
|
||||
|
||||
@@ -1005,7 +1049,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
sample_count = scene_sample_count(context.scene)
|
||||
recommended_cap = sample_count // 4
|
||||
|
||||
split = box.split(**blender.factor(0.4))
|
||||
split = box.split(**compatibility.factor(0.4))
|
||||
split.label(text='Total Sample Count: %d' % sample_count)
|
||||
props = split.operator('flamenco.set_recommended_sample_cap',
|
||||
text='Recommended Max Samples per Task: %d' % recommended_cap)
|
||||
@@ -1019,7 +1063,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
else:
|
||||
box.prop(context.scene, 'flamenco_render_fchunk_size')
|
||||
|
||||
labeled_row = layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Frame Range:')
|
||||
prop_btn_row = labeled_row.row(align=True)
|
||||
prop_btn_row.prop(context.scene, 'flamenco_render_frame_range', text='')
|
||||
@@ -1030,7 +1074,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
|
||||
paths_layout = layout.column(align=True)
|
||||
|
||||
labeled_row = paths_layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = paths_layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Storage:')
|
||||
prop_btn_row = labeled_row.row(align=True)
|
||||
prop_btn_row.label(text=prefs.flamenco_job_file_path)
|
||||
@@ -1038,12 +1082,18 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
text='', icon='DISK_DRIVE')
|
||||
props.path = prefs.flamenco_job_file_path
|
||||
|
||||
|
||||
if is_file_inside_job_storage(prefs, context.blend_data.filepath):
|
||||
# File is contained in the job storage path, no need to copy anything.
|
||||
paths_layout.label(text='Current file already in job storage path; '
|
||||
'not going to create BAT pack.')
|
||||
|
||||
render_output = render_output_path(context)
|
||||
if render_output is None:
|
||||
paths_layout.label(text='Unable to render with Flamenco, outside of project directory.')
|
||||
return
|
||||
|
||||
labeled_row = paths_layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = paths_layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Output:')
|
||||
prop_btn_row = labeled_row.row(align=True)
|
||||
|
||||
@@ -1062,7 +1112,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
props.path = str(render_output.parent)
|
||||
|
||||
if context.scene.flamenco_do_override_output_path:
|
||||
labeled_row = paths_layout.split(**blender.factor(0.25), align=True)
|
||||
labeled_row = paths_layout.split(**compatibility.factor(0.25), align=True)
|
||||
labeled_row.label(text='Effective Output Path:')
|
||||
labeled_row.label(text=str(render_output))
|
||||
|
||||
@@ -1072,7 +1122,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
||||
flamenco_status = context.window_manager.flamenco_status
|
||||
if flamenco_status in {'IDLE', 'ABORTED', 'DONE'}:
|
||||
if prefs.flamenco_show_quit_after_submit_button:
|
||||
ui = layout.split(**blender.factor(0.75), align=True)
|
||||
ui = layout.split(**compatibility.factor(0.75), align=True)
|
||||
else:
|
||||
ui = layout
|
||||
ui.operator(FLAMENCO_OT_render.bl_idname,
|
||||
|
@@ -25,7 +25,7 @@ import bpy
|
||||
import pillarsdk
|
||||
from pillarsdk import exceptions as sdk_exceptions
|
||||
from .pillar import pillar_call
|
||||
from . import async_loop, pillar, home_project, blender
|
||||
from . import async_loop, compatibility, pillar, home_project, blender
|
||||
|
||||
REQUIRES_ROLES_FOR_IMAGE_SHARING = {'subscriber', 'demo'}
|
||||
IMAGE_SHARING_GROUP_NODE_NAME = 'Image sharing'
|
||||
@@ -53,6 +53,7 @@ async def find_image_sharing_group_id(home_project_id, user_id):
|
||||
return share_group['_id']
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class PILLAR_OT_image_share(pillar.PillarOperatorMixin,
|
||||
async_loop.AsyncModalOperatorMixin,
|
||||
bpy.types.Operator):
|
||||
|
@@ -70,8 +70,8 @@ def handle_project_update(_=None, _2=None):
|
||||
with mark_as_loading():
|
||||
prefs = preferences()
|
||||
project_id = prefs.project.project
|
||||
log.info('Updating internal state to reflect extensions enabled on current project %s.',
|
||||
project_id)
|
||||
log.debug('Updating internal state to reflect extensions enabled on current project %s.',
|
||||
project_id)
|
||||
|
||||
project_extensions.cache_clear()
|
||||
|
||||
|
@@ -35,7 +35,7 @@ import asyncio
|
||||
import pillarsdk
|
||||
from pillarsdk import exceptions as sdk_exceptions
|
||||
from .pillar import pillar_call
|
||||
from . import async_loop, blender, pillar, cache, blendfile, home_project
|
||||
from . import async_loop, blender, compatibility, pillar, cache, blendfile, home_project
|
||||
|
||||
SETTINGS_FILES_TO_UPLOAD = ['userpref.blend', 'startup.blend']
|
||||
|
||||
@@ -196,6 +196,7 @@ async def available_blender_versions(home_project_id: str, user_id: str) -> list
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
@compatibility.convert_properties
|
||||
class PILLAR_OT_sync(pillar.PillarOperatorMixin,
|
||||
async_loop.AsyncModalOperatorMixin,
|
||||
bpy.types.Operator):
|
||||
|
@@ -26,7 +26,7 @@ import bpy
|
||||
import bgl
|
||||
|
||||
import pillarsdk
|
||||
from .. import async_loop, pillar, cache, blender, utils
|
||||
from .. import async_loop, compatibility, pillar, cache, blender, utils
|
||||
from . import menu_item as menu_item_mod # so that we can have menu items called 'menu_item'
|
||||
from . import nodes
|
||||
|
||||
@@ -648,6 +648,7 @@ class BlenderCloudBrowser(pillar.PillarOperatorMixin,
|
||||
self.scroll_offset_target = self.scroll_offset = 0
|
||||
|
||||
|
||||
@compatibility.convert_properties
|
||||
class PILLAR_OT_switch_hdri(pillar.PillarOperatorMixin,
|
||||
async_loop.AsyncModalOperatorMixin,
|
||||
bpy.types.Operator):
|
||||
@@ -776,7 +777,7 @@ def _hdri_download_panel(self, current_image):
|
||||
current_image.name)
|
||||
return
|
||||
|
||||
row = self.layout.row(align=True).split(**blender.factor(0.3))
|
||||
row = self.layout.row(align=True).split(**compatibility.factor(0.3))
|
||||
row.label(text='HDRi', icon_value=blender.icon('CLOUD'))
|
||||
row.prop(current_image, 'hdri_variation', text='')
|
||||
|
||||
|
@@ -94,7 +94,10 @@ def pyside_cache(propname):
|
||||
result = wrapped(self, context)
|
||||
return result
|
||||
finally:
|
||||
rna_type, rna_info = getattr(self.bl_rna, propname)
|
||||
try:
|
||||
rna_type, rna_info = self.bl_rna.__annotations__[propname]
|
||||
except AttributeError:
|
||||
rna_type, rna_info = getattr(self.bl_rna, propname)
|
||||
rna_info['_cached_result'] = result
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@@ -3,7 +3,7 @@
|
||||
lockfile==0.12.2
|
||||
pillarsdk==1.8.0
|
||||
wheel==0.29.0
|
||||
blender-asset-tracer==1.1.1
|
||||
blender-asset-tracer==1.3.1
|
||||
|
||||
# Secondary requirements:
|
||||
asn1crypto==0.24.0
|
||||
|
2
setup.py
2
setup.py
@@ -236,7 +236,7 @@ setup(
|
||||
'wheels': BuildWheels},
|
||||
name='blender_cloud',
|
||||
description='The Blender Cloud addon allows browsing the Blender Cloud from Blender.',
|
||||
version='1.13.5',
|
||||
version='1.17',
|
||||
author='Sybren A. Stüvel',
|
||||
author_email='sybren@stuvel.eu',
|
||||
packages=find_packages('.'),
|
||||
|
Reference in New Issue
Block a user