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 scene = context.scene
# Save to a different file, specifically for Flamenco. # 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) filepath = await self._save_blendfile(context)
# Determine where the render output will be stored. # Determine where the render output will be stored.
@ -348,7 +348,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
try: try:
outfile, missing_sources = await bat_interface.bat_copy( 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: except bat_interface.FileTransferError as ex:
self.log.error('Could not transfer %d files, starting with %s', self.log.error('Could not transfer %d files, starting with %s',
len(ex.files_remaining), ex.files_remaining[0]) 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, class FLAMENCO_OT_copy_files(Operator,
FlamencoPollMixin, FlamencoPollMixin,
async_loop.AsyncModalOperatorMixin): 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_idname = 'flamenco.copy_files'
bl_label = 'Copy files to target' bl_label = 'Copy files to target'
bl_description = __doc__.rstrip('.') bl_description = __doc__.rstrip('.')
@ -395,7 +398,8 @@ class FLAMENCO_OT_copy_files(Operator,
prefs = preferences() prefs = preferences()
exclusion_filter = (prefs.flamenco_exclude_filter or '').strip() 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(context.blend_data.filepath),
Path(prefs.cloud_project_local_path), Path(prefs.cloud_project_local_path),
Path(prefs.flamenco_job_file_path), Path(prefs.flamenco_job_file_path),
@ -405,7 +409,8 @@ class FLAMENCO_OT_copy_files(Operator,
if missing_sources: if missing_sources:
names = (ms.name for ms in missing_sources) names = (ms.name for ms in missing_sources)
self.report({'ERROR'}, 'Missing source files: %s' % '; '.join(names)) self.report({'ERROR'}, 'Missing source files: %s' % '; '.join(names))
else:
self.report({'INFO'}, 'Written %s' % outpath)
self.quit() self.quit()
def quit(self): def quit(self):
@ -684,12 +689,16 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
layout.operator(FLAMENCO_OT_render.bl_idname, layout.operator(FLAMENCO_OT_render.bl_idname,
text='Render on Flamenco', text='Render on Flamenco',
icon='RENDER_ANIMATION') icon='RENDER_ANIMATION')
elif flamenco_status == 'PACKING': elif flamenco_status == 'INVESTIGATING':
layout.label('Flamenco is packing your file + dependencies') layout.label('Investigating your files')
elif flamenco_status == 'COMMUNICATING': elif flamenco_status == 'COMMUNICATING':
layout.label('Communicating with Flamenco Server') 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(): def activate():
@ -790,14 +799,32 @@ def register():
bpy.types.WindowManager.flamenco_status = EnumProperty( bpy.types.WindowManager.flamenco_status = EnumProperty(
items=[ items=[
('IDLE', 'IDLE', 'Not doing anything.'), ('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.'), ('COMMUNICATING', 'COMMUNICATING', 'Communicating with Flamenco Server.'),
('DONE', 'DONE', 'Not doing anything, but doing something earlier.'),
], ],
name='flamenco_status', name='flamenco_status',
default='IDLE', default='IDLE',
description='Current status of the Flamenco add-on', description='Current status of the Flamenco add-on',
update=redraw) 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(): def unregister():
deactivate() deactivate()

View File

@ -3,18 +3,79 @@
import asyncio import asyncio
import logging import logging
import typing import typing
from pathlib import Path import pathlib
from blender_asset_tracer import pack from blender_asset_tracer import pack
from blender_asset_tracer.pack import progress
from blender_asset_tracer.pack.transfer import FileTransferError from blender_asset_tracer.pack.transfer import FileTransferError
import bpy
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
async def bat_copy(base_blendfile: Path, class BatProgress(progress.Callback):
project: Path, """Report progress of BAT Packing to the UI.
target: Path,
exclusion_filter: str) -> typing.Tuple[Path, typing.Set[Path]]: 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. """Use BAT🦇 to copy the given file and dependencies to the target location.
:raises: FileTransferError if a file couldn't be transferred. :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() loop = asyncio.get_event_loop()
wm = bpy.context.window_manager
with pack.Packer(base_blendfile, project, target) as packer: with pack.Packer(base_blendfile, project, target) as packer:
if exclusion_filter: if exclusion_filter:
packer.exclude(*exclusion_filter.split()) packer.exclude(*exclusion_filter.split())
packer.progress_cb = BatProgress(context)
log.debug('awaiting strategise') log.debug('awaiting strategise')
wm.flamenco_status = 'INVESTIGATING'
await loop.run_in_executor(None, packer.strategise) await loop.run_in_executor(None, packer.strategise)
log.debug('awaiting execute') log.debug('awaiting execute')
wm.flamenco_status = 'TRANSFERRING'
await loop.run_in_executor(None, packer.execute) await loop.run_in_executor(None, packer.execute)
log.debug('done') log.debug('done')
wm.flamenco_status = 'DONE'
return packer.output_path, packer.missing_files return packer.output_path, packer.missing_files

View File

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