diff --git a/blender_cloud/async_loop.py b/blender_cloud/async_loop.py index 80c1fa0..280e28a 100644 --- a/blender_cloud/async_loop.py +++ b/blender_cloud/async_loop.py @@ -153,7 +153,7 @@ class AsyncLoopModalOperator(bpy.types.Operator): _loop_kicking_operator_running = True wm = context.window_manager - self.timer = wm.event_timer_add(0.00001, context.window) + self.timer = wm.event_timer_add(0.00001, window=context.window) return {'RUNNING_MODAL'} @@ -192,7 +192,7 @@ class AsyncModalOperatorMixin: def invoke(self, context, event): context.window_manager.modal_handler_add(self) - self.timer = context.window_manager.event_timer_add(1 / 15, context.window) + self.timer = context.window_manager.event_timer_add(1 / 15, window=context.window) self.log.info('Starting') self._new_async_task(self.async_execute(context)) diff --git a/blender_cloud/attract/__init__.py b/blender_cloud/attract/__init__.py index 66b368c..3b15361 100644 --- a/blender_cloud/attract/__init__.py +++ b/blender_cloud/attract/__init__.py @@ -46,9 +46,10 @@ if "bpy" in locals(): draw = importlib.reload(draw) pillar = importlib.reload(pillar) async_loop = importlib.reload(async_loop) + blender = importlib.reload(blender) else: from . import draw - from .. import pillar, async_loop + from .. import pillar, async_loop, blender import bpy import pillarsdk @@ -198,7 +199,7 @@ class AttractToolsPanel(AttractPollMixin, Panel): if strip.atc_object_id_conflict: warnbox = layout.box() warnbox.alert = True - warnbox.label('Warning: This shot is linked to multiple sequencer strips.', + warnbox.label(text='Warning: This shot is linked to multiple sequencer strips.', icon='ERROR') layout.prop(strip, 'atc_name', text='Name') @@ -230,7 +231,7 @@ class AttractToolsPanel(AttractPollMixin, Panel): icon='RENDER_STILL') # Group more dangerous operations. - dangerous_sub = layout.split(0.6, align=True) + dangerous_sub = layout.split(**blender.factor(0.6), align=True) dangerous_sub.operator('attract.strip_unlink', text='Unlink %s' % noun, icon='PANEL_CLOSE') @@ -918,12 +919,12 @@ def draw_strip_movie_meta(self, context): row = box.row(align=True) fname = meta.get('BLEND_FILE', None) or None if fname: - row.label('Original Blendfile: %s' % fname) + row.label(text='Original Blendfile: %s' % fname) row.operator(ATTRACT_OT_open_meta_blendfile.bl_idname, text='', icon='FILE_BLEND') sfra = meta.get('START_FRAME', '?') efra = meta.get('END_FRAME', '?') - box.label('Original Frame Range: %s-%s' % (sfra, efra)) + box.label(text='Original Frame Range: %s-%s' % (sfra, efra)) def activate(): diff --git a/blender_cloud/blender.py b/blender_cloud/blender.py index b7cb433..4d3701c 100644 --- a/blender_cloud/blender.py +++ b/blender_cloud/blender.py @@ -41,6 +41,18 @@ log = logging.getLogger(__name__) icons = None +@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): """Returns the list of items used by SyncStatusProperties.version EnumProperty.""" @@ -298,8 +310,8 @@ 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(percentage=0.33) - row.label('Blender Sync with Blender Cloud', icon_value=icon('CLOUD')) + row = bsync_box.row().split(**factor(0.33)) + row.label(text='Blender Sync with Blender Cloud', icon_value=icon('CLOUD')) icon_for_level = { 'INFO': 'NONE', @@ -309,7 +321,7 @@ class BlenderCloudPreferences(AddonPreferences): } msg_icon = icon_for_level[bss.level] if bss.message else 'NONE' message_container = row.row() - message_container.label(bss.message, icon=msg_icon) + message_container.label(text=bss.message, icon=msg_icon) sub = bsync_box.column() @@ -319,7 +331,7 @@ class BlenderCloudPreferences(AddonPreferences): # Image Share stuff share_box = layout.box() - share_box.label('Image Sharing on Blender Cloud', icon_value=icon('CLOUD')) + share_box.label(text='Image Sharing on Blender Cloud', icon_value=icon('CLOUD')) share_box.prop(self, 'open_browser_after_share') # Project selector @@ -341,7 +353,7 @@ class BlenderCloudPreferences(AddonPreferences): layout.enabled = bss.status in {'NONE', 'IDLE'} buttons = layout.column() - row_buttons = buttons.row().split(percentage=0.5) + row_buttons = buttons.row().split(**factor(0.5)) row_push = row_buttons.row() row_pull = row_buttons.row(align=True) @@ -366,11 +378,11 @@ class BlenderCloudPreferences(AddonPreferences): text='', icon='DOTSDOWN').action = 'SELECT' else: - row_pull.label('Cloud Sync is running.') + row_pull.label(text='Cloud Sync is running.') def draw_project_selector(self, project_box, bcp: BlenderCloudProjectGroup): project_row = project_box.row(align=True) - project_row.label('Project settings', icon_value=icon('CLOUD')) + project_row.label(text='Project settings', icon_value=icon('CLOUD')) row_buttons = project_row.row(align=True) @@ -391,31 +403,29 @@ class BlenderCloudPreferences(AddonPreferences): icon='WORLD') props.project_id = project else: - row_buttons.label('Fetching available projects.') + row_buttons.label(text='Fetching available projects.') enabled_for = project_extensions(project) if not project: return if not enabled_for: - project_box.label('This project is not set up for Attract or Flamenco') + project_box.label(text='This project is not set up for Attract or Flamenco') return - project_box.label('This project is set up for: %s' % - ', '.join(sorted(enabled_for))) + project_box.label(text='This project is set up for: %s' % + ', '.join(sorted(enabled_for))) # This is only needed when the project is set up for either Attract or Flamenco. project_box.prop(self, 'cloud_project_local_path', text='Local Project Path') def draw_flamenco_buttons(self, flamenco_box, bcp: flamenco.FlamencoManagerGroup, context): - from .flamenco import bat_interface - header_row = flamenco_box.row(align=True) - header_row.label('Flamenco:', icon_value=icon('CLOUD')) + header_row.label(text='Flamenco:', icon_value=icon('CLOUD')) - manager_split = flamenco_box.split(0.32, align=True) - manager_split.label('Manager:') + manager_split = flamenco_box.split(**factor(0.32), align=True) + manager_split.label(text='Manager:') manager_box = manager_split.row(align=True) if bcp.status in {'NONE', 'IDLE'}: @@ -429,9 +439,9 @@ class BlenderCloudPreferences(AddonPreferences): text='', icon='FILE_REFRESH') else: - manager_box.label('Fetching available managers.') + manager_box.label(text='Fetching available managers.') - path_split = flamenco_box.split(0.32, align=True) + path_split = flamenco_box.split(**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='') @@ -439,7 +449,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(0.32, align=True) + path_split = job_output_box.split(**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='') @@ -447,8 +457,8 @@ class BlenderCloudPreferences(AddonPreferences): props.path = self.flamenco_job_output_path job_output_box.prop(self, 'flamenco_exclude_filter') - prop_split = job_output_box.split(0.32, align=True) - prop_split.label('Strip Components:') + prop_split = job_output_box.split(**factor(0.32), align=True) + prop_split.label(text='Strip Components:') prop_split.prop(self, 'flamenco_job_output_strip_components', text='') from .flamenco import render_output_path @@ -456,12 +466,12 @@ class BlenderCloudPreferences(AddonPreferences): path_box = job_output_box.row(align=True) output_path = render_output_path(context) if output_path: - path_box.label(str(output_path)) + path_box.label(text=str(output_path)) props = path_box.operator('flamenco.explore_file_path', text='', icon='DISK_DRIVE') props.path = str(output_path.parent) else: - path_box.label('Blend file is not in your project path, ' - 'unable to give output path example.') + path_box.label(text='Blend file is not in your project path, ' + 'unable to give output path example.') flamenco_box.prop(self, 'flamenco_open_browser_after_submit') diff --git a/blender_cloud/flamenco/__init__.py b/blender_cloud/flamenco/__init__.py index 7b7fb3b..1a5ee2a 100644 --- a/blender_cloud/flamenco/__init__.py +++ b/blender_cloud/flamenco/__init__.py @@ -33,10 +33,13 @@ if "bpy" in locals(): try: bat_interface = importlib.reload(bat_interface) sdk = importlib.reload(sdk) + blender = importlib.reload(blender) except NameError: from . import bat_interface, sdk + from .. import blender else: from . import bat_interface, sdk + from .. import blender import bpy from bpy.types import AddonPreferences, Operator, WindowManager, Scene, PropertyGroup @@ -695,12 +698,12 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin): else: prop_btn_row.label('Fetching available managers.') - labeled_row = layout.split(0.25, align=True) - labeled_row.label('Job Type:') + labeled_row = layout.split(**blender.factor(0.25), align=True) + labeled_row.label(text='Job Type:') labeled_row.prop(context.scene, 'flamenco_render_job_type', text='') - labeled_row = layout.split(0.25, align=True) - labeled_row.label('Frame Range:') + labeled_row = layout.split(**blender.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='') prop_btn_row.operator('flamenco.scene_to_frame_range', text='', icon='ARROW_LEFTRIGHT') @@ -714,21 +717,21 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin): paths_layout = layout.column(align=True) - labeled_row = paths_layout.split(0.25, align=True) - labeled_row.label('Storage:') + labeled_row = paths_layout.split(**blender.factor(0.25), align=True) + labeled_row.label(text='Storage:') prop_btn_row = labeled_row.row(align=True) - prop_btn_row.label(prefs.flamenco_job_file_path) + prop_btn_row.label(text=prefs.flamenco_job_file_path) props = prop_btn_row.operator(FLAMENCO_OT_explore_file_path.bl_idname, text='', icon='DISK_DRIVE') props.path = prefs.flamenco_job_file_path render_output = render_output_path(context) if render_output is None: - paths_layout.label('Unable to render with Flamenco, outside of project directory.') + paths_layout.label(text='Unable to render with Flamenco, outside of project directory.') return - labeled_row = paths_layout.split(0.25, align=True) - labeled_row.label('Output:') + labeled_row = paths_layout.split(**blender.factor(0.25), align=True) + labeled_row.label(text='Output:') prop_btn_row = labeled_row.row(align=True) if context.scene.flamenco_do_override_output_path: @@ -736,7 +739,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin): op = FLAMENCO_OT_disable_output_path_override.bl_idname icon = 'X' else: - prop_btn_row.label(str(render_output)) + prop_btn_row.label(text=str(render_output)) op = FLAMENCO_OT_enable_output_path_override.bl_idname icon = 'GREASEPENCIL' prop_btn_row.operator(op, icon=icon, text='') @@ -746,9 +749,9 @@ 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(0.25, align=True) - labeled_row.label('Effective Output Path:') - labeled_row.label(str(render_output)) + labeled_row = paths_layout.split(**blender.factor(0.25), align=True) + labeled_row.label(text='Effective Output Path:') + labeled_row.label(text=str(render_output)) # Show current status of Flamenco. flamenco_status = context.window_manager.flamenco_status @@ -760,13 +763,13 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin): layout.operator(FLAMENCO_OT_copy_files.bl_idname) elif flamenco_status == 'INVESTIGATING': row = layout.row(align=True) - row.label('Investigating your files') + row.label(text='Investigating your files') row.operator(FLAMENCO_OT_abort.bl_idname, text='', icon='CANCEL') elif flamenco_status == 'COMMUNICATING': - layout.label('Communicating with Flamenco Server') + layout.label(text='Communicating with Flamenco Server') elif flamenco_status == 'ABORTING': row = layout.row(align=True) - row.label('Aborting, please wait.') + row.label(text='Aborting, please wait.') row.operator(FLAMENCO_OT_abort.bl_idname, text='', icon='CANCEL') if flamenco_status == 'TRANSFERRING': row = layout.row(align=True) @@ -774,7 +777,7 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin): text=context.window_manager.flamenco_status_txt) row.operator(FLAMENCO_OT_abort.bl_idname, text='', icon='CANCEL') elif flamenco_status != 'IDLE' and context.window_manager.flamenco_status_txt: - layout.label(context.window_manager.flamenco_status_txt) + layout.label(text=context.window_manager.flamenco_status_txt) def activate(): diff --git a/blender_cloud/image_sharing.py b/blender_cloud/image_sharing.py index fa1e9bd..779ff1e 100644 --- a/blender_cloud/image_sharing.py +++ b/blender_cloud/image_sharing.py @@ -327,7 +327,12 @@ def register(): bpy.utils.register_class(PILLAR_OT_image_share) bpy.types.IMAGE_MT_image.append(image_editor_menu) - bpy.types.INFO_MT_window.append(window_menu) + try: + menu = bpy.types.TOPBAR_MT_window + except AttributeError: + # Blender < 2.80 + menu = bpy.types.INFO_MT_window + menu.append(window_menu) def unregister(): diff --git a/blender_cloud/texture_browser.py b/blender_cloud/texture_browser.py index 20abe9b..9ee8dca 100644 --- a/blender_cloud/texture_browser.py +++ b/blender_cloud/texture_browser.py @@ -1013,8 +1013,8 @@ def _hdri_download_panel(self, current_image): current_image.name) return - row = self.layout.row(align=True).split(0.3) - row.label('HDRi', icon_value=blender.icon('CLOUD')) + row = self.layout.row(align=True).split(**blender.factor(0.3)) + row.label(text='HDRi', icon_value=blender.icon('CLOUD')) row.prop(current_image, 'hdri_variation', text='') if current_image.hdri_variation != current_variation: