Attract thumbs: only use middle frame when current frame not on shot

This now also applies when rendering multiple shot thumbnails.
This commit is contained in:
Sybren A. Stüvel 2016-11-04 15:45:23 +01:00
parent ae570e5907
commit 7ef5e522f8

View File

@ -644,9 +644,13 @@ class ATTRACT_OT_make_shot_thumbnail(AttractOperatorMixin,
@contextlib.contextmanager @contextlib.contextmanager
def temporary_current_frame(self, context): def temporary_current_frame(self, context):
"""Allows the context to set the scene current frame, restores it on exit.
Yields the initial current frame, so it can be used for reference in the context.
"""
current_frame = context.scene.frame_current current_frame = context.scene.frame_current
try: try:
yield yield current_frame
finally: finally:
context.scene.frame_current = current_frame context.scene.frame_current = current_frame
@ -654,19 +658,25 @@ class ATTRACT_OT_make_shot_thumbnail(AttractOperatorMixin,
nr_of_strips = len(context.selected_sequences) nr_of_strips = len(context.selected_sequences)
do_multishot = nr_of_strips > 1 do_multishot = nr_of_strips > 1
with self.temporary_current_frame(context): with self.temporary_current_frame(context) as original_curframe:
# The multishot and singleshot branches do pretty much the same thing,
# but report differently to the user.
if do_multishot: if do_multishot:
context.window_manager.progress_begin(0, nr_of_strips) context.window_manager.progress_begin(0, nr_of_strips)
try: try:
self.report({'INFO'}, 'Rendering thumbnails for %i selected shots.' % self.report({'INFO'}, 'Rendering thumbnails for %i selected shots.' %
nr_of_strips) nr_of_strips)
for idx, strip in enumerate(context.selected_sequences): strips = sorted(context.selected_sequences, key=self.by_frame)
for idx, strip in enumerate(strips):
context.window_manager.progress_update(idx) context.window_manager.progress_update(idx)
# For multi-shot we can't just use the current frame (each thumb would be
# identical), so instead we use the middle frame. The first/last frames # Pick the middle frame, except for the strip the original current frame
# cannot be reliably used due to transitions with other shots. # marker was over.
self.set_middle_frame(context, strip) if not self.strip_contains(strip, original_curframe):
self.set_middle_frame(context, strip)
else:
context.scene.frame_set(original_curframe)
await self.thumbnail_strip(context, strip) await self.thumbnail_strip(context, strip)
if self._state == 'QUIT': if self._state == 'QUIT':
@ -677,7 +687,7 @@ class ATTRACT_OT_make_shot_thumbnail(AttractOperatorMixin,
else: else:
strip = active_strip(context) strip = active_strip(context)
if not strip.frame_final_start <= context.scene.frame_current <= strip.frame_final_end: if not self.strip_contains(strip, original_curframe):
self.report({'WARNING'}, 'Rendering middle frame as thumbnail for active shot.') self.report({'WARNING'}, 'Rendering middle frame as thumbnail for active shot.')
self.set_middle_frame(context, strip) self.set_middle_frame(context, strip)
else: else:
@ -697,12 +707,27 @@ class ATTRACT_OT_make_shot_thumbnail(AttractOperatorMixin,
self.report({'INFO'}, 'Thumbnail uploaded to Attract') self.report({'INFO'}, 'Thumbnail uploaded to Attract')
self.quit() self.quit()
def set_middle_frame(self, context, strip): @staticmethod
def strip_contains(strip, framenr: int) -> bool:
"""Returns True iff the strip covers the given frame number"""
return strip.frame_final_start <= framenr <= strip.frame_final_end
@staticmethod
def set_middle_frame(context, strip):
"""Sets the current frame to the middle frame of the strip.""" """Sets the current frame to the middle frame of the strip."""
middle = round((strip.frame_final_start + strip.frame_final_end) / 2) middle = round((strip.frame_final_start + strip.frame_final_end) / 2)
context.scene.frame_set(middle) context.scene.frame_set(middle)
@staticmethod
def by_frame(sequence_strip) -> int:
"""Returns the start frame number of the sequence strip.
This can be used for sorting strips by time.
"""
return sequence_strip.frame_final_start
async def thumbnail_strip(self, context, strip): async def thumbnail_strip(self, context, strip):
atc_object_id = getattr(strip, 'atc_object_id', None) atc_object_id = getattr(strip, 'atc_object_id', None)
if not atc_object_id: if not atc_object_id: