Allow aborting a running BAT Pack operation
This commit is contained in:
parent
b82bc14fcf
commit
164f65f30c
@ -310,10 +310,6 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
|||||||
|
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
def quit(self):
|
|
||||||
super().quit()
|
|
||||||
bpy.context.window_manager.flamenco_status = 'IDLE'
|
|
||||||
|
|
||||||
async def bat_pack(self, filepath: Path) -> (typing.Optional[Path], typing.List[Path]):
|
async def bat_pack(self, filepath: Path) -> (typing.Optional[Path], typing.List[Path]):
|
||||||
"""BAT-packs the blendfile to the destination directory.
|
"""BAT-packs the blendfile to the destination directory.
|
||||||
|
|
||||||
@ -347,7 +343,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
|||||||
return None, []
|
return None, []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
outfile, missing_sources = await bat_interface.bat_copy(
|
outfile, missing_sources = await bat_interface.copy(
|
||||||
bpy.context, 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',
|
||||||
@ -356,6 +352,7 @@ class FLAMENCO_OT_render(async_loop.AsyncModalOperatorMixin,
|
|||||||
self.quit()
|
self.quit()
|
||||||
return None, []
|
return None, []
|
||||||
|
|
||||||
|
bpy.context.window_manager.flamenco_status = 'DONE'
|
||||||
return outfile, missing_sources
|
return outfile, missing_sources
|
||||||
|
|
||||||
|
|
||||||
@ -398,7 +395,7 @@ 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()
|
||||||
|
|
||||||
outpath, missing_sources = await bat_interface.bat_copy(
|
outpath, missing_sources = await bat_interface.copy(
|
||||||
context,
|
context,
|
||||||
Path(context.blend_data.filepath),
|
Path(context.blend_data.filepath),
|
||||||
Path(prefs.cloud_project_local_path),
|
Path(prefs.cloud_project_local_path),
|
||||||
@ -411,11 +408,24 @@ class FLAMENCO_OT_copy_files(Operator,
|
|||||||
self.report({'ERROR'}, 'Missing source files: %s' % '; '.join(names))
|
self.report({'ERROR'}, 'Missing source files: %s' % '; '.join(names))
|
||||||
else:
|
else:
|
||||||
self.report({'INFO'}, 'Written %s' % outpath)
|
self.report({'INFO'}, 'Written %s' % outpath)
|
||||||
|
context.window_manager.flamenco_status = 'DONE'
|
||||||
self.quit()
|
self.quit()
|
||||||
|
|
||||||
def quit(self):
|
|
||||||
super().quit()
|
class FLAMENCO_OT_abort(Operator, FlamencoPollMixin):
|
||||||
bpy.context.window_manager.flamenco_status = 'IDLE'
|
"""Aborts a running Flamenco file packing/transfer operation."""
|
||||||
|
bl_idname = 'flamenco.abort'
|
||||||
|
bl_label = 'Abort'
|
||||||
|
bl_description = __doc__.rstrip('.')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return super().poll(context) and context.window_manager.flamenco_status != 'ABORTING'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
context.window_manager.flamenco_status = 'ABORTING'
|
||||||
|
bat_interface.abort()
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class FLAMENCO_OT_explore_file_path(FlamencoPollMixin,
|
class FLAMENCO_OT_explore_file_path(FlamencoPollMixin,
|
||||||
@ -685,19 +695,26 @@ class FLAMENCO_PT_render(bpy.types.Panel, FlamencoPollMixin):
|
|||||||
labeled_row.label(str(render_output))
|
labeled_row.label(str(render_output))
|
||||||
|
|
||||||
flamenco_status = context.window_manager.flamenco_status
|
flamenco_status = context.window_manager.flamenco_status
|
||||||
if flamenco_status == 'IDLE':
|
if flamenco_status in {'IDLE', 'ABORTED', 'DONE'}:
|
||||||
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 == 'INVESTIGATING':
|
elif flamenco_status == 'INVESTIGATING':
|
||||||
layout.label('Investigating your files')
|
row = layout.row(align=True)
|
||||||
|
row.label('Investigating your files')
|
||||||
|
row.operator(FLAMENCO_OT_abort.bl_idname, text='', icon='CANCEL')
|
||||||
elif flamenco_status == 'COMMUNICATING':
|
elif flamenco_status == 'COMMUNICATING':
|
||||||
layout.label('Communicating with Flamenco Server')
|
layout.label('Communicating with Flamenco Server')
|
||||||
|
elif flamenco_status == 'ABORTING':
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.label('Aborting, please wait.')
|
||||||
|
row.operator(FLAMENCO_OT_abort.bl_idname, text='', icon='CANCEL')
|
||||||
if flamenco_status == 'TRANSFERRING':
|
if flamenco_status == 'TRANSFERRING':
|
||||||
layout.prop(context.window_manager, 'flamenco_progress',
|
row = layout.row(align=True)
|
||||||
text=context.window_manager.flamenco_status_txt)
|
row.prop(context.window_manager, 'flamenco_progress',
|
||||||
elif flamenco_status != 'IDLE':
|
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(context.window_manager.flamenco_status_txt)
|
||||||
|
|
||||||
|
|
||||||
@ -746,6 +763,7 @@ def register():
|
|||||||
bpy.utils.register_class(FLAMENCO_OT_explore_file_path)
|
bpy.utils.register_class(FLAMENCO_OT_explore_file_path)
|
||||||
bpy.utils.register_class(FLAMENCO_OT_enable_output_path_override)
|
bpy.utils.register_class(FLAMENCO_OT_enable_output_path_override)
|
||||||
bpy.utils.register_class(FLAMENCO_OT_disable_output_path_override)
|
bpy.utils.register_class(FLAMENCO_OT_disable_output_path_override)
|
||||||
|
bpy.utils.register_class(FLAMENCO_OT_abort)
|
||||||
bpy.utils.register_class(FLAMENCO_PT_render)
|
bpy.utils.register_class(FLAMENCO_PT_render)
|
||||||
|
|
||||||
scene = bpy.types.Scene
|
scene = bpy.types.Scene
|
||||||
@ -804,6 +822,8 @@ def register():
|
|||||||
('TRANSFERRING', 'TRANSFERRING', 'Transferring 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.'),
|
('DONE', 'DONE', 'Not doing anything, but doing something earlier.'),
|
||||||
|
('ABORTING', 'ABORTING', 'User requested we stop doing something.'),
|
||||||
|
('ABORTED', 'ABORTED', 'We stopped doing something.'),
|
||||||
],
|
],
|
||||||
name='flamenco_status',
|
name='flamenco_status',
|
||||||
default='IDLE',
|
default='IDLE',
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
import threading
|
||||||
import typing
|
import typing
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
@ -14,6 +15,9 @@ import bpy
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_running_packer = None # type: pack.Packer
|
||||||
|
_packer_lock = threading.RLock()
|
||||||
|
|
||||||
|
|
||||||
class BatProgress(progress.Callback):
|
class BatProgress(progress.Callback):
|
||||||
"""Report progress of BAT Packing to the UI.
|
"""Report progress of BAT Packing to the UI.
|
||||||
@ -30,10 +34,20 @@ class BatProgress(progress.Callback):
|
|||||||
|
|
||||||
def txt(self, msg: str):
|
def txt(self, msg: str):
|
||||||
"""Set a text in a thread-safe way."""
|
"""Set a text in a thread-safe way."""
|
||||||
|
|
||||||
async def set_text():
|
async def set_text():
|
||||||
self.wm.flamenco_status_txt = msg
|
self.wm.flamenco_status_txt = msg
|
||||||
|
|
||||||
asyncio.run_coroutine_threadsafe(set_text(), loop=self.loop)
|
asyncio.run_coroutine_threadsafe(set_text(), loop=self.loop)
|
||||||
|
|
||||||
|
def status(self, status: str):
|
||||||
|
"""Set the flamenco_status property in a thread-safe way."""
|
||||||
|
|
||||||
|
async def set_status():
|
||||||
|
self.wm.flamenco_status = status
|
||||||
|
|
||||||
|
asyncio.run_coroutine_threadsafe(set_status(), loop=self.loop)
|
||||||
|
|
||||||
def pack_start(self) -> None:
|
def pack_start(self) -> None:
|
||||||
self.txt('Starting BAT Pack operation')
|
self.txt('Starting BAT Pack operation')
|
||||||
|
|
||||||
@ -45,6 +59,10 @@ class BatProgress(progress.Callback):
|
|||||||
else:
|
else:
|
||||||
self.txt('Pack of %s done' % output_blendfile.name)
|
self.txt('Pack of %s done' % output_blendfile.name)
|
||||||
|
|
||||||
|
def pack_aborted(self):
|
||||||
|
self.txt('Aborted')
|
||||||
|
self.status('ABORTED')
|
||||||
|
|
||||||
def trace_blendfile(self, filename: pathlib.Path) -> None:
|
def trace_blendfile(self, filename: pathlib.Path) -> None:
|
||||||
"""Called for every blendfile opened when tracing dependencies."""
|
"""Called for every blendfile opened when tracing dependencies."""
|
||||||
self.txt('Inspecting %s' % filename.name)
|
self.txt('Inspecting %s' % filename.name)
|
||||||
@ -71,26 +89,29 @@ class BatProgress(progress.Callback):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def bat_copy(context,
|
async def copy(context,
|
||||||
base_blendfile: pathlib.Path,
|
base_blendfile: pathlib.Path,
|
||||||
project: pathlib.Path,
|
project: pathlib.Path,
|
||||||
target: pathlib.Path,
|
target: pathlib.Path,
|
||||||
exclusion_filter: str) -> typing.Tuple[pathlib.Path, typing.Set[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.
|
||||||
:returns: the path of the packed blend file, and a set of missing sources.
|
:returns: the path of the packed blend file, and a set of missing sources.
|
||||||
"""
|
"""
|
||||||
|
global _running_packer
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
wm = bpy.context.window_manager
|
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:
|
with _packer_lock:
|
||||||
packer.exclude(*exclusion_filter.split())
|
if exclusion_filter:
|
||||||
|
packer.exclude(*exclusion_filter.split())
|
||||||
|
|
||||||
packer.progress_cb = BatProgress(context)
|
packer.progress_cb = BatProgress(context)
|
||||||
|
_running_packer = packer
|
||||||
|
|
||||||
log.debug('awaiting strategise')
|
log.debug('awaiting strategise')
|
||||||
wm.flamenco_status = 'INVESTIGATING'
|
wm.flamenco_status = 'INVESTIGATING'
|
||||||
@ -103,4 +124,21 @@ async def bat_copy(context,
|
|||||||
log.debug('done')
|
log.debug('done')
|
||||||
wm.flamenco_status = 'DONE'
|
wm.flamenco_status = 'DONE'
|
||||||
|
|
||||||
|
with _packer_lock:
|
||||||
|
_running_packer = None
|
||||||
|
|
||||||
return packer.output_path, packer.missing_files
|
return packer.output_path, packer.missing_files
|
||||||
|
|
||||||
|
|
||||||
|
def abort() -> None:
|
||||||
|
"""Abort a running copy() call.
|
||||||
|
|
||||||
|
No-op when there is no running copy(). Can be called from any thread.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with _packer_lock:
|
||||||
|
if _running_packer is None:
|
||||||
|
log.debug('No running packer, ignoring call to bat_abort()')
|
||||||
|
return
|
||||||
|
log.info('Aborting running packer')
|
||||||
|
_running_packer.abort()
|
||||||
|
Reference in New Issue
Block a user