Notifications
Clear all

[Closed] Timeslider key snap

I’m thinking of making a tool that will make the timeslider snap to keys on the trackbar when shift is held while dragging. This works great in AEF and would be nice to have in Max as well.

Maybe with an on time-change-event that will check if shift is pressed, if so move the timeslider to the closest key. Direction of slide will be determined by the storing the a previous current time.

Does anyone have a smarter ways of doing it? A nice extra optional feature would be if the scene did not update until shift is released so you can easily pick your key without a heavy scene slowing things down.

(and aware of the next-prev key toggle but that isn’t always the most efficient way)

4 Replies
1 Reply
(@dangrover)
Joined: 11 months ago

Posts: 0

This sounds very interesting and useful! How would this deal with the mousepointer still being where it was before, though? I can see the timeslider moving to the key’s location and then immediately jumping back to where the mouse pointer is? Perhaps you’ll need to move the pointer too?

Yeah, that is a problem, it will be quite jumpy to operate. I’m having some time next Friday to spent so time on this, I hope someone will have a better idea by then

Here is a ruff first version… run the script once after which you can hold the alt-key while dragging the timeslider to make is snap to keys.

There is one catch with room for improvement… to calculate the new mouse position I had to know the length of the trackbar in pixels. I used the viewpost size for this as a yard stick. In a default quad layout out it’s:

trackbarsize= 2*viewportsize+8px middle border - 2*50px on each side

But you can only get that info for the active viewport so I assumed there are 4 equal sized viewports or one maximized one.

The script with a few comments:

unregisterTimeCallback tracksnap_fn
  
  --globals so they can be reused between different callback events.
  
  global tracksnap_p= point2 0 0
  global tracksnap_op= point2 0 0
  global tracksnap_t=0
  global tracksnap_ot=0
  global tracksnap_key = 0
  
  
  fn tracksnap_fn = (
  	
  		--get mouse position
  		mousepos = dotnetclass "System.Windows.Forms.Cursor"
  	
  		-- store current and old mouse cursor position in global vars.
  		  tracksnap_op=tracksnap_p  
  		 tracksnap_p = mousepos.Position
  	
  	
  		-- very  simple key selection, should be smarter
  	
  		tr1=5  -- snap treshold distance
  		tr2=15  -- release distance
  		kn=trackbar.getNextKeyTime()
  		kp=trackbar.getPreviousKeyTime()
  	
  		if (kn==undefined) do ( kn=0 )
  		if (kp==undefined) do ( kp=0 )
  	
  		if (tracksnap_key==undefined)  do ( tracksnap_key=0)
  	 
  		
  		if (abs(tracksnap_key-sliderTime)>tr2) do
  		(
  			tracksnap_key=0
  			if (abs(kn-sliderTime)<tr1) do ( tracksnap_key=kn )
  			if (abs(kp-sliderTime)<tr1) do ( tracksnap_key=kp )
  		)
  		 
  		
  		   
  		kb=dotNetClass "system.windows.forms.control"
   
  		if (tracksnap_key>0  AND  tracksnap_key!=sliderTime AND  kb.modifierKeys==kb.modifierKeys.alt ) then
  		(
   
    -- get pixel spacing of keyframes on trackbar
   -- ** this assumes 1 maximized viewport or 4 equal sized viewports**
  	
  			
  			vs=getViewSize() 
  			 if (viewport.numViews==1) then
  			(
  				tb_width=vs.x+108;  --1*viewport size + border + 2x50 = trackviewsize in pixels
  			) else
  			(
  				tb_width=vs.x*2+108;   --2*viewport size + border + 2x50 = trackviewsize in pixels
  			)
  		
  			keyspace=tb_width/((animationRange.end-animationRange.start) as integer )*TicksPerFrame   -- calculate keyframe pixel spacing on trackbar. 
  			
  				-- set slider to key-time
  			timedistance=tracksnap_key-sliderTime  
  			sliderTime = tracksnap_key
  			
  			 tx = mousepos.Position
  			
  			tx.x += ((tx.x+timedistance*keyspace)-tx.x)/10   --dampen occlation due to delay is slider vs mouseposition
  			
  			mousepos.Position = dotnetobject "System.Drawing.Point" tx.x tracksnap_p.y  -- move the mouse to new position
  		
  		 ) else (
  			tracksnap_key=0
  		)
     
  )
  	
  registerTimeCallback tracksnap_fn

the only solution that i see is to use ‘on-fly’ assembly (or compiled .dll) that implements native window or mouse hooker.
to realize the idea we have not just to catch events (time changed, mouse move, any ever…) but also be able to suppress some messages.