Flamenco: Reporting BAT Pack process on the UI

This commit is contained in:
Sybren A. Stüvel 2018-03-15 18:01:04 +01:00
parent 9e5dcd0b55
commit b82bc14fcf
3 changed files with 115 additions and 15 deletions

View File

@ -170,7 +170,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
scene = context.scene
# Save to a different file, specifically for Flamenco.
context.window_manager.flamenco_status = 'PACKING'
context.window_manager.flamenco_status = 'SAVING'
filepath = await self._save_blendfile(context)
# Determine where the render output will be stored.
@ -348,7 +348,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
try:
outfile, missing_sources = await bat_interface.bat_copy(
filepath, projdir, outdir, exclusion_filter)
bpy.context, filepath, projdir, outdir, exclusion_filter)
except bat_interface.FileTransferError as ex:
self.log.error('Could not transfer %d files, starting with %s',
len(ex.files_remaining), ex.files_remaining[0])
@ -380,7 +380,10 @@ class FLAMENCO_OT_scene_to_frame_range(FlamencoPollMixin, Operator):
class FLAMENCO_OT_copy_files(Operator,
FlamencoPollMixin,
async_loop.AsyncModalOperatorMixin):
"""Uses BAT to copy the current blendfile + dependencies to the target directory."""
"""Uses BAT to copy the current blendfile + dependencies to the target directory.
This operator is not used directly, but can be useful for testing.
"""
bl_idname = 'flamenco.copy_files'
bl_label = 'Copy files to target'
bl_description = __doc__.rstrip('.')
@ -395,7 +398,8 @@ class FLAMENCO_OT_copy_files(Operator,
prefs = preferences()
exclusion_filter = (prefs.flamenco_exclude_filter or '').strip()
missing_sources = await bat_interface.bat_copy(
outpath, missing_sources = await bat_interface.bat_copy(
context,
Path(context.blend_data.filepath),
Path(prefs.cloud_project_local_path),
Path(prefs.flamenco_job_file_path),
@ -405,7 +409,8 @@ class FLAMENCO_OT_copy_files(Operator,
if missing_sources:
names = (ms.name for ms in missing_sources)
self.report({'ERROR'}, 'Missing source files: %s' % '; '.join(names))
else:
self.report({'INFO'}, 'Written %s' % outpath)
self.quit()
def quit(self):
@ -684,12 +689,16 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
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 == 'INVESTIGATING':
layout.label('Investigating your files')
elif flamenco_status == 'COMMUNICATING':
layout.label('Communicating with Flamenco Server')
else:
layout.label('Unknown Flamenco status %s' % flamenco_status)
if flamenco_status == 'TRANSFERRING':
layout.prop(context.window_manager, 'flamenco_progress',
text=context.window_manager.flamenco_status_txt)
elif flamenco_status != 'IDLE':
layout.label(context.window_manager.flamenco_status_txt)
def activate():
@ -790,14 +799,32 @@ def register():
bpy.types.WindowManager.flamenco_status = EnumProperty(
items=[
('IDLE', 'IDLE', 'Not doing anything.'),
('PACKING', 'PACKING', 'BAT-packing all dependencies.'),
('SAVING', 'SAVING', 'Saving your file.'),
('INVESTIGATING', 'INVESTIGATING', 'Finding all dependencies.'),
('TRANSFERRING', 'TRANSFERRING', 'Transferring all dependencies.'),
('COMMUNICATING', 'COMMUNICATING', 'Communicating with Flamenco Server.'),
('DONE', 'DONE', 'Not doing anything, but doing something earlier.'),
],
name='flamenco_status',
default='IDLE',
description='Current status of the Flamenco add-on',
update=redraw)
bpy.types.WindowManager.flamenco_status_txt = StringProperty(
name='Flamenco Status',
default='',
description='Textual description of what Flamenco is doing',
update=redraw)
bpy.types.WindowManager.flamenco_progress = IntProperty(
name='Flamenco Progress',
default=0,
description='File transfer progress',
subtype='PERCENTAGE',
min=0,
max=100,
update=redraw)
def unregister():
deactivate()

View File

@ -3,18 +3,79 @@
import asyncio
import logging
import typing
from pathlib import Path
import pathlib
from blender_asset_tracer import pack
from blender_asset_tracer.pack import progress
from blender_asset_tracer.pack.transfer import FileTransferError
import bpy
log = logging.getLogger(__name__)
async def bat_copy(base_blendfile: Path,
project: Path,
target: Path,
exclusion_filter: str) -> typing.Tuple[Path, typing.Set[Path]]:
class BatProgress(progress.Callback):
"""Report progress of BAT Packing to the UI.
Uses asyncio.run_coroutine_threadsafe() to ensure the UI is only updated
from the main thread. This is required since we run the BAT Pack in a
background thread.
"""
def __init__(self, context) -> None:
super().__init__()
self.wm = context.window_manager
self.loop = asyncio.get_event_loop()
def txt(self, msg: str):
"""Set a text in a thread-safe way."""
async def set_text():
self.wm.flamenco_status_txt = msg
asyncio.run_coroutine_threadsafe(set_text(), loop=self.loop)
def pack_start(self) -> None:
self.txt('Starting BAT Pack operation')
def pack_done(self,
output_blendfile: pathlib.Path,
missing_files: typing.Set[pathlib.Path]) -> None:
if missing_files:
self.txt('There were %d missing files' % len(missing_files))
else:
self.txt('Pack of %s done' % output_blendfile.name)
def trace_blendfile(self, filename: pathlib.Path) -> None:
"""Called for every blendfile opened when tracing dependencies."""
self.txt('Inspecting %s' % filename.name)
def trace_asset(self, filename: pathlib.Path) -> None:
if filename.stem == '.blend':
return
self.txt('Found asset %s' % filename.name)
def rewrite_blendfile(self, orig_filename: pathlib.Path) -> None:
self.txt('Rewriting %s' % orig_filename.name)
def transfer_file(self, src: pathlib.Path, dst: pathlib.Path) -> None:
self.txt('Transferring %s' % src.name)
def transfer_file_skipped(self, src: pathlib.Path, dst: pathlib.Path) -> None:
self.txt('Skipped %s' % src.name)
def transfer_progress(self, total_bytes: int, transferred_bytes: int) -> None:
self.wm.flamenco_progress = 100 * transferred_bytes / total_bytes
def missing_file(self, filename: pathlib.Path) -> None:
# TODO(Sybren): report missing files in a nice way
pass
async def bat_copy(context,
base_blendfile: pathlib.Path,
project: pathlib.Path,
target: pathlib.Path,
exclusion_filter: str) -> typing.Tuple[pathlib.Path, typing.Set[pathlib.Path]]:
"""Use BAT🦇 to copy the given file and dependencies to the target location.
:raises: FileTransferError if a file couldn't be transferred.
@ -23,13 +84,23 @@ async def bat_copy(base_blendfile: Path,
loop = asyncio.get_event_loop()
wm = bpy.context.window_manager
with pack.Packer(base_blendfile, project, target) as packer:
if exclusion_filter:
packer.exclude(*exclusion_filter.split())
packer.progress_cb = BatProgress(context)
log.debug('awaiting strategise')
wm.flamenco_status = 'INVESTIGATING'
await loop.run_in_executor(None, packer.strategise)
log.debug('awaiting execute')
wm.flamenco_status = 'TRANSFERRING'
await loop.run_in_executor(None, packer.execute)
log.debug('done')
wm.flamenco_status = 'DONE'
return packer.output_path, packer.missing_files

View File

@ -99,4 +99,6 @@ def pyside_cache(propname):
def redraw(self, context):
if context.area is None:
return
context.area.tag_redraw()