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:
parent
ae570e5907
commit
7ef5e522f8
@ -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:
|
||||||
|
Reference in New Issue
Block a user