-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Synced slider with frame index rather than active keyframe #99
Conversation
…. Frame sequence changed to contain the first keyframe.
Codecov Report
@@ Coverage Diff @@
## main #99 +/- ##
==========================================
+ Coverage 90.08% 90.59% +0.51%
==========================================
Files 20 20
Lines 827 851 +24
==========================================
+ Hits 745 771 +26
+ Misses 82 80 -2
Continue to review full report at Codecov.
|
…sync with slider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @Fifourche - I love the idea but am not 100% on the implementation, especially the generation of the whole list to obtain the required index
Could you explain the purpose of the extra code you added into the cache too? 🙂
def _on_frame_index_changed(self, event=None): | ||
frame_index = event.value | ||
self.animationSlider.blockSignals(True) | ||
self.animationSlider.setValue(frame_index) | ||
self.animationSlider.blockSignals(False) | ||
|
||
def _on_active_keyframe_changed(self, event): | ||
active_keyframe = event.value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just making sure I understand what's going on here
frame_index is linked to the frame in the whole animation, active keyframe is linked to the key-frame in the key-frames list?
If I've got that right, would you mind adding some docstrings to these methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and yes ! will do :)
napari_animation/animation.py
Outdated
self.__set_frame_index = 0 | ||
self.events = EmitterGroup(source=self, _set_frame_index=None) | ||
|
||
@property | ||
def _set_frame_index(self): | ||
return self.__set_frame_index | ||
|
||
@_set_frame_index.setter | ||
def _set_frame_index(self, frame_index): | ||
if frame_index != self._set_frame_index: | ||
self.__set_frame_index = frame_index | ||
self.events._set_frame_index(value=frame_index) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about renaming this to _frame_index
? I feel like it doesn't make sense to 'get' a _set_frame_index
property
napari_animation/animation.py
Outdated
@@ -208,6 +230,12 @@ def animate( | |||
if not save_as_folder: | |||
writer.close() | |||
|
|||
def _keyframe_frame_index(self, keyframe): | |||
n_frames = len(self._frames) | |||
kf1_list = [self._frames._frame_index[n][0] for n in range(n_frames)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it feels quite heavy to generate the whole list of keyframes to get an index... maybe we can find a better way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm switching back to something I wrote on a previous version. I hope it feels lighter ! :)
napari_animation/frame_sequence.py
Outdated
else: | ||
f = 0 | ||
if len(self._key_frames) == 1: | ||
kf1 = self._key_frames[0] | ||
else: | ||
for kf0, kf1 in pairwise(self._key_frames): | ||
for s in range(kf1.steps): | ||
fraction = s / kf1.steps | ||
self._frame_index[f] = (kf0, kf1, fraction) | ||
f += 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you remove the outer else here to make the whole block less nested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still kept an elif
, for probably a better readability !
napari_animation/frame_sequence.py
Outdated
else: | ||
f = 0 | ||
if len(self._key_frames) == 1: | ||
kf1 = self._key_frames[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand the purpose of this little section, could you explain it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, if there was only one keyframe, it was not added as a frame and _frames was empty. I just added this here so _frames would be empty only when there are no keyframes at all.
Okay cool! Maybe we could refactor this logic into a ‘has_frames’ properly rather than adding it here?
|
Wasn't sure of what you meant, as it's mostly the number of key frames that is needed there. Would you still go for an attribute for this ?
|
Hey :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @Fifourche - this is looking really nice now! Thanks for your patience with my reviewing here, let's get this in!
steps_to_keyframe = [ | ||
kf.steps for kf in self.key_frames[1 : keyframe_index + 1] | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is looking much nicer! 🙂
@property | ||
def _current_index(self): | ||
return self.__current_index | ||
|
||
@_current_index.setter | ||
def _current_index(self, frame_index): | ||
if frame_index != self._frame_index: | ||
self.__current_index = frame_index | ||
self.events._current_index(value=frame_index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like having this directly on the FrameSequence
A PR to link the
AnimationSlider
with the frame index being set.Before it was synced with the change of
key_frames.selection.active
, and now with the signal of anEmitter
:frame_index
, added toAnimation
. This way, if we useset_movie_frame_index
, it'll put the slider at the frame's position and not at the closest key frame.For some context, the idea I had was to sync the slider with a frame_index signal to prepare the way for a "previewer" capability. The preview would be launched via a method of
Animation
, or a button next to the slider.