Skip to content

Commit

Permalink
Refactor images to track by index, rather than frame
Browse files Browse the repository at this point in the history
  • Loading branch information
avanwinkle committed Dec 6, 2020
1 parent 3e27159 commit f9bca6c
Showing 1 changed file with 32 additions and 16 deletions.
48 changes: 32 additions & 16 deletions mpfmc/widgets/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, mc: "MpfMc", config: dict, key: Optional[str] = None, **kwarg

self._image = None # type: ImageAsset
self._current_loop = 0
self._end_frame = -1
self._end_index = -1

# Retrieve the specified image asset to display. This widget simply
# draws a rectangle using the texture from the loaded image asset to
Expand Down Expand Up @@ -104,12 +104,15 @@ def _image_loaded(self, *args) -> None:
self.fps = self.config['fps']
self.loops = self.config['loops']
self.start_frame = self.config['start_frame']

self._end_index = self.start_frame - 1
# Always play so we can get the starting frame rendered
self.play(start_frame=self.start_frame)
self.mc.log.info("Loaded calling play for image {} with start frame {}".format(self._image.image.filename, self.start_frame))
# If auto_play is not enabled, immediately stop
if not self.config['auto_play']:
self.stop()
# if self.config['auto_play']:
self.play(start_frame=self.start_frame, auto_play=self.config['auto_play'])
# if not self.config['auto_play']:
# self.stop()
self.mc.log.info(" - loaded play complete for image {}, anim index is now {} and current frame is {}".format(self._image.image.filename, self._image.image.anim_index, self.current_frame))

def _on_texture_change(self, *args) -> None:
"""Update texture from image asset (callback when image texture changes)."""
Expand All @@ -120,9 +123,15 @@ def _on_texture_change(self, *args) -> None:
self._draw_widget()

ci = self._image.image
if self._end_frame > -1 and ci.anim_index == self._end_frame:
self._end_frame = -1

# Check if this is the end frame to stop the image. For some reason, after the image
# stops the anim_index will increment one last time, so check for end_index - 1 to prevent
# a full rollover on subsequent calls to the same end frame.
if self._end_index > -1 and ci.anim_index == self._end_index - 1:
self.mc.log.info("Image {} end index {} hit, stopping with anim index {}".format(self._image.image.filename, self._end_index, ci.anim_index))
self._end_index = -1
ci.anim_reset(False)
self.mc.log.info(" - anim_reset false is now complete, what's the anim index? {}".format(ci.anim_index))
return

# Handle animation looping (when applicable)
Expand All @@ -140,6 +149,7 @@ def prepare_for_removal(self) -> None:
self._image.references -= 1
if self._image.references == 0:
try:
self.mc.log.info("Preparing to REMOVE image {}".format(self._image.image.filename))
self._image.image.anim_reset(False)
# If the image was already unloaded from memory
except AttributeError:
Expand All @@ -158,14 +168,16 @@ def _draw_widget(self, *args):
Scale(self.scale).origin = anchor
Rectangle(pos=self.pos, size=self.size, texture=self.texture)

def play(self, start_frame: Optional[int] = 0):
def play(self, start_frame: Optional[int] = 0, auto_play: Optional[bool] = True):
"""Play the image animation (if images supports it)."""
self.mc.log.info("Playing image with start frame {}, current index returns {}".format(start_frame, self.current_frame))
if start_frame:
self.current_frame = start_frame

# pylint: disable-msg=protected-access
self._image.image._anim_index = start_frame
self._image.image.anim_reset(True)
self._image.image._anim_index = start_frame - 1

This comment has been minimized.

Copy link
@jabdoa2

jabdoa2 Feb 16, 2022

Collaborator

This line seem to have broken gifs for some users: https://groups.google.com/g/mpf-users/c/GvH_6kbE_Js

This comment has been minimized.

Copy link
@avanwinkle

avanwinkle Feb 16, 2022

Author Collaborator

An off by one error? Impossible!

I'll take a look and see if I can figure out how maths work...

This comment has been minimized.

Copy link
@jabdoa2

jabdoa2 Feb 16, 2022

Collaborator

I think his issue is that we start with the last frame if start_frame == 0.

self.mc.log.info(" - play is calling anim_reset, start frame {} current_frame {} anim_index {}".format(start_frame, self.current_frame, self._image.image.anim_index))
self._image.image.anim_reset(auto_play)

def stop(self) -> None:
"""Stop the image animation."""
Expand Down Expand Up @@ -219,30 +231,34 @@ def _get_current_frame(self) -> int:
def _set_current_frame(self, value: Union[int, float]):
if not self._image.image.anim_available or not hasattr(self._image.image.image, 'textures'):
return

self.mc.log.info("Setting current frame, value is {} and texture length is {}".format(value, len(self._image.image.image.textures)))
frame = (int(value) - 1) % len(self._image.image.image.textures)
self.mc.log.info(" - resulting calculated frame index: {}".format(frame))
if frame == self._image.image.anim_index:
self.mc.log.info(" - anim index is also {}, no action".format(frame))
return
else:
self._image.image._anim_index = frame # pylint: disable-msg=protected-access
self.mc.log.info(" - anim index is {}, setting to {} and calling play".format(self._image.image.anim_index, frame))
self._image.image._anim_index = frame # pylint: disable-msg=protected-access
self._image.image.anim_reset(True)

current_frame = AliasProperty(_get_current_frame, _set_current_frame)
'''The current frame of the animation.
'''

def _get_end_frame(self) -> int:
return self._end_frame
return self._end_index + 1

def _set_end_frame(self, value: int):
if not self._image.image.anim_available or not hasattr(self._image.image.image, 'textures'):
return
frame = (int(value) - 1) % len(self._image.image.image.textures)
self.mc.log.info("Setting end frame to {}, current frame is {}".format(frame, self._image.image.anim_index))
if frame == self._image.image.anim_index - 1:
self.mc.log.info("Setting end index to {}, current index is {}".format(frame, self._image.image.anim_index))
if frame == self._image.image.anim_index:
self.mc.log.info(" - end index matchen current index, not doing anything")
return

self._end_frame = frame
self._end_index = frame
self._image.image.anim_reset(True)

end_frame = AliasProperty(_get_end_frame, _set_end_frame)
Expand Down

0 comments on commit f9bca6c

Please sign in to comment.