Compare commits

..

18 Commits

Author SHA1 Message Date
e32e75e3db Bumped version to 1.15 and marked as released in CHANGELOG 2019-12-12 10:42:08 +01:00
6fa5ab5481 Removed trailing period from property description
No functional changes.
2019-12-12 10:40:58 +01:00
379580de86 Don't create BAT pack when rendering file in job storage directory
When the to-be-rendered blend file is contained in the job storage
directory, it is now assumed that all files are already reachable by the
Flamenco Workers. This supports environments working directly on shared
storage.

This assumes that the paths are already correct for the Flamenco
Workers. No detection of missing files is done (as BAT doesn't run).
2019-10-25 13:34:34 +02:00
db30b3df76 Bumped version to 1.14 2019-10-10 10:39:37 +02:00
5de99baaef Updated changelog 2019-10-10 10:39:28 +02:00
2184b39d27 Bump Blender Asset Tracer (BAT) version from 1.1.1 → 1.2.1 2019-10-10 10:29:53 +02:00
23b1f7de7d Convert property definitions from assignment to annotations on Blender 2.80+
The properties are still declared in the Python 3.5 compatible assignment
notation, and a class decorator that converts those to class annotations
as preferred by Blender 2.80.
2019-10-10 10:29:36 +02:00
28f68c6fbf update_version.sh: Use Python 3 in example command
This makes it possible to run the command outside of a Python 3 virtualenv.
2019-06-21 14:31:54 +02:00
b00cb233cc Bumped version to 1.13.5 2019-06-21 14:30:03 +02:00
2142e9e7fc Attract fix for Blender 2.80 panel change
Commit 1e7c3a159fd2ca42fd5688be067008ef0d2c03df removed the 'Info' panel
(which is good), so we have to attach the metadata subpanel somewhere else.
2019-06-21 14:29:49 +02:00
1dea802932 Attract doesn't have to be active to use ATTRACT_OT_open_meta_blendfile
It is pretty much independent of Attract.
2019-06-21 14:29:07 +02:00
077bd1abdb Prevent KeyError when Flamenco Manager settings are unknown 2019-06-12 11:47:16 +02:00
5a2c528681 Run Pip via {sys.executable} -m pip
This solves the same problem as c457767edf,
but in a way that's actually [recommended](https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program).
2019-06-04 12:40:02 +02:00
53b12376d1 Revert "Use Python module to run Pip"
This reverts commit c457767edf. Modern pip
can no longer be used this way ('pip.main' does not exist).
2019-06-04 12:35:46 +02:00
8495868ea6 Bumped version to 1.13.4 2019-06-04 12:29:50 +02:00
cf810de41b Another Blender 2.8 compatibility fix 2019-06-04 12:29:37 +02:00
c457767edf Use Python module to run Pip
setup.py used systemcalls for package management pip. This call is
platform dependent as on ubuntu distros this needs to be pip3. On these
platforms pip points to the python2 version.

By direct calling the pip module from within the running python process
we know for sure we are triggering the correct one.

Differential revision: https://developer.blender.org/D4952/

Reviewed by: sybren
2019-05-29 10:29:14 +02:00
985b3f6a7d Attract: draw strip metadata as its own panel
The panel is a subpanel in Blender 2.80, and a top-level panel in 2.79.
2019-05-24 14:12:36 +02:00
13 changed files with 189 additions and 76 deletions

View File

@@ -1,11 +1,25 @@
# Blender Cloud changelog # Blender Cloud changelog
## 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) ## Version 1.13 (2019-04-18)
- Upgraded BAT to 1.1.1 for a compatibility fix with Blender 2.79 - 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. - 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 When using Blender Cloud Add-on 1.12 or older, Flamenco Server will automatically convert the
Manager settings to version 1. Manager settings to version 1.
- More Blender 2.80 compatibility fixes
## Version 1.12 (2019-03-25) ## Version 1.12 (2019-03-25)

View File

@@ -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, 13, 3), 'version': (1, 15),
'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 '

View File

@@ -47,6 +47,7 @@ if "bpy" in locals():
pillar = importlib.reload(pillar) pillar = importlib.reload(pillar)
async_loop = importlib.reload(async_loop) async_loop = importlib.reload(async_loop)
blender = importlib.reload(blender) blender = importlib.reload(blender)
compatibility = importlib.reload(compatibility)
else: else:
import bpy import bpy
@@ -54,7 +55,7 @@ else:
from . import draw_27 as draw from . import draw_27 as draw
else: else:
from . import draw from . import draw
from .. import pillar, async_loop, blender from .. import pillar, async_loop, blender, compatibility
import bpy import bpy
import pillarsdk import pillarsdk
@@ -63,6 +64,7 @@ from pillarsdk.projects import Project
from pillarsdk import exceptions as sdk_exceptions from pillarsdk import exceptions as sdk_exceptions
from bpy.types import Operator, Panel, AddonPreferences from bpy.types import Operator, Panel, AddonPreferences
import bl_ui.space_sequencer
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -251,7 +253,7 @@ class ATTRACT_PT_tools(AttractPollMixin, Panel):
icon='RENDER_STILL') icon='RENDER_STILL')
# Group more dangerous operations. # 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', dangerous_sub.operator('attract.strip_unlink',
text='Unlink %s' % noun, text='Unlink %s' % noun,
icon='PANEL_CLOSE') icon='PANEL_CLOSE')
@@ -407,6 +409,7 @@ class ATTRACT_OT_shot_fetch_update(AttractOperatorMixin, Operator):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class ATTRACT_OT_shot_relink(AttractOperatorMixin, Operator): class ATTRACT_OT_shot_relink(AttractOperatorMixin, Operator):
bl_idname = "attract.shot_relink" bl_idname = "attract.shot_relink"
bl_label = "Relink With Attract" bl_label = "Relink With Attract"
@@ -476,6 +479,7 @@ class ATTRACT_OT_shot_open_in_browser(AttractOperatorMixin, Operator):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class ATTRACT_OT_shot_delete(AttractOperatorMixin, Operator): class ATTRACT_OT_shot_delete(AttractOperatorMixin, Operator):
bl_idname = 'attract.shot_delete' bl_idname = 'attract.shot_delete'
bl_label = 'Delete Shot' bl_label = 'Delete Shot'
@@ -639,8 +643,7 @@ class ATTRACT_OT_open_meta_blendfile(AttractOperatorMixin, Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return AttractOperatorMixin.poll(context) and \ return bool(any(cls.filename_from_metadata(s) for s in context.selected_sequences))
bool(any(cls.filename_from_metadata(s) for s in context.selected_sequences))
@staticmethod @staticmethod
def filename_from_metadata(strip): def filename_from_metadata(strip):
@@ -915,6 +918,7 @@ class ATTRACT_OT_copy_id_to_clipboard(AttractOperatorMixin, Operator):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class ATTRACT_OT_project_open_in_browser(Operator): class ATTRACT_OT_project_open_in_browser(Operator):
bl_idname = 'attract.project_open_in_browser' bl_idname = 'attract.project_open_in_browser'
bl_label = 'Open Project in Browser' bl_label = 'Open Project in Browser'
@@ -946,7 +950,13 @@ class ATTRACT_OT_project_open_in_browser(Operator):
return {'FINISHED'} return {'FINISHED'}
def draw_strip_movie_meta(self, context): class ATTRACT_PT_strip_metadata(bl_ui.space_sequencer.SequencerButtonsPanel, Panel):
bl_label = "Metadata"
bl_parent_id = "SEQUENCER_PT_source"
bl_category = "Strip"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
strip = active_strip(context) strip = active_strip(context)
if not strip: if not strip:
return return
@@ -1023,13 +1033,6 @@ 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")
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)

View File

@@ -30,7 +30,7 @@ from bpy.types import AddonPreferences, Operator, WindowManager, Scene, Property
from bpy.props import StringProperty, EnumProperty, PointerProperty, BoolProperty, IntProperty from bpy.props import StringProperty, EnumProperty, PointerProperty, BoolProperty, IntProperty
import rna_prop_ui 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 from .utils import pyside_cache, redraw
PILLAR_WEB_SERVER_URL = os.environ.get('BCLOUD_SERVER', 'https://cloud.blender.org/') 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__) log = logging.getLogger(__name__)
icons = None 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') @pyside_cache('version')
def blender_syncable_versions(self, context): def blender_syncable_versions(self, context):
@@ -69,6 +52,7 @@ def blender_syncable_versions(self, context):
return [(v, v, '') for v in versions] return [(v, v, '') for v in versions]
@compatibility.convert_properties
class SyncStatusProperties(PropertyGroup): class SyncStatusProperties(PropertyGroup):
status = EnumProperty( status = EnumProperty(
items=[ items=[
@@ -156,6 +140,7 @@ def project_extensions(project_id) -> set:
return set(proj.get('enabled_for', ())) return set(proj.get('enabled_for', ()))
@compatibility.convert_properties
class BlenderCloudProjectGroup(PropertyGroup): class BlenderCloudProjectGroup(PropertyGroup):
status = EnumProperty( status = EnumProperty(
items=[ items=[
@@ -185,6 +170,7 @@ class BlenderCloudProjectGroup(PropertyGroup):
project_specific.handle_project_update() project_specific.handle_project_update()
@compatibility.convert_properties
class BlenderCloudPreferences(AddonPreferences): class BlenderCloudPreferences(AddonPreferences):
bl_idname = ADDON_NAME bl_idname = ADDON_NAME
@@ -257,7 +243,7 @@ class BlenderCloudPreferences(AddonPreferences):
name='Relative Paths Only', name='Relative Paths Only',
description='When enabled, only assets that are referred to with a relative path are ' 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 ' '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, default=False,
update=project_specific.store, update=project_specific.store,
) )
@@ -331,7 +317,7 @@ class BlenderCloudPreferences(AddonPreferences):
bss = context.window_manager.blender_sync_status bss = context.window_manager.blender_sync_status
bsync_box = layout.box() bsync_box = layout.box()
bsync_box.enabled = msg_icon != 'ERROR' 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')) row.label(text='Blender Sync with Blender Cloud', icon_value=icon('CLOUD'))
icon_for_level = { icon_for_level = {
@@ -374,7 +360,7 @@ class BlenderCloudPreferences(AddonPreferences):
layout.enabled = bss.status in {'NONE', 'IDLE'} layout.enabled = bss.status in {'NONE', 'IDLE'}
buttons = layout.column() 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_push = row_buttons.row()
row_pull = row_buttons.row(align=True) row_pull = row_buttons.row(align=True)
@@ -396,7 +382,7 @@ class BlenderCloudPreferences(AddonPreferences):
props.blender_version = bss.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=compatibility.SYNC_SELECT_VERSION_ICON).action = 'SELECT'
else: else:
row_pull.label(text='Cloud Sync is running.') row_pull.label(text='Cloud Sync is running.')
@@ -444,7 +430,7 @@ class BlenderCloudPreferences(AddonPreferences):
header_row = flamenco_box.row(align=True) header_row = flamenco_box.row(align=True)
header_row.label(text='Flamenco:', icon_value=icon('CLOUD')) 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_split.label(text='Manager:')
manager_box = manager_split.row(align=True) manager_box = manager_split.row(align=True)
@@ -461,7 +447,7 @@ class BlenderCloudPreferences(AddonPreferences):
else: else:
manager_box.label(text='Fetching available managers.') 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_split.label(text='Job File Path:')
path_box = path_split.row(align=True) path_box = path_split.row(align=True)
path_box.prop(self, 'flamenco_job_file_path', text='') path_box.prop(self, 'flamenco_job_file_path', text='')
@@ -469,7 +455,7 @@ class BlenderCloudPreferences(AddonPreferences):
props.path = self.flamenco_job_file_path props.path = self.flamenco_job_file_path
job_output_box = flamenco_box.column(align=True) 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_split.label(text='Job Output Path:')
path_box = path_split.row(align=True) path_box = path_split.row(align=True)
path_box.prop(self, 'flamenco_job_output_path', text='') path_box.prop(self, 'flamenco_job_output_path', text='')
@@ -477,7 +463,7 @@ class BlenderCloudPreferences(AddonPreferences):
props.path = self.flamenco_job_output_path props.path = self.flamenco_job_output_path
job_output_box.prop(self, 'flamenco_exclude_filter') 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.label(text='Strip Components:')
prop_split.prop(self, 'flamenco_job_output_strip_components', text='') prop_split.prop(self, 'flamenco_job_output_strip_components', text='')
@@ -561,6 +547,7 @@ class PILLAR_OT_subscribe(Operator):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class PILLAR_OT_project_open_in_browser(Operator): class PILLAR_OT_project_open_in_browser(Operator):
bl_idname = 'pillar.project_open_in_browser' bl_idname = 'pillar.project_open_in_browser'
bl_label = 'Open in Browser' bl_label = 'Open in Browser'

View 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}

View File

@@ -34,12 +34,13 @@ if "bpy" in locals():
bat_interface = importlib.reload(bat_interface) bat_interface = importlib.reload(bat_interface)
sdk = importlib.reload(sdk) sdk = importlib.reload(sdk)
blender = importlib.reload(blender) blender = importlib.reload(blender)
compatibility = importlib.reload(compatibility)
except NameError: except NameError:
from . import bat_interface, sdk from . import bat_interface, sdk
from .. import blender from .. import blender, compatibility
else: else:
from . import bat_interface, sdk from . import bat_interface, sdk
from .. import blender from .. import blender, compatibility
import bpy import bpy
from bpy.types import AddonPreferences, Operator, WindowManager, Scene, PropertyGroup from bpy.types import AddonPreferences, Operator, WindowManager, Scene, PropertyGroup
@@ -138,6 +139,7 @@ def silently_quit_blender():
bpy.ops.wm.quit_blender() bpy.ops.wm.quit_blender()
@compatibility.convert_properties
class FlamencoManagerGroup(PropertyGroup): class FlamencoManagerGroup(PropertyGroup):
manager = EnumProperty( manager = EnumProperty(
items=available_managers, items=available_managers,
@@ -238,6 +240,24 @@ def guess_output_file_extension(output_format: str, scene) -> str:
return '.' + container.lower() return '.' + container.lower()
def is_file_inside_job_storage(prefs, current_file: 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.
"""
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, class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
pillar.AuthenticatedPillarOperatorMixin, pillar.AuthenticatedPillarOperatorMixin,
FlamencoPollMixin, FlamencoPollMixin,
@@ -435,7 +455,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
# Pop out some settings so that settings of irrelevant Managers are excluded. # Pop out some settings so that settings of irrelevant Managers are excluded.
flamenco_managers_settings = project_settings.pop('flamenco_managers_settings', {}) flamenco_managers_settings = project_settings.pop('flamenco_managers_settings', {})
flamenco_manager_settings = flamenco_managers_settings.pop(manager_id) flamenco_manager_settings = flamenco_managers_settings.pop(manager_id, '-unknown-')
info = { info = {
'_meta': {'version': 2}, '_meta': {'version': 2},
@@ -593,6 +613,11 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
outfile = PurePath('{shaman}') / outfile outfile = PurePath('{shaman}') / outfile
return None, outfile, missing_sources 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. # Create a unique directory that is still more or less identifyable.
# This should work better than a random ID. # This should work better than a random ID.
unique_dir = '%s-%s-%s' % (datetime.now().isoformat('-').replace(':', ''), unique_dir = '%s-%s-%s' % (datetime.now().isoformat('-').replace(':', ''),
@@ -729,6 +754,7 @@ class FLAMENCO_OT_abort(Operator, FlamencoPollMixin):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class FLAMENCO_OT_explore_file_path(FlamencoPollMixin, class FLAMENCO_OT_explore_file_path(FlamencoPollMixin,
Operator): Operator):
"""Opens the Flamenco job storage path in a file explorer. """Opens the Flamenco job storage path in a file explorer.
@@ -796,6 +822,7 @@ class FLAMENCO_OT_disable_output_path_override(Operator):
return {'FINISHED'} return {'FINISHED'}
@compatibility.convert_properties
class FLAMENCO_OT_set_recommended_sample_cap(Operator): class FLAMENCO_OT_set_recommended_sample_cap(Operator):
bl_idname = 'flamenco.set_recommended_sample_cap' bl_idname = 'flamenco.set_recommended_sample_cap'
bl_label = 'Set Recommended Maximum Sample Count' bl_label = 'Set Recommended Maximum Sample Count'
@@ -962,7 +989,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
prefs = preferences() 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:') labeled_row.label(text='Manager:')
prop_btn_row = labeled_row.row(align=True) prop_btn_row = labeled_row.row(align=True)
@@ -980,7 +1007,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
else: else:
prop_btn_row.label(text='Fetching available managers.') 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.label(text='Job Type:')
labeled_row.prop(context.scene, 'flamenco_render_job_type', text='') labeled_row.prop(context.scene, 'flamenco_render_job_type', text='')
@@ -1005,7 +1032,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
sample_count = scene_sample_count(context.scene) sample_count = scene_sample_count(context.scene)
recommended_cap = sample_count // 4 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) split.label(text='Total Sample Count: %d' % sample_count)
props = split.operator('flamenco.set_recommended_sample_cap', props = split.operator('flamenco.set_recommended_sample_cap',
text='Recommended Max Samples per Task: %d' % recommended_cap) text='Recommended Max Samples per Task: %d' % recommended_cap)
@@ -1019,7 +1046,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
else: else:
box.prop(context.scene, 'flamenco_render_fchunk_size') 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:') labeled_row.label(text='Frame Range:')
prop_btn_row = labeled_row.row(align=True) prop_btn_row = labeled_row.row(align=True)
prop_btn_row.prop(context.scene, 'flamenco_render_frame_range', text='') prop_btn_row.prop(context.scene, 'flamenco_render_frame_range', text='')
@@ -1030,7 +1057,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
paths_layout = layout.column(align=True) 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:') labeled_row.label(text='Storage:')
prop_btn_row = labeled_row.row(align=True) prop_btn_row = labeled_row.row(align=True)
prop_btn_row.label(text=prefs.flamenco_job_file_path) prop_btn_row.label(text=prefs.flamenco_job_file_path)
@@ -1038,12 +1065,18 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
text='', icon='DISK_DRIVE') text='', icon='DISK_DRIVE')
props.path = prefs.flamenco_job_file_path props.path = prefs.flamenco_job_file_path
if is_file_inside_job_storage(prefs, Path(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) render_output = render_output_path(context)
if render_output is None: if render_output is None:
paths_layout.label(text='Unable to render with Flamenco, outside of project directory.') paths_layout.label(text='Unable to render with Flamenco, outside of project directory.')
return 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:') labeled_row.label(text='Output:')
prop_btn_row = labeled_row.row(align=True) prop_btn_row = labeled_row.row(align=True)
@@ -1062,7 +1095,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
props.path = str(render_output.parent) props.path = str(render_output.parent)
if context.scene.flamenco_do_override_output_path: 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='Effective Output Path:')
labeled_row.label(text=str(render_output)) labeled_row.label(text=str(render_output))
@@ -1072,7 +1105,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
flamenco_status = context.window_manager.flamenco_status flamenco_status = context.window_manager.flamenco_status
if flamenco_status in {'IDLE', 'ABORTED', 'DONE'}: if flamenco_status in {'IDLE', 'ABORTED', 'DONE'}:
if prefs.flamenco_show_quit_after_submit_button: 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: else:
ui = layout ui = layout
ui.operator(FLAMENCO_OT_render.bl_idname, ui.operator(FLAMENCO_OT_render.bl_idname,

View File

@@ -25,7 +25,7 @@ import bpy
import pillarsdk import pillarsdk
from pillarsdk import exceptions as sdk_exceptions from pillarsdk import exceptions as sdk_exceptions
from .pillar import pillar_call 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'} REQUIRES_ROLES_FOR_IMAGE_SHARING = {'subscriber', 'demo'}
IMAGE_SHARING_GROUP_NODE_NAME = 'Image sharing' 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'] return share_group['_id']
@compatibility.convert_properties
class PILLAR_OT_image_share(pillar.PillarOperatorMixin, class PILLAR_OT_image_share(pillar.PillarOperatorMixin,
async_loop.AsyncModalOperatorMixin, async_loop.AsyncModalOperatorMixin,
bpy.types.Operator): bpy.types.Operator):

View File

@@ -35,7 +35,7 @@ import asyncio
import pillarsdk import pillarsdk
from pillarsdk import exceptions as sdk_exceptions from pillarsdk import exceptions as sdk_exceptions
from .pillar import pillar_call 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'] 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 # noinspection PyAttributeOutsideInit
@compatibility.convert_properties
class PILLAR_OT_sync(pillar.PillarOperatorMixin, class PILLAR_OT_sync(pillar.PillarOperatorMixin,
async_loop.AsyncModalOperatorMixin, async_loop.AsyncModalOperatorMixin,
bpy.types.Operator): bpy.types.Operator):

View File

@@ -26,7 +26,7 @@ import bpy
import bgl import bgl
import pillarsdk 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 menu_item as menu_item_mod # so that we can have menu items called 'menu_item'
from . import nodes from . import nodes
@@ -648,6 +648,7 @@ class BlenderCloudBrowser(pillar.PillarOperatorMixin,
self.scroll_offset_target = self.scroll_offset = 0 self.scroll_offset_target = self.scroll_offset = 0
@compatibility.convert_properties
class PILLAR_OT_switch_hdri(pillar.PillarOperatorMixin, class PILLAR_OT_switch_hdri(pillar.PillarOperatorMixin,
async_loop.AsyncModalOperatorMixin, async_loop.AsyncModalOperatorMixin,
bpy.types.Operator): bpy.types.Operator):
@@ -776,7 +777,7 @@ def _hdri_download_panel(self, current_image):
current_image.name) current_image.name)
return 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.label(text='HDRi', icon_value=blender.icon('CLOUD'))
row.prop(current_image, 'hdri_variation', text='') row.prop(current_image, 'hdri_variation', text='')

View File

@@ -94,6 +94,9 @@ def pyside_cache(propname):
result = wrapped(self, context) result = wrapped(self, context)
return result return result
finally: finally:
try:
rna_type, rna_info = self.bl_rna.__annotations__[propname]
except AttributeError:
rna_type, rna_info = getattr(self.bl_rna, propname) rna_type, rna_info = getattr(self.bl_rna, propname)
rna_info['_cached_result'] = result rna_info['_cached_result'] = result
return wrapper return wrapper

View File

@@ -3,7 +3,7 @@
lockfile==0.12.2 lockfile==0.12.2
pillarsdk==1.8.0 pillarsdk==1.8.0
wheel==0.29.0 wheel==0.29.0
blender-asset-tracer==1.1.1 blender-asset-tracer==1.2.1
# Secondary requirements: # Secondary requirements:
asn1crypto==0.24.0 asn1crypto==0.24.0

View File

@@ -123,8 +123,8 @@ class BuildWheels(Command):
"""Downloads a wheel from PyPI and saves it in self.wheels_path.""" """Downloads a wheel from PyPI and saves it in self.wheels_path."""
subprocess.check_call([ subprocess.check_call([
'pip', 'download', sys.executable, '-m', 'pip',
'--no-deps', 'download', '--no-deps',
'--dest', str(self.wheels_path), '--dest', str(self.wheels_path),
requirement[0] requirement[0]
]) ])
@@ -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.13.3', version='1.15',
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('.'),

View File

@@ -19,4 +19,4 @@ echo git commit -m \'Bumped version to $VERSION\' setup.py blender_cloud/__init_
echo git tag -a version-$VERSION -m \'Tagged version $VERSION\' echo git tag -a version-$VERSION -m \'Tagged version $VERSION\'
echo echo
echo "To build a distribution ZIP:" echo "To build a distribution ZIP:"
echo python setup.py bdist echo python3 setup.py bdist