Skip to content
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

[usdview] Split _updateOnFrameChange logic. Simplified the FrameSlider class. #770

Merged
merged 4 commits into from
Apr 25, 2019

Conversation

ianlawson
Copy link
Contributor

The three PR's I've submitted tonight will allow me to submit a final PR for the current frame feature once they have been merged into dev!

Description of Change(s)

  • Split _updateOnFrameChange into _updateOnFrameChange and _updateOnFrameChangeFinish

    • Allows us to differentiate between what we want to update whilst the frame is changing (playing/scrubbing) and what we want to update when the frame change has finished.
    • Removes the need for the refreshUI variable.
  • Simplified the FrameSlider class

    • Reverted to using Qt's logic for scrubbing/tracking which improves accuracy and performance.
    • In doing so, fixed a minor bug that was causing extra UI updates whilst scrubbing.
      • If the action of scrubbing happens towards the start or end, isSliderDown returns False rather than True.
    • Only using the class to override necessary mouse events.
    • Removed unused _playbackFrameIndex variable.

@spiffmon
Copy link
Member

On the second commit that rewrites the FrameSlider class... it looks like you have completely removed the "update when pausing scrubbing" behavior that kicks in when "Update on scrubbing" is turned off. I think we like that feature - can you work it back in? Thanks!

@ianlawson
Copy link
Contributor Author

Thanks for your comments - they've been addressed and the PR has been updated!

@jilliene
Copy link

Filed as internal issue #USD-5096



def _playClicked(self):
if self._ui.playButton.isChecked():
# Enable tracking whilst playing
self._ui.frameSlider.setTracking(True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'll discover why later, but why do we want tracking on during playback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to mirror the behavior that was already there! And...

We want mouse tracking to be enabled as the user might choose to click somewhere on the slider as it is playing. We want that new play point to be respected regardless of whether the frame scrub option is enabled/disabled!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that makes sense - thanks, @ianlawson !

value = self._ui.frameSlider.value() + 1
if value > self._ui.frameSlider.maximum():
value = self._ui.frameSlider.minimum()
self._ui.frameSlider.setValue(value)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the goal here (which I'm slowly coming around to) is to simplify the slider widget/controller, and put logic in the appController, then shouldn't we be implementing advance/retreat in terms of the appController concepts of currentFrame and stepSize, and then just having the slider update in response to a signal that frame has changed? Slider values should correspond exactly to indices in _timeSamples, right?

For reference, I've been hoping that at some point we'll migrate all of the time/playback-related controller logic into a TransportController class to make transport be a more modular piece.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some really good points again here - definitely can make these changes!

I've been taking a closer look and found some more inconsistencies with the advance/retreat frame, especially when looking at hotkey presses and active focus (between the slider and the window).

I'd like to address all of this in another pull request if possible, what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good to me, @ianlawson !

super(FrameSlider, self).mousePressEvent(event)
# Set the slider down property.
# This tells the slider to obey the tracking state.
self.setSliderDown(True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you want to loft up logic from the base class here rather than just delegating to it? Same comment for mouseReleaseEvent()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I don't quite follow! What do you mean by just delegating to it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as it was doing previously, calling super(FrameSlider, self).mousePressEvent(event)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure but what logic/functionality do you think we can remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is a good shout. I've taken another look at the logic in QSlider and I've simplified the implementation in our subclass.

The perfect solution here would be to create a QProxyStyle. Then we could modify the value of QStyle::SH_Slider_AbsoluteSetButtons (which is currently set to just the middle mouse button) to include the left mouse button. However, this is only available in PyQt >= 5.5!

)
# Set the slider value.
self.setSliderPosition(value)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logical block is shared with mousePressEvent() - factor it out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to do this originally, but I couldn't think of a suitable name for the function.

I'll refactor the logic out into setSliderPositionFromEvent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me!

@spiffmon
Copy link
Member

spiffmon commented Mar 12, 2019 via email

Copy link
Member

@spiffmon spiffmon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ready to go, to me, @ianlawson - thanks so much for doing this!

@spiffmon
Copy link
Member

Hi @ianlawson . After @c64kernal pulled the change into our tree for final review, I did some manual testing, and discovered a couple things:

  1. In Pyside (and the Qt.py adapter), QStyle lives in QtWidgets, not QtGui . I fixed this locally to proceed with testing, and would have just committed that and proceeded, but
  2. It introduces a regression that is a little tricky to repro, but happened to me often enough. It happens when you click-n-hold on the timeline, away from the slider-head. Without "Redraw On Frame Scrub" enabled, what you get sometimes is that clicking just has no effect - the playhead is not summoned to your mouse, and dragging produces no movement. With "Redraw On Frame Scrub" enabled, the playhead is always summoned, but sometimes it stops off-center from your cursor - sometimes completely outside of your cursor, and when this happens, you can no longer scrub, i.e. mouse movement produces no playhead movement.

I think it may have something to do with rounding and something not getting updated correctly, but I couldn't pick out an obvious line of code in five minutes. This is easiest for me to reproduce if I make the window really wide, so that the timeline is long and there's lots more pixels than there are frames... which is what leads me to think it has something to do with rounding/mapping. I was able to repro with both a heavier animation that only achieves 9fps playback, but also with a light one that gets over 200 fps - it reprod more easily with the heavier anim, but that may have been also because it only had 47 frames of anim, whereas the light one had 100 frames.

Let me know if you have trouble reproing, I can probably share either or both assets with you - they are both synthetic.

On the plus side, this change fixes a regression that got introduced sometime in the last little while: after summoning the playhead on the slider, the arrow keys would no longer actually cause the scene to update until you hit the first or last frame!

I also discovered a long-standing bug that I'll file that after summoning the playhead a single time, the arrow keys will no longer loop from end to beginning or beginning to end - playhead just gets stuck at beginning or end.

@ianlawson
Copy link
Contributor Author

I also discovered a long-standing bug that I'll file that after summoning the playhead a single time, the arrow keys will no longer loop from end to beginning or beginning to end - playhead just gets stuck at beginning or end.

I also noticed this - this is what I meant with the inconsistencies in advance/retreat frames in my earlier comment! Feel free to assign that ticket to me as I was planning on putting in a fix when I get some time.

@spiffmon
Copy link
Member

@ianlawson - if you could, would you also rebase to current dev, which should now have your earlier changes?

Thanks!

@ianlawson
Copy link
Contributor Author

Yep - on it, do you also want me to squash the extra commits?

@spiffmon
Copy link
Member

spiffmon commented Mar 14, 2019 via email

@ianlawson
Copy link
Contributor Author

Hey @spiffmon!

Anything left for me to do here or are we okay to merge? I'm keen to get the final PR into review for the current frame behavior! 😁

Thanks!

@ianlawson
Copy link
Contributor Author

Ah of course - sorry, I'll look into that today!

@ianlawson
Copy link
Contributor Author

Managed to reproduce both of your issues - thanks again for spotting them!

When Redraw On Frame Scrub is disabled, the 'no-update' issue looks to appear when the mouse click event occurs slightly above or below the main visible slider area.

  • This is definitely a regression, I'll get this fixed!

When Redraw On Frame Scrub is enabled, the 'off-center' issue occurs when we have a small number of time samples on the slider. The slider finds the closest time sample to where the mouse press event occurred and jumps to it's respective index.

  • This doesn't seem like a regression, however...
  • I agree that if you hold the mouse press you should be able to continue to move the control around and scrub, I'll get this fixed.
  • I tested this case without my changes (on the latest dev) and the behavior is extremely erratic, it looks to jump around (either side of the mouse press event) the timeline as your scrub.

Let me know what you think!

@spiffmon
Copy link
Member

spiffmon commented Mar 27, 2019 via email

@ianlawson
Copy link
Contributor Author

Yep of course, I'll get this all fixed up and post an update later today!

@ianlawson
Copy link
Contributor Author

ianlawson commented Apr 3, 2019

@spiffmon - what are your thoughts? 😄

@spiffmon
Copy link
Member

spiffmon commented Apr 8, 2019

Hi @ianlawson - sorry I either hadn't gotten or missed the notification that you'd pushed new changes up! Am focused on doc improvements for 19.05 till its release, but will have a look after it gets pushed (hopefully mid-week). Thanks!

@ianlawson
Copy link
Contributor Author

No worries at all!

Actually, just took a quick look. :-) If we're synthesizing a MM press, do we also need to synthesize a MM release when LM is released?

Nope, we're fine on that front. Only the mousePressEvent is concerned with what button is pressed!

Ian Lawson added 4 commits April 11, 2019 11:34
…pdateOnFrameChangeFinish

* Allows us to differentiate between what we want to update whilst the frame is changing (playing/scrubbing) and what we want to update when the frame change has finished.
* Removes the need for the refreshUI variable.
* Reverted to using Qt's logic for scrubbing/tracking which improves accuracy and performance.
* In doing so, fixed a minor bug that was causing extra UI updates whilst scrubbing.
  * If the action of scrubbing happens towards the start or end, isSliderDown returns False rather than True.
* Only using the class to override necessary mouse events.
* Removed unused _playbackFrameIndex variable.
* Changed _updateOnFrameChangeFinish to _updateGUIForFrameChange
* Added mousePauseTimer to FrameSlider class
* Simplified FrameSlider class, using more functionality from the base class.
* Fixed minor bug in the state of the Play Button.
  * If you change the `Step Size` value whilst playing, it sets the internal state of the play button to False. Which means you have to hit the button twice to stop the playback.
…ddleButton presses to allow the FrameSlider to be manipulated correctly.
@ianlawson ianlawson force-pushed the dev_frame_slider branch 3 times, most recently from 3575c2f to fc4c1cd Compare April 12, 2019 03:23
@spiffmon
Copy link
Member

Huzzah! Testing went well - I had to change the module from QtWidgets to QtGui for QMouseEvent, and we can just do that fixup internally and accept. I think we are good to go, @ianlawson !

@ianlawson
Copy link
Contributor Author

Awesome - once that's merged I'll get the PR in for the --curentframe behaviour!

@pixar-oss pixar-oss merged commit fc4c1cd into PixarAnimationStudios:dev Apr 25, 2019
pixar-oss added a commit that referenced this pull request Apr 25, 2019
 [usdview] Split _updateOnFrameChange logic. Simplified the FrameSlider class.

(Internal change: 1959450)
@ianlawson ianlawson deleted the dev_frame_slider branch April 25, 2019 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants