Notifications
Clear all

[Closed] How to make your own Timeline (NOT ENCRYPTED)

i said it’s easy

 MZ1

Denis,generally I use tag a lot,so I think i have to replace tags in your code with structured tags.what you think?

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

are you talking about Time Tags?
i don’t deal with tags in my code… at least yet.

 MZ1

I mean button tag,something like this:

struct DNBtnTag
(
  MyEvents,Type,GrpName,ImageFileName,SoundFileName
)

slider = dotnetobject "Button"
slider.tag = dotNetMxsValue (DNBtnTag())
 MZ1
 try(destroydialog timelineRollout3) catch()
 rollout timelineRollout3 "timelineRollout" width:780 height:24
 (
 	mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
 	dotnetcontrol panel "UserControl" pos:[2,2] width:776 height:20 across:3
 	
	struct DNBtnTag
	(
	  MyTag,Type,GrpName,ImageFileName,SoundFileName
	)

 	on panel Paint s e do if s.tag != off do
 	(
 		s.tag = off
 		s.Refresh()
 		s.tag = on
 	)	
 	on timelineRollout resized size do panel.Width = size.x
 	
 	local dotcolor = dotnetclass "System.Drawing.Color"
 	local dock = dotnetclass "DockStyle"
 	
 	local slidepanel
 	fn makeSlidePanel = 
 	(
 		panel.backcolor = panel.backcolor.Gray
 		
 		slidepanel = dotnetobject "UserControl"
 		slidepanel.dock = dock.Fill
 
 		slider = dotnetobject "Button"
 		slider.backcolor = slider.backcolor.Transparent
		slider.tag = dotNetMxsValue (timelineRollout3.DNBtnTag())
 
 		fn onTransform s e = 
 		(
 			x = s.Location.x
 			w = s.Width
 			str = x as string + "   " + (x + w) as string
 			if ((dotnetclass "TextRenderer").MeasureText str s.Font).width > s.Width-8 do str = ""
 			s.Text = str
 		)
 		dotnet.addeventhandler slider "Move" onTransform
 		dotnet.addeventhandler slider "Resize" onTransform
 		
 		slider.Width = 100 
 		slider.height = 20
 		
 		slidepanel.controls.addrange #(slider)
 		panel.controls.addrange #(slidepanel, sr_sp, sa_sp, er_sp, ea_sp)
 
 		fn onMouseDown s e = 
 		(
 			c = dotnetclass "System.Windows.Forms.Cursors"
 			s.tag.value.MyTag = case of
 			(
 				(e.x < 5): 
 				(
 					s.Cursor.Current = c.SizeWE
 					#(e.x,0,0)
 				)
 				(e.x > s.width - 5): 
 				(
 					s.Cursor.Current = c.SizeWE
 					#(e.x,2,0)
 				)
 				default: 
 				(
 					s.Cursor.Current = c.Default
 					#(e.x,1,0)
 				)
 			)
 		)
 		dotnet.addeventhandler slider "MouseDown" onMouseDown
 		fn onMouseMove s e = 
 		(
 			case e.Button of
 			(
 				(e.Button.None):
 				(
 					c = dotnetclass "System.Windows.Forms.Cursors"
 					s.Cursor.Current = if (e.x < 5 or e.x > s.width-5) then c.SizeWE else c.Default
 				)
 				(e.Button.Left): if s.tag.value.MyTag[3] == 0 then
 				(
 					tag = s.tag.value.MyTag
 					d = e.x - tag[1]
 					tag[3] = 1
 					case tag[2] of
 					(
 						0:
 						(
 							if d  >= 0 then
 							(
 								w = amax 20 (s.width - d)
 								dx = s.location.x + (s.width - w)
 							)
 							else
 							(
 								dx = amax 0 (s.location.x + d)
 								w = amax 20 (s.width + (s.location.x - dx))
 							)
 							s.bounds = dotnetobject "system.drawing.rectangle" dx s.location.y w s.height
 						)
 						2:
 						(
 							w = amin (s.parent.width - s.location.x) (amax 20 (s.width + d))
 							tag[1] += w - s.width
 							s.width = w
 						)
 						default:
 						(
 							x = amin (s.parent.width - s.width) (amax 0 (s.location.x + d))
 							s.location.x = x
 						)
 					)
 					s.tag.value.MyTag = tag
 				)
 				else 
 				(
 					tag = s.tag.value.MyTag
 					tag[3] = 0
 					s.tag.value.MyTag = tag
 				)
 			)
 		)
 		dotnet.addeventhandler slider "MouseMove" onMouseMove
 		
 		setLifetimeControl #(slider, slidepanel)
 		slidepanel
 	)
 	
 	on timelineRollout3 open do slidepanel = makeSlidePanel()
 )
 createdialog timelineRollout3 style:#(#style_titlebar, #style_sysmenu, #style_resizing) lockWidth:on lockHeight:on 

Denis code with structured slider tags. structured tags help us to add more than one tag to a button.

continuing the project i will show how to do the things without any tags, and explain why in our case it’s an overwork. recently i try to avoid the passing max data as dotnetmxsvalue to dotnet events.

the name for this project is The Trackbar Navigator. the question is – has any timerange change to be undoable? i can do it. and i will show how to do it. but… i see the reason to organize the special UNDO stack for timerange changes. does it make sense?

1 Reply
 MZ1
(@mz1)
Joined: 10 months ago

Posts: 0

Making UNDO stack for training is very interesting for me so i can use it in other cases.
but about timerange, I think its not very important for users.

 eek

FBX importer can adjust the time range to the imported data.

http://download.autodesk.com/us/fbx/20112/3dsmax/_index.html

Fill Timeline

Activate this option when you want to update the application Timeline by the animation range in the incoming FBX file. The term “Animation range” refers to the first and last keys of animation contained in the file.

2 Replies
 MZ1
(@mz1)
Joined: 10 months ago

Posts: 0

Either biped files.

(@denist)
Joined: 10 months ago

Posts: 0

good catch!
these two events can change animationrange, but we will not use any extra callback to handle it.
the #animationRangeChange works right in both cases.

 lo1

Can you explain why you think time range changes need an undo stack of their own?

ok… let’s bind time change events and our controls.
first of all we need to simplify the code to leave only necessary parts to be able play with ideas and easy debug the code.

so here is what i have:


  try(destroydialog trackbarNavigatorLight) catch()
  rollout trackbarNavigatorLight "Trackbar Navigator" width:327 height:24
  (
  	spinner sa_sp fieldwidth:50 range:[-1e9,1e9,0] type:#integer pos:[0,4]
  	spinner sr_sp fieldwidth:50 range:[-1e9,1e9,0] type:#integer pos:[61,4]
  	
  	spinner er_sp fieldwidth:50 range:[-1e9,1e9,100] type:#integer pos:[200,4]
  	spinner ea_sp fieldwidth:50 range:[-1e9,1e9,1000] type:#integer pos:[261,4]
  
  	fn update event:#custom =
  	(
  		format "event:% range:%
" event animationrange
  	)
  	
  	on trackbarNavigatorLight close do 
  	(
  		callbacks.removescripts id:#trackbarNavigatorLight
  	)
  	on trackbarNavigatorLight open do 
  	(
  		callbacks.removescripts id:#trackbarNavigatorLight
  		call = "if trackbarNavigatorLight != undefined and trackbarNavigatorLight.open do trackbarNavigatorLight.update event:"
  		callbacks.addscript #animationRangeChange (call + "#range") id:#trackbarNavigatorLight
  		callbacks.addscript #filePostOpen (call + "#open") id:#trackbarNavigatorLight
  		callbacks.addscript #systemPostNew (call + "#new") id:#trackbarNavigatorLight
  		callbacks.addscript #systemPostReset (call + "#reset") id:#trackbarNavigatorLight
  		callbacks.addscript #postSystemStartup (call + "#start") id:#trackbarNavigatorLight
  		
  		update()
  	)
  )
  createdialog trackbarNavigatorLight style:#(#style_titlebar, #style_sysmenu)
  

now we can check all range change related events… add new one if we need or remove some another if it duplicates the functionality.
as you see i set the default event as #custom. we will use this event when we start using spinners to change the range ourselves.

do you see any problem in this setup?

 MZ1

seems everything work fine, I like your way to put “trackbarNavigatorLight conditions” in execution string.

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

no, it doesn’t. as you see the system raises the #animationRangeChange event multiple times even an animation range is the same. so we have to keep this in mind…

Page 5 / 8