Compare commits

...

5 Commits

Author SHA1 Message Date
cb73030e6a Bumped version to 1.5.99999 2017-01-24 17:22:04 +01:00
fbf02c3625 Captialising labels/captions 2017-01-24 15:15:08 +01:00
95699aca36 Open webbrowser after submitting a Flamenco job
This can be disabled in the add-on preferences.
2017-01-24 15:14:43 +01:00
60018cd78c Using explicit status EnumProperty to show Flamenco status
By Andy's request, I've removed the window_manager.progress_xxx stuff (so
no longer hijacking the mouse cursor) and instead show the Flamenco status
in the Flamenco Render panel.
2017-01-24 14:55:39 +01:00
5f73837d3c Don't write to artist's blend file, but to temporary file.
This file is saved to '{blendfile}.flamenco.blend', which is used to BAM-
pack and create the Flamenco job. After that, the file is removed from
the local filesystem again.
2017-01-24 14:39:49 +01:00
4 changed files with 101 additions and 33 deletions

View File

@@ -21,7 +21,7 @@
bl_info = {
'name': 'Blender Cloud',
"author": "Sybren A. Stüvel, Francesco Siddi, Inês Almeida, Antony Riakiotakis",
'version': (1, 5, 9999),
'version': (1, 5, 99999),
'blender': (2, 77, 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 '

View File

@@ -155,12 +155,12 @@ class BlenderCloudPreferences(AddonPreferences):
)
local_texture_dir = StringProperty(
name='Default Blender Cloud texture storage directory',
name='Default Blender Cloud Texture Storage Directory',
subtype='DIR_PATH',
default='//textures')
open_browser_after_share = BoolProperty(
name='Open browser after sharing file',
name='Open Browser after Sharing File',
description='When enabled, Blender will open a webbrowser',
default=True
)
@@ -169,7 +169,7 @@ class BlenderCloudPreferences(AddonPreferences):
# can switch projects and the local path switches with it.
attract_project = PointerProperty(type=BlenderCloudProjectGroup)
attract_project_local_path = StringProperty(
name='Local project path',
name='Local Project Path',
description='Local path of your Attract project, used to search for blend files; '
'usually best to set to an absolute path',
subtype='DIR_PATH',
@@ -180,19 +180,19 @@ class BlenderCloudPreferences(AddonPreferences):
# NOTE: The assumption is that the workers can also find the files in the same path.
# This assumption is true for the Blender Institute.
flamenco_job_file_path = StringProperty(
name='Job file path',
name='Job File Path',
description='Path where to store job files, should be accesible for Workers too',
subtype='DIR_PATH',
default='/render/_flamenco/storage')
# TODO: before making Flamenco public, change the defaults to something less Institute-specific.
flamenco_job_output_path = StringProperty(
name='Job output path',
name='Job Output Path',
description='Path where to store output files, should be accessible for Workers',
subtype='DIR_PATH',
default='/render/_flamenco/output')
flamenco_job_output_strip_components = IntProperty(
name='Job output path strip components',
name='Job Output Path Strip Components',
description='The final output path comprises of the job output path, and the blend file '
'path relative to the project with this many path components stripped off '
'the front',
@@ -200,6 +200,11 @@ class BlenderCloudPreferences(AddonPreferences):
default=0,
soft_max=4,
)
flamenco_open_browser_after_submit = BoolProperty(
name='Open Browser after Submitting Job',
description='When enabled, Blender will open a webbrowser',
default=True
)
def draw(self, context):
import textwrap
@@ -379,7 +384,7 @@ class BlenderCloudPreferences(AddonPreferences):
props.path = self.flamenco_job_output_path
job_output_box.prop(self, 'flamenco_job_output_strip_components',
text='Strip components')
text='Strip Components')
from .flamenco import render_output_path
@@ -389,6 +394,8 @@ class BlenderCloudPreferences(AddonPreferences):
props = path_box.operator('flamenco.explore_file_path', text='', icon='DISK_DRIVE')
props.path = str(output_path.parent)
flamenco_box.prop(self, 'flamenco_open_browser_after_submit')
# TODO: make a reusable way to select projects, and use that for Attract and Flamenco.
note_box = flamenco_box.column(align=True)
note_box.label('NOTE: For now, Flamenco uses the same project as Attract.')

View File

@@ -128,22 +128,27 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
if not await self.authenticate(context):
return
context.window_manager.progress_begin(0, 4)
context.window_manager.progress_update(1)
from pillarsdk import exceptions as sdk_exceptions
from ..blender import preferences
filepath = Path(context.blend_data.filepath)
scene = context.scene
# The file extension should be determined by the render settings, not necessarily
# by the setttings in the output panel.
scene.render.use_file_extension = True
bpy.ops.wm.save_mainfile()
# Save to a different file, specifically for Flamenco. We shouldn't overwrite
# the artist's file. We can compress, since this file won't be managed by SVN
# and doesn't need diffability.
context.window_manager.flamenco_status = 'PACKING'
filepath = Path(context.blend_data.filepath).with_suffix('.flamenco.blend')
self.log.info('Saving copy to temporary file %s', filepath)
bpy.ops.wm.save_as_mainfile(filepath=str(filepath),
compress=True,
copy=True)
# Determine where the render output will be stored.
render_output = render_output_path(context)
render_output = render_output_path(context, filepath)
if render_output is None:
self.report({'ERROR'}, 'Current file is outside of project path.')
self.quit()
@@ -155,11 +160,10 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
if not outfile:
return
context.window_manager.progress_update(3)
# Create the job at Flamenco Server.
prefs = preferences()
context.window_manager.flamenco_status = 'COMMUNICATING'
settings = {'blender_cmd': '{blender}',
'chunk_size': scene.flamenco_render_chunk_size,
'filepath': str(outfile),
@@ -186,6 +190,25 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
job_info['missing_files'] = [str(mf) for mf in missing_sources]
json.dump(job_info, outfile, sort_keys=True, indent=4)
# We can now remove the local copy we made with bpy.ops.wm.save_as_mainfile().
# Strictly speaking we can already remove it after the BAM-pack, but it may come in
# handy in case of failures.
try:
self.log.info('Removing temporary file %s', filepath)
filepath.unlink()
except Exception as ex:
self.report({'ERROR'}, 'Unable to remove file: %s' % ex)
self.quit()
return
if prefs.flamenco_open_browser_after_submit:
import webbrowser
from urllib.parse import urljoin
from ..blender import PILLAR_WEB_SERVER_URL
url = urljoin(PILLAR_WEB_SERVER_URL, '/flamenco/jobs/%s/redir' % job_info['_id'])
webbrowser.open_new_tab(url)
# Do a final report.
if missing_sources:
names = (ms.name for ms in missing_sources)
@@ -193,11 +216,12 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
'; '.join(names))
else:
self.report({'INFO'}, 'Flamenco job created.')
self.quit()
def quit(self):
super().quit()
bpy.context.window_manager.progress_end()
bpy.context.window_manager.flamenco_status = 'IDLE'
async def bam_pack(self, filepath: Path) -> (typing.Optional[Path], typing.List[Path]):
"""BAM-packs the blendfile to the destination directory.
@@ -269,6 +293,8 @@ class FLAMENCO_OT_copy_files(Operator,
from . import bam_interface
from ..blender import preferences
context.window_manager.flamenco_status = 'PACKING'
missing_sources = await bam_interface.bam_copy(
Path(context.blend_data.filepath),
Path(preferences().flamenco_job_file_path),
@@ -280,6 +306,10 @@ class FLAMENCO_OT_copy_files(Operator,
self.quit()
def quit(self):
super().quit()
bpy.context.window_manager.flamenco_status = 'IDLE'
class FLAMENCO_OT_explore_file_path(Operator):
"""Opens the Flamenco job storage path in a file explorer."""
@@ -353,7 +383,7 @@ def is_image_type(render_output_type: str) -> bool:
@functools.lru_cache(1)
def _render_output_path(
local_project_path: str,
blend_filepath: str,
blend_filepath: Path,
flamenco_job_output_strip_components: int,
flamenco_job_output_path: str,
render_image_format: str,
@@ -366,16 +396,15 @@ def _render_output_path(
"""
project_path = Path(bpy.path.abspath(local_project_path)).resolve()
blendfile = Path(blend_filepath)
try:
proj_rel = blendfile.parent.relative_to(project_path)
proj_rel = blend_filepath.parent.relative_to(project_path)
except ValueError:
return None
rel_parts = proj_rel.parts[flamenco_job_output_strip_components:]
output_top = Path(flamenco_job_output_path)
dir_components = output_top.joinpath(*rel_parts) / blendfile.stem
dir_components = output_top.joinpath(*rel_parts) / blend_filepath.stem
# Blender will have to append the file extensions by itself.
if is_image_type(render_image_format):
@@ -383,9 +412,12 @@ def _render_output_path(
return dir_components / flamenco_render_frame_range
def render_output_path(context) -> typing.Optional[PurePath]:
def render_output_path(context, filepath: Path=None) -> typing.Optional[PurePath]:
"""Returns the render output path to be sent to Flamenco.
:param context: the Blender context (used to find Flamenco preferences etc.)
:param filepath: the Path of the blend file to render, or None for the current file.
Returns None when the current blend file is outside the project path.
"""
@@ -394,9 +426,12 @@ def render_output_path(context) -> typing.Optional[PurePath]:
scene = context.scene
prefs = preferences()
if filepath is None:
filepath = Path(context.blend_data.filepath)
return _render_output_path(
prefs.attract_project_local_path,
context.blend_data.filepath,
filepath,
prefs.flamenco_job_output_strip_components,
prefs.flamenco_job_output_path,
scene.render.image_settings.file_format,
@@ -421,18 +456,18 @@ class FLAMENCO_PT_render(bpy.types.Panel):
layout.prop(context.scene, 'flamenco_render_job_priority')
layout.prop(context.scene, 'flamenco_render_chunk_size')
labeled_row = layout.split(0.2, align=True)
labeled_row.label('Job type:')
labeled_row = layout.split(0.25, align=True)
labeled_row.label('Job Type:')
labeled_row.prop(context.scene, 'flamenco_render_job_type', text='')
labeled_row = layout.split(0.2, align=True)
labeled_row.label('Frame range:')
labeled_row = layout.split(0.25, align=True)
labeled_row.label('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')
readonly_stuff = layout.column(align=True)
labeled_row = readonly_stuff.split(0.2, align=True)
labeled_row = readonly_stuff.split(0.25, align=True)
labeled_row.label('Storage:')
prop_btn_row = labeled_row.row(align=True)
prop_btn_row.label(prefs.flamenco_job_file_path)
@@ -440,10 +475,11 @@ class FLAMENCO_PT_render(bpy.types.Panel):
text='', icon='DISK_DRIVE')
props.path = prefs.flamenco_job_file_path
labeled_row = readonly_stuff.split(0.2, align=True)
labeled_row = readonly_stuff.split(0.25, align=True)
labeled_row.label('Output:')
prop_btn_row = labeled_row.row(align=True)
render_output = render_output_path(context)
if render_output is None:
prop_btn_row.label('Unable to render with Flamenco, outside of project directory.')
else:
@@ -452,9 +488,17 @@ class FLAMENCO_PT_render(bpy.types.Panel):
text='', icon='DISK_DRIVE')
props.path = str(render_output.parent)
layout.operator(FLAMENCO_OT_render.bl_idname,
text='Render on Flamenco',
icon='RENDER_ANIMATION')
flamenco_status = context.window_manager.flamenco_status
if flamenco_status == 'IDLE':
layout.operator(FLAMENCO_OT_render.bl_idname,
text='Render on Flamenco',
icon='RENDER_ANIMATION')
elif flamenco_status == 'PACKING':
layout.label('Flamenco is packing your file + dependencies')
elif flamenco_status == 'COMMUNICATING':
layout.label('Communicating with Flamenco Server')
else:
layout.label('Unknown Flamenco status %s' % flamenco_status)
if not context.scene.render.use_overwrite:
warnbox = layout.box().column(align=True)
@@ -463,6 +507,8 @@ class FLAMENCO_PT_render(bpy.types.Panel):
def register():
from ..utils import redraw
bpy.utils.register_class(FlamencoManagerGroup)
bpy.utils.register_class(FLAMENCO_OT_fmanagers)
bpy.utils.register_class(FLAMENCO_OT_render)
@@ -496,6 +542,17 @@ def register():
description='Higher numbers mean higher priority'
)
bpy.types.WindowManager.flamenco_status = EnumProperty(
items=[
('IDLE', 'IDLE', 'Not doing anything.'),
('PACKING', 'PACKING', 'BAM-packing all dependencies.'),
('COMMUNICATING', 'COMMUNICATING', 'Communicating with Flamenco Server.'),
],
name='flamenco_status',
default='IDLE',
description='Current status of the Flamenco add-on',
update=redraw)
def unregister():
bpy.utils.unregister_module(__name__)
@@ -516,3 +573,7 @@ def unregister():
del bpy.types.Scene.flamenco_render_job_priority
except AttributeError:
pass
try:
del bpy.types.WindowManager.flamenco_status
except AttributeError:
pass

View File

@@ -227,7 +227,7 @@ setup(
'wheels': BuildWheels},
name='blender_cloud',
description='The Blender Cloud addon allows browsing the Blender Cloud from Blender.',
version='1.5.9999',
version='1.5.99999',
author='Sybren A. Stüvel',
author_email='sybren@stuvel.eu',
packages=find_packages('.'),