Notifications
Clear all

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

no comments, ideas, requests… does it mean that there is no any interest to this project?
well…

there is a homework for some enthusiasts.
by default the System.Windows.Forms.Button doesn’t raise the DoubleClick and MouseDoubleClick events. How to force its to do it?

Maybe using dotNetClass “System.Windows.Forms.ControlStyles”, but i don’t know
how to set StandardDoubleClick to true.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

this is not a problem. the problem is that i already showed it on this forum… what for?

This is my try with LabelControl object. Label support mouseDoubleClick event.


try(destroydialog timelineRollout3) catch()
 rollout timelineRollout3 "timelineRollout" width:780 height:24
 (
	 mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
	fn defFont fName fSize = (dotNetObject "System.Drawing.Font" fName fSize )
	fn defPaintRect dnCtrl x y w h = 
	(
		local CR = dnCtrl.ClientRectangle, CRX = CR.x, CRY = CR.y, CRW = CR.Width, CRH = CR.Height
		dotNetObject "System.Drawing.Rectangle" (CRX+x) (CRY+y) (CRW+w) (CRH+h)
	)	
	 dotnetcontrol panel "UserControl" pos:[2,2] width:776 height:20 across:3
	
	 
	 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 fontArrow = defFont "Webdings" 18
	 --local FlagsHCVC = dotNet.CombineEnums (dotNetClass "TextFormatFlags").HorizontalCenter (dotNetClass "TextFormatFlags").VerticalCenter
	local FlagsLVC = dotNet.CombineEnums (dotNetClass "TextFormatFlags").Left (dotNetClass "TextFormatFlags").VerticalCenter
	local FlagsRVC = dotNet.CombineEnums (dotNetClass "TextFormatFlags").Right (dotNetClass "TextFormatFlags").VerticalCenter
	local TxtRender = dotNetClass "TextRenderer"
	 local slidepanel
	 fn makeSlidePanel = 
	 (
		 panel.backcolor = panel.backcolor.Gray
		 
		 slidepanel = dotnetobject "UserControl"
		 slidepanel.dock = dock.Fill
 
		 slider = dotnetobject "Label"
		slider.MinimumSize = dotNetObject "System.Drawing.Size" 32 20
		 slider.backcolor = slider.backcolor.LightGray --Transparent
		fn onPaint s e =
		(
			local Graphics = e.Graphics
			x = s.Location.x
			 w = s.Width
			 
			rectTXT1 = defPaintRect s 10 0 0 0
			rectTXT2 = defPaintRect s -10 0 0 0
			rectTXT3 = defPaintRect s -10 -2 0 0
			rectTXT4 = defPaintRect s 13 -2 0 0
			if w < 70 then (str1 = str2 = "•") else (str1 = x as string ; str2 = (x + w) as string)
			TxtRender.DrawText Graphics "3" fontArrow rectTXT3 dotcolor.DimGray FlagsLVC
			TxtRender.DrawText Graphics str1 s.Font rectTXT1 dotcolor.black FlagsLVC		
			TxtRender.DrawText Graphics str2 s.Font rectTXT2 dotcolor.black FlagsRVC	
			TxtRender.DrawText Graphics "4" fontArrow rectTXT4 dotcolor.DimGray FlagsRVC
		)
		 fn onTransform s e = (s.invalidate() ; print s.Width)

		dotnet.addeventhandler slider "paint" onPaint
		 dotnet.addeventhandler slider "Move" onTransform
		 dotnet.addeventhandler slider "Resize" onTransform
		dotnet.addeventhandler slider "MouseDoubleClick" (fn dc s e = format "a=%
" e.clicks)
		 
		 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 = 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[3] == 0 then
				 (
					 tag = s.tag
					 d = e.x - tag[1]
					 tag[3] = 1
					 case s.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 = tag
				 )
				 else 
				 (
					 tag = s.tag
					 tag[3] = 0
					 s.tag = 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 

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

nice slider! i like it. the only problem that i see is a flickering of the right side when you move the left one.

(@gazybara)
Joined: 11 months ago

Posts: 0

Yep. This is main problem. Also i try with spinners but i have same problem.

try(destroydialog timelineRollout3) catch()
 rollout timelineRollout3 "timelineRollout" width:780 height:24
 (
	local slider, leftSpin, rightSpin
	 local dotcolor = dotnetclass "System.Drawing.Color"
	 local dock = dotnetclass "DockStyle"
	local BS = (dotNetClass "BorderStyle").None
	local leftHA = (dotNetClass "HorizontalAlignment").Left
	local rightHA = (dotNetClass "HorizontalAlignment").center	 
	 
	 mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
	fn DisableAccel = (enableAccelerators = false) ; fn EnableAccel = (enableAccelerators = true)
	fn defPoint x y = (dotNetObject "System.Drawing.Point" x y) 
	fn defFont fName fSize = (dotNetObject "System.Drawing.Font" fName fSize )
	fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
	fn defSpinner dnSpn w h locX locY inc dp minV maxV val side: =
	(
		dnSpn.BackColor = dnSpn.Backcolor.dimGray ; dnSpn.Bounds = defRect locX (locY+2) w h
		if side == #left then dnSpn.TextAlign = leftHA else dnSpn.TextAlign = rightHA
		rectClip = (defRect 0 0 w (h-4)) ; dnSpn.Region = dotNetObject "System.Drawing.Region" rectClip ; dnSpn.AutoSize = true
		dnSpn.DecimalPlaces = dp ; dnSpn.Minimum = minV ; dnSpn.Maximum = maxV ; dnSpn.Value = val ; dnSpn.BorderStyle = BS ; dnSpn.Increment = inc
	)	
	 dotnetcontrol panel "UserControl" pos:[2,2] width:776 height:20 across:3
	 
	 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 slidepanel
	 fn makeSlidePanel = 
	 (
		 panel.backcolor = panel.backcolor.Gray
		 
		 slidepanel = dotnetobject "UserControl"
		 slidepanel.dock = dock.Fill
 
		 slider = dotnetobject "Label"
		leftSpin = dotnetobject "NumericUpDown"
		rightSpin = dotnetobject "NumericUpDown"
		slider.Width = 100 
		 slider.height = 20
		defSpinner leftSpin 35 18 5 1 1 0 -1e5 1e5 0 side:#left
		defSpinner rightSpin 35 18 (slider.Width - 40) 1 1 0 -1e5 1e5 100 side:#right
		slider.Controls.Add(leftSpin) ; slider.Controls.Add(rightSpin)
		slider.MinimumSize = dotNetObject "System.Drawing.Size" 80 20
		 slider.backcolor = slider.backcolor.LightGray --Transparent
		fn onMove s e =
		(
			leftSpin.Value = s.Location.x
			 rightSpin.Value  = s.Location.x + s.Width
		)
		fn onResize s e = 
		(
			leftSpin.Value = s.Location.x
			 rightSpin.Value  = s.Location.x + s.Width
			rightSpin.Location = defPoint (s.Width - 40) 3
			if s.Width < 80 then leftSpin.visible = rightSpin.visible = false else leftSpin.visible = rightSpin.visible = true 
		)		
		fn onValChange s e =
		(
			case s of (
				(leftSpin): 
					(
						if rightSpin.value - s.value <= 80 then (s.value = rightSpin.value - s.value ; slider.Width = 80)
						else slider.Width = rightSpin.value - s.value					
					)
				(rightSpin):
					(
						if s.value - leftSpin.value <= 80 then (s.value = s.value - leftSpin.value ; slider.Width = 80)
						else slider.Width = s.value - leftSpin.value
					)
			)
		)
		dotnet.AddEventHandler leftSpin "ValueChanged" onValChange
		dotnet.AddEventHandler rightSpin "ValueChanged" onValChange
		dotnet.AddEventHandler leftSpin "GotFocus" DisableAccel
		dotnet.AddEventHandler leftSpin "LostFocus" EnableAccel
		dotnet.AddEventHandler rightSpin "GotFocus" DisableAccel
		dotnet.AddEventHandler rightSpin "LostFocus" EnableAccel		
		 dotnet.addeventhandler slider "Move" onMove
		 dotnet.addeventhandler slider "Resize" onResize
		dotnet.addeventhandler slider "MouseDoubleClick" (fn dc s e = format "a=%
" e.clicks)
		  
		 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 = 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[3] == 0 then
				 (
					 tag = s.tag
					 d = e.x - tag[1]
					 tag[3] = 1
					 case s.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 = tag
				 )
				 else 
				 (
					 tag = s.tag
					 tag[3] = 0
					 s.tag = 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 

I think that scaling of a label control causes the flickering problem of the right side.

 MZ1

Nice job Thanks!

sorry guys. i was very busy all last days to continue the project. but i will…
the easy question –

what general events might change the animationrange?

 MZ1

I think:
-Open,reset max file
-Import FBX files maybe
-Click&drag timeline with Ctrl+Alt
-Changing time configuration.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0
  • open file (yes)
    #filePostOpen
  • resetfile (yes)
    #systemPostReset
  • import FBX (no) (i don’t remember any import plugin that changes time range)
  • manual time range change (yes)
    #animationRangeChange
  • changing time configuration (yes)
    #animationRangeChange

also we will need some more for initialization:

  • system startup
    #postSystemStartup
  • new file
    #systemPostNew
 lo1

I assume the hard question is how to catch all of those events

You might call me a one trick pony, but I think it might be easier to just attach yourself to the wndproc of the max timeline and check the animationrange on each WM_PAINT message.

Either that or to use a timer, but implementing a timer to catch an event is like raising a white flag – you should only do it when all hope is lost.

 MZ1

#animationRangeChange callback!

1 Reply
 lo1
(@lo1)
Joined: 11 months ago

Posts: 0

Oh heh, I was sure that existed but couldn’t find it in the list just now so I thought maybe I dreamed it. Yeah, definitely THAT and not the crap I said

 MZ1

yes,i hate timers especially max timer.
I think finally i can make sound editing timeline in 3dsmax:)

Page 4 / 8