local frameDots,frameGaps = {},{}

local function pprect(mode,x,y,w,h,r)
	gfx.rectangle(mode,mf(x),mf(y),mf(w),mf(h),r)
end
local function drawClip(panel,clip)
	local r = clip
	if r.frames.last and r.frames.first  and r.layers.last and r.layers.first then 
		
		if panel.scrubbing and not clip.isClip then 
			r.f1,r.f2 = math.min(r.frames.last,r.frames.first),math.max(r.frames.last,r.frames.first)
			r.l1,r.l2 = math.min(r.layers.last,r.layers.first),math.max(r.layers.last,r.layers.first)
			r.f3 = r.f3 or 0
		end

		local fw = r.f2-r.f1+1
		local lh = r.l2-r.l1+1
		r.fw = fw 
		r.lh = lh
		local k = editor.getKeyFrame(panel,r.l1,r.f1)
		local a = editor.getAbsoluteFrame(panel,r.l1,k)
		if fw==1 and lh ==1 and a~=r.f1 and not config.flashFrames then return end
		local mul=0.6

		r.k1,r.k2 = editor.getKeyFrame(panel,r.l1,r.f1),editor.getKeyFrame(panel,r.l1,r.f2)
		r.k1 = r.k1 + (editor.getAbsoluteFrame(panel,r.l1,r.k1)==r.f1 and 0 or 1)

		local aframe = editor.getAbsoluteFrame(panel,r.l1,r.k1)
		if not aframe then return end
		r.left =  r.left or aframe-r.f1+1

		if not panel.layers[r.l2].element then 
			return 
		end

		r.rect = {x=(r.f1-1)*panel.frameWidth+panel.framesX, y=panel.layers[r.l2].element.y+1, w=fw*panel.frameWidth, h=lh*panel.row-4 }
		r.canDrag = (mouseIn(lume.merge(r.rect,{w=(fw+(r.f3 or 0))*panel.frameWidth})))
		
		if panel.draggingFrame then 
			r.canDrag = panel.activeClip ==r
		else 
			r.right = r.f2+r.f3-editor.getAbsoluteFrame(panel,r.l1,r.k2)
			r.max = r.f2-editor.getAbsoluteFrame(panel,r.l1,r.k2)
		end

		mul=r.canDrag and 1 or 0.6
		
		local corner = editor.debug.timelineZoom>0.2 and 2 or 0

		gfx.setColor(r.isClip and 1 or 0.6,0.7,1,0.1*mul)
		gfx.rectangle("fill", r.rect.x,r.rect.y,r.rect.w,r.rect.h,corner )
		
		if r.isClip then
			local w = math.max(6,panel.frameWidth/2)
			local lx=r.rect.x+r.rect.w
			if r.f3 and r.f3>0 then 
				local loops = mu(r.f3/fw)
				local img = getImage("reload")
				if LOVE then  img:setFilter("linear","linear") end
				for i=1, loops,1 do 
					gfx.setColor(1,1,1,0.2)
					gfx.draw(img,lx+1,r.rect.y+8,pi/2+pi/4,0.12,0.12,64,64)
					gfx.setColor(1,0.7,1,0.06*mul)
					gfx.rectangle("fill", lx,r.rect.y,i==loops and (r.f3-((loops-1)*fw))*panel.frameWidth or r.rect.w,r.rect.h,2 )
					lx = i==loops and lx+(r.f3-((loops-1)*fw))*panel.frameWidth or lx + r.rect.w
				end
			end
			
			if r.canDrag then 
				gfx.setColor(0.6,0.7,1,0.8*mul)
				gfx.rectangle("fill", 	lx-w,r.rect.y,w,r.rect.h/2 ,corner)
				r.canLoop = mouseIn({x=lx-w,y=r.rect.y,w=w,h=r.rect.h/2})

				if r.canLoop and not mouse.down.L  then editor.setToolTip("Loop Clip")end

				-- gfx.setColor(0.6,1,1,0.8*mul)
				-- pprect("fill", lx-w,r.rect.y+r.rect.h/2,w,r.rect.h/2 ,2)
			end

		end

		if not r.isClip then 
			gfx.setColor(0,0,0,0.4)
			gfx.rectangle("fill", r.rect.x+1,r.rect.y+1,r.rect.w-2,r.rect.h-2,corner )
			gfx.rectangle("line", r.rect.x,r.rect.y,r.rect.w,r.rect.h,corner )
			gfx.setColor(1,1,1,0.5*mul)
			gfx.rectangle("line", r.rect.x-1.5,r.rect.y-1.5,r.rect.w+3,r.rect.h+3,corner )
		end

	end
end
function editor.updatePanelHeight(panel,h)
	panel.height = panel.height+(h or panel.row)
end
function editor.deselectRegion(panel)
	panel.region=nil
end

function editor.layerOptions(panel,l)
	-- {
	-- 	name = "camera",
	-- 	click = function() 
	-- 		layer.camera = not layer.camera
	-- 	end,
	-- 	draw = function(option)
	-- 		gfx.setColor(1,1,1,option.hovered and 0.6 or (layer.smooth and 80 or 40))
	-- 		gfx.rectangle("line",option.x+4,option.y+5,10,6,layer.smooth and 3 or 0)
	-- 	end
	-- },
	-- {
	-- 	name = "billboard",
	-- 	click = function() 
	-- 		layer.billboard = not layer.billboard
	-- 	end,
	-- 	draw = function(option)
	-- 		gfx.setColor(1,1,1,option.hovered and 0.6 or (layer.smooth and 80 or 40))
	-- 		gfx.rectangle("line",option.x+4,option.y+5,10,6,layer.smooth and 3 or 0)
	-- 	end
	-- },
	-- {
	-- 	name = "format",
	-- 	click = function() 
	-- 		layer.format = layer.format=="normal" and "r8" or "normal"
	-- 	end,
	-- 	draw = function(option)
	-- 		gfx.setColor(1,1,1,option.hovered and 0.6 or (layer.smooth and 80 or 40))
	-- 		gfx.rectangle("line",option.x+4,option.y+5,10,6,layer.smooth and 3 or 0)
	-- 	end
	-- },

	local layer = panel.layers[l]
	if #layer.options==0 then 
		if not level.isAnim then 
			table.insert(layer.options,{
				name = "smooth tween",
				click = function(option) 
					local layer = panel.layers[option.l]
					layer.smooth = not layer.smooth
				end,
				draw = function(option)
					local layer = panel.layers[option.l]
					gfx.setColor(1,1,1,option.hovered and 0.6 or (layer.smooth and 0.4 or 0.2))
					gfx.rectangle("line",4,5,10,6,layer.smooth and 3 or 0)
				end
			})
		end

		table.insert(layer.options,{
			name = "solo",
			click = function(option) 
				local layer = panel.layers[option.l]
				editor.changeLayer(option.l)
				panel.solo = panel.solo>0 and 0 or panel.layer
			end,
			draw = function(option)
				local layer = panel.layers[option.l]
				gfx.setColor(0.8,0.8,1,option.hovered and 0.6 or (panel.solo == option.l and 0.8 or 0.05))
				-- gfx.circle("line", 8,8, 6,16)
				gfx.draw(getImage("circleLine12"),2,2)
				if panel.solo == option.l then 
					gfx.line(5,8, 10,8 )
				end
			end
		})

		table.insert(layer.options,{
			name = "visible",
			click = function(option) 
				local layer = panel.layers[option.l]
				layer.visible = not layer.visible
			end,
			draw = function(option)
				local layer = panel.layers[option.l]
				gfx.setColor(1,1,1,option.hovered and 0.6 or (layer.visible and 0.4 or 0.2))
				-- gfx.circle("line", 8,8, 6,16)
				gfx.draw(getImage("circleLine12"),2,2)
				if layer.visible then 
					-- gfx.circle("fill", 8,8, 3,16)
					-- gfx.circle("line", 8,8, 3,16)
					gfx.draw(getImage("circleFill8"),4,4)
				end
			end
		})

		-- table.insert(layer.options,{
		-- 	name = "loop",
		-- 	click = function(option		-- 		layer.loop = not layer.loop
			-- local layer = panel.layers[option.l]
		-- 	end,
		-- 	draw = function(option)
			-- local layer = panel.layers[option.l]
		-- 		gfx.setColor(1,1,1, layer.loop and 0.6 or (option.hovered and 0.4 or 0.1))
		-- 		gfx.draw(getImage("loop"),0,	0,0,0.25,0.25)
		-- 	end
		-- })
		

		if layer.type=="drawing" then 
			if not level.isAnim then 
				table.insert(layer.options,1,{
					name = "auto center frames",
					click = function(option) 
						local layer = panel.layers[option.l]
						layer.center = not layer.center
					end,
					draw = function(option)
						local layer = panel.layers[option.l]
						gfx.push()
						gfx.translate(-2,0)
						gfx.setColor(1,layer.center and 0.8 or 1,layer.center and 0.8 or 1,option.hovered and 0.6 or (layer.center and 0.4 or 0.2))
						local set = layer.center and 2 or 4
						gfx.line(10-set,8, 10+set,8 )
						gfx.line(10,8-set, 10,8+set )
						if layer.center then 
							gfx.rectangle("line",5,3,10,10,1)
						end
						gfx.pop()
					end
				})
			end
			table.insert(layer.options,1,{
				name = "type: "..layer.format,
				draw = function(option)
					local layer = panel.layers[option.l]
					if layer.format=="vector" then 
						gfx.setColor(0.8,1,0.8,0.4)
						gfx.line(4,4, 14,4, 9,13 ,4,4)
						-- gfx.printf("V",6,3,6)
						gfx.line(7,6, 11,6, 9,11, 7,6)
						-- gfx.polygon("fill", 4,4, 14,4, 9,13)
					elseif layer.format=="normal" then 
						gfx.setColor(0.8,0.1,0.8,0.4)
						gfx.rectangle("line",4,3,11,11)
						gfx.rectangle("line",6,5,7,7)
						-- gfx.printf("R",7,3,6)
					elseif layer.format=="r8" then 

					elseif layer.format=="model" then 

					elseif layer.format=="camera" then 

					end
				end,
				click = function(option)
					local layer = panel.layers[option.l]
				end
			})
		end

		if layer.type=="model" then 
			table.insert(layer.options,1,{
				name = "edit mesh",
				click = function(option) 
					local layer = panel.layers[option.l]
					layer.remodel = not layer.remodel
				end,
				draw = function(option)
					local layer = panel.layers[option.l]
					gfx.setColor(1,layer.remodel and 0.6 or 1,layer.remodel and 0.3 or 1,option.hovered and 0.6 or (layer.remodel and 0.4 or 0.2))
					gfx.draw(getImage("remodel"),2,	2,0,0.2,0.2)
				end
			})
			table.insert(layer.options,1,{
				name = "wireframe",
				click = function(option) 
					local layer = panel.layers[option.l]
					layer.wireframe = not layer.wireframe
				end,
				draw = function(option)
					local layer = panel.layers[option.l]
					gfx.setColor(layer.wireframe and 0.5 or 1,layer.wireframe and 0.8 or 1,1,option.hovered and 0.6 or (layer.wireframe and 0.4 or 0.2))
					gfx.draw(getImage("wireframe"),2,	2,0,0.2,0.2)
				end
			})
		end
	end
end

function editor.frameGapContext(panel,items,l,f,frame)
	frame.tween = frame.tween or {easeIn=0,easeOut=0,enabled=false}
	table.insert(items,{
		name = "Insert Frame", func=function()
			panel.pushUndoState()
			editor.changeLayer(l)
			animationPanel.hovered = false
			editor.addBlankFrame(panel)
			keyTime=5
			-- local length = newL or -frameHov
			-- local newFrame = editor.defaultFrame(panel,lume.merge(frame,{l=newL or -frameHov}))

			-- frame.l 		= frame.l + frameHov
			-- frameDot.l 	= frame.l*frameWidth
			-- sum 				= sum + frameHov
			-- frameOffset = frameOffset+frameHov*frameWidth

			-- table.insert(layer.frames, f+1, newFrame)

			-- panel.frame = f+1
			-- editor.setAbsoluteFrame(panel)
			panel.changed=true
		end
	})

	table.insert(items,{
		name = "Paste Frame", func=function()

		end
	})
	
	-- table.insert(items,{	
	-- 	{
	-- 	name = "Tween", size=6, func=function()
	-- 		panel.pushUndoState()
	-- 		frame.tween.enabled = not frame.tween.enabled
	-- 		return "toggle"
	-- 	end
	-- 	},{	
	-- 		name = "", align="center",size=1, col = {r=0,g=0,b=0,a=0.6},
	-- 		hover= hover,
	-- 		func = function() 
	-- 			frame.tween.enabled = not frame.tween.enabled
	-- 			return "toggle"
	-- 		end,
	-- 		update 	= function(x)
	-- 			x.text = frame.tween.enabled and "ticked" or "unticked"
	-- 		end
	-- 	}
	-- })

	-- table.insert(items,{	
	-- 	{
	-- 	name = "Blend", size=6, func=function()
	-- 		panel.pushUndoState()
	-- 		frame.tween.blend = not frame.tween.blend
	-- 		return "toggle"
	-- 	end
	-- 	},{	
	-- 		name = "", align="center",size=1, col = {r=0,g=0,b=0,a=0.6},
	-- 		hover= hover,
	-- 		func = function() 
	-- 			frame.tween.blend = not frame.tween.blend
	-- 			return "toggle"
	-- 		end,
	-- 		update 	= function(x)
	-- 			x.text = frame.tween.blend and "ticked" or "unticked"
	-- 		end
	-- 	}
	-- })
end



function editor.updateTimeline ( panel )
	-- if LOVR then trace("notimeline") return end

	gfx.push("all")

	-- sidebar.row = 20
	-- panel.row = 20
	-- trace(editor.resized>0 )
	-- trace(	 panel.scrubbing )
	-- trace(	panel.panTimeline )

	-- trace()
	-- 			trace((not panel.canvasClicked) and (panel.y<screenHeight+5))
	-- trace(			 panel.playing )
	-- trace(				keyTime>0  )
	-- trace(				panel.sizeSlider and panel.sizeSlider.sliding )
	-- trace(				panel.fpsSlider and panel.fpsSlider.sliding )
	-- trace(				panel.timelineMousing  )
	-- trace(				panel.trackHead )

	if  
		 editor.resized>0 
		or panel.scrubbing 
		or panel.panTimeline 
		or panel.unblanked 
		or ((not panel.canvasClicked) and (panel.y<screenHeight+5) and 
				( panel.playing 
					or keyTime>0  
					or panel.sizeSlider.sliding 
					or panel.fpsSlider.sliding 
					or panel.timelineMousing  
					 ) 
				)   then 
			panel.unblanked =false
		trace("update timeline")
		panel.layerWidth 			= 200--panel.baseLayerWidth + (panel.width/10)
		local scrubPoint
		local layerWidth 			= panel.layerWidth 
		local framesX 				= panel.x+layerWidth
		local frameOffset 			= 0
		local currentFrameOffset 	= 0
		local sum 					= 0
		local length 				= panel.animation.length
		local hoveredLayer 			= 0
		local timeline 				= {x=panel.x+layerWidth,	y=panel.y+13,	w=panel.width-layerWidth,	h=panel.savedHeight-15}
		local timelineTop    = {x=panel.x+layerWidth,	y=panel.y,	w=panel.width-layerWidth,	h=16}
		local layerswap 			= {}
		local frameWidth = panel.frameWidth

		-- print("frameWidth",frameWidth)
		local circleScale = frameWidth>12 and 12 or 8
		-- print("circleScale",circleScale)
		-- print("circleFill"..tostring(circleScale))
		panel.circleFill = getImage("circleFill"..tostring(circleScale))
		panel.circleLine = getImage("circleLine"..tostring(circleScale))
		panel.circleFill:setFilter("linear","linear")
		panel.circleLine:setFilter("linear","linear")

			if not panel.timelineCanvas or panel.timelineCanvas:getWidth() ~= screenWidth or mf(timeline.h+panel.row)~= panel.timelineCanvas:getHeight() then 
				panel.timelineCanvas = newCanvas(screenWidth,timeline.h+panel.row,{msaa=4})
				log("new timeline")
			end
			gfx.setCanvas(panel.timelineCanvas)
			gfx.clear(0,0,0,0)

		
		gfx.push("all")
		gfx.translate(0,panel.timelineCanvas and -panel.y or 0)
		gfx.setBlendMode("alpha")


		if mouseIn(timeline) then
			lmouse.setCursor(cursors.plus)
		end

		framesX = framesX-panel.scrollPos		
		gfx.setScissor( timeline.x,-15,timeline.w,timeline.h+15 )
			gfx.fontSize(8)
			gfx.setColor(1,1,1,LOVE and 0.5 or 1)-- DRAW TIMELINE NUMBERS  -- 
			for i=1, math.max(length,(panel.width+100)/frameWidth), 1  do
				if i>(panel.scrollPos)/frameWidth and i<(panel.scrollPos+panel.width-200)/frameWidth then 
					gfx.print(
						(i%4 == 0) and tostring(i) or ".", 
						mf(panel.x-panel.scrollPos+layerWidth+(i)*frameWidth-frameWidth/1.5-(#tostring(i)-1)*2) , 
						mf(panel.y+12) )
				end
			end
			for i=1, math.max(length,(panel.width+100)/frameWidth), 1  do
				if (i%panel.animation.fps == 0) then 
					local seconds = i/panel.animation.fps
					local minutes = mf(seconds/60)
					seconds = seconds - minutes*60
					gfx.print(
						string.format("%02d:%02d",minutes,seconds), 
						panel.x-panel.scrollPos+layerWidth+(i)*frameWidth-frameWidth-(#tostring(i))*2 , 
						panel.y) 
				end
			end

		gfx.setScissor()

		if panel.tweenDrag.side~="" then 
			trace(panel.tweenDrag.side..tostring(mouse.start.x-mouse.x))
			panel.tweenDrag.frame.tween["ease"..capFirst(panel.tweenDrag.side)]=mc(0,panel.tweenDrag.startEase+(panel.tweenDrag.side=="in" and mouse.start.x-mouse.x or mouse.x-mouse.start.x)/80,1)
			trace(panel.tweenDrag.frame.tween["ease"..capFirst(panel.tweenDrag.side)])
		end

		gfx.fontSize(12)
		

		
		for l,layer in lume.ripairs(panel.layers) do
			-- trace("layer",layer)
			local fillFrame  		= layer.iqm or layer.obj or layer.external

			framesX 				= panel.x+layerWidth
			frameOffset 			= 0
			currentFrameOffset 		= 0
			sum 					= 0

			framesX = framesX-panel.scrollPos
			panel.framesX=framesX
			

			layer.options =  layer.options or {}
			editor.layerOptions(panel,l)

			local optionWidth = 20

			layer.element = layer.element or {}
			layer.element.x	= panel.x+(optionWidth)*(#layer.options)+4
			layer.element.y	= easeTo(
				layer.element.y or panel.y+panel.height, 
				(panel.draggedLayer==layer.id and panel.draggedLayerStart:dist(mouse)>3)
					and mc(panel.y+panel.row*0.9,mouse.y-panel.row/2,panel.y+panel.savedHeight-panel.row*1.9) 
					or panel.y+panel.height,
				panel.hideSpeed
			)
			layer.element.cy = layer.element.y +panel.row/2-10

			layer.element.w	= layerWidth-(optionWidth)*#layer.options
			layer.element.h	= panel.row-2
			layer.element.hovered = (mouseIn(layer.element) and not panel.draggedLayer)

			if layer.element.hovered then 
				mouse.set(function() 
					editor.changeLayer(l)
					panel.draggedLayer = layer.id
					panel.draggedLayerStart = vec2(mouse)
				end)
				mouse.setR(function() 
					editor.changeLayer(l)
					local items = {}

					if layer.type~="model" then 
						table.insert(items, {
							name="Format: "..layer.format,
							static=true,
							-- tip = "There are two possible formats for the raster element of a layer \n\nNormal is regular full color \n\nLimited has a maximum of 255 colors, but uses about a quarter of the memory",
							func=function()

							end,
							update=function(item) 
								item.name = "Format: "..(layer.format=="r8" and "Limited" or capFirst(layer.format))
							end
						})
						table.insert(items, editor.makeSlider(layer,"alpha",{name="Opacity"}))
						if layer.format=="vector" then 
							table.insert(items, editor.makeToggle(layer,{"lineWidth","lineWidthOverride"},{min=0.25,max=2,name="Line Width Modifier",click=editor.refreshStrokes,slide=editor.refreshStrokes}))
							table.insert(items, editor.makeToggle(layer,"onePixel",{name="1px lines",click=editor.refreshStrokes}))
							-- table.insert(items, editor.makeSlider(layer,"catmull",{name="Line Smoothing",min=0,max=4,round=1,slide=editor.refreshStrokes}))
						end
						-- table.insert(items, editor.makeSlider(layer,"resolution",{name="Resolution"}))
					end
					table.insert(items, editor.makeSlider(layer,"wobble",{name="Wobble"}))

					table.insert(items, {name="New Layer",col=colors.green,func=function() editor.newLayer(panel,l) end,items={
						{name="Format:",static=true},
						{name="Raster",tip="",func=function()editor.newLayer(panel,l,"normal") end},
						-- {name="Limited",tip="Limited Color Raster",func=function()editor.newLayer(panel,l,"r8") end},
						{name="Vector",tip="",func=function()editor.newLayer(panel,l,"vector") end},
						-- {name="Model",tip="3D Model",func=function() editor.newLayer(panel,l,"model") end, items={{name="Cube"},{name="Sphere"},{name="Cylinder"}}},
						-- {name="Camera",tip="Camera",func=function()  editor.newLayer(panel,l,"camera") end},
					}})
					if #panel.layers>1 then 
						table.insert(items, {
							name="Delete Layer",
							col=colors.red,
							warning="open",
							func=function() 
								editor.deleteLayer(panel,l) 
							end})
					end
					editor.openContextMenu(items,{y=mouse.y-15,up=true}) 
				end)
			end

			local layerBack ={
				x	= panel.x+layerWidth,
				y	= layer.element.cy,
				w	= panel.width-layerWidth+2,	
				h	= panel.row-2
			}
			layerBack.hovered = (mouseIn(layerBack) and not panel.draggedLayer)
			if layerBack.hovered then
				hoveredLayer = l
			else
				hoveredLayer = 0
			end
			layer.hovered = mouseIn(lume.merge(layerBack,{x=0,w=layerWidth}))

			local layerRename ={
				x	= layer.element.x+layer.element.w-optionWidth-8,
				y	= layer.element.cy+2,
				w	= optionWidth,	
				h	= panel.row-4
			}
			layerRename.hovered = mouseIn(layerRename)
			if mouseIn(layerRename) then
				-- editor.setToolTip("rename")
				mouse.set(function() 
					namer:typeString("rename layer",panel.layers[l].name,{x=layerRename.x,y=layerRename.y},function(n) panel.layers[l].name = n end)
				end)
			end
			gfx.setColor(1,1,1, layerRename.hovered and 0.3 or layer.hovered and 0.2 or 0.05)
			gfx.draw(getImage("pen"),layerRename.x+4,	layerRename.y+1,0,0.6,0.6)
			

			gfx.fontSize(12)
			gfx.setLineWidth(1)

			if (layer.element.hovered or l == panel.layer) then
				gfx.setColor(0.5,0.5,0.7,0.1)
				gfx.rectangle(	"fill", 0,	layer.element.y,	layerWidth+2,	layer.element.h) 
			end

			if  l == panel.layer or panel.draggedLayer == layer.id then
				gfx.setColor(0.5,0.5,0.7,0.15)
				gfx.rectangle(	"fill", layerBack.x,	layer.element.y,	layerBack.w,	layer.element.h) 
			end

			gfx.setColor(0.9,0.9,0.9,1) 											
			gfx.print(layer.name:sub(1,((layerWidth-optionWidth)/6)-(layer.hovered and 2 or 0)), layer.element.x, layer.element.cy+2) 

			for o,option in ipairs(layer.options) do 
				option.x				= layer.element.x-(optionWidth)*(#layer.options-o+1)-4
				option.y				= layer.element.cy+1
				option.w				= optionWidth
				option.h				= panel.row-2
				option.hovered 	= mouseIn(option)
				option.l 				= l
				if option.hovered then 
					editor.setToolTip(option.name)
					mouse.set({option.click,option})
				end
				gfx.push("all")
				gfx.translate(option.x,option.y)
				option.draw(option)
				gfx.pop()
			end
			gfx.setScissor( timeline.x,0,timeline.w,timeline.h )
			local framesUpped,fl,nextFrame,prevFrame,frame = 0

			for f =1, #layer.frames,1 do

				frame = layer.frames[f]
				
				fl = frame.l and frame.l or 1

				if f == panel.frame and l==panel.layer then 
					currentFrameOffset = frameOffset 
				end

				frame.sum = sum

				
				if sum~=panel.currentFrame then 
					if frame.strokePreview then 
						-- frame.strokePreview:release()
						-- frame.strokePreview=nil
						-- lume.clear(frame.strokeVerts)
						-- frame.strokeVerts=nil
					end
				end

				sum = sum + frame.l
				frameOffset 	= frameOffset + fl*frameWidth

				if (frameOffset+fl*frameWidth >panel.scrollPos and frameOffset-fl*frameWidth <panel.scrollPos+panel.width) or f==#layer.frames then 
					nextFrame = layer.frames[f==#layer.frames and 1 or f+1]
					prevFrame = layer.frames[f==1 and #layer.frames or f-1] 

					frame.abs = editor.getAbsoluteFrame(panel,l,f)
					framesUpped = framesUpped +1
					frameOffset 	= frameOffset - fl*frameWidth

					frameDots[f] = frameDots[f] or {}
					frameDot = frameDots[f]
					frameDot.x = framesX+frameOffset
					frameDot.y = layer.element.y-1
					frameDot.w = frameWidth
					frameDot.h = panel.row
					frameDot.l = fl*frameWidth

					frameGaps[f] = frameGaps[f] or {}
					frameGap = frameGaps[f]
					frameGap.x = frameDot.x+frameWidth
					frameGap.y = frameDot.y
					frameGap.w = frameWidth*(fl-1)
					frameGap.h = panel.row
					frameGap.l = fl*frameWidth
					

					frameDot.hoved 	= false--mouseIn(frameDot) and not panel.draggingFrame and not (panel.region and panel.region.canDrag)
					frameDot.r 		=  ((panel.draggingFrame and panel.draggedFrame == f-1 and panel.draggedFrameLayer==l ) and frameWidth/2.5 or frameWidth/3)
					frameOffset 	= frameOffset + fl*frameWidth

					local side = panel.tweenDrag.side
					local newL = (not mouseIn(frameGap)) and 1
					local frameHov = mf( (mouse.x-framesX)/frameWidth)-sum
					local openContext = false
					local items = {}

					if not panel.playing then 
						if mouseIn(layerBack) or mouseIn(timelineTop) then 

							mouse.pushClick(function()
								if mouseIn(timelineTop) then 
									panel.topScrub = true
								end
								if not (panel.region and panel.region.canDrag) then  
									panel.scrubbing=true
									if mouseIn(layerBack)  then 
										editor.changeLayer(l)
										panel.region = {
											selected = true,
											frames = {},
											layers = {}
										}
									end
								end
							end)
						end

						-- CLICK INBETWEEN CIRCLES TO MAKE NEW FRAMES -- 
						if (mouseIn(frameGap) or (mouseIn(layerBack) and f==#layer.frames and mouse.x-framesX>sum*frameWidth))  then
							
							openContext = true
							side = ( mouse.x<frameGap.x+frameGap.w/2 and "in" or "out")
							
							editor.frameGapContext(panel,items,l,f,frame)

							if frame.tween and frame.tween.enabled then 
								mouse.set(function() 
									panel.tweenDrag = {side=side,frame=frame,startEase=frame.tween["ease"..capFirst(side)]}
								end)
							end


						-- CLICK TIMELINE CIRCLES -- 
						elseif mouseIn(frameDot) then 
							openContext = true
							
							if not shiftDown then 
								mouse.set(function() 
									panel.pushUndoState()
									editor.changeLayer(l)
									panel.frame = f
									editor.setAbsoluteFrame(panel)
									-- editor.startDragFrames(panel,f,l)
								end)
							end

							mouse.setR(function()

							end)

							if layer.iqm then
								if frame.anim then
									gfx.push("all")
									gfx.setScissor()
									editor.drawTip({text=frame.anim})
									gfx.pop()
								end
								local animList = {}
								for a,anim in ipairs(layer.iqmAnims) do 
									table.insert(animList,{
										name=anim.name,
										func=function()
											frame.anim = anim.name
											return true
										end,
										update 	= function(x)
											x.col = frame.anim == anim.name and {r=0,g=0,b=0,a=0.8} or {r=0,g=0,b=0,a=0}
										end
									})
								end

								table.insert(items,{	
									name = "Animation", 
									items = animList
								})
							end
						end
						
						if (panel.scrubbing or panel.draggingFrame) and not scrubPoint  then 
							scrubPoint = math.max(1,sum + frameHov+1)
							if panel.scrubbing and panel.region and panel.region.frames and not panel.topScrub then 
								trace("reg")
								panel.region.frames.first = panel.region.frames.first or scrubPoint
								panel.region.frames.last = scrubPoint
							end
							trace("scrubbing",panel.scrubbing)
						end

						if openContext then 
							mouse.setR(function() 
								if panel.region and panel.region.rect then 
									if  mouseIn(panel.region.rect) then 
										table.insert(items,{
											name = "Create Clip", func=function()
											panel.pushUndoState("clip")
												local clip = deepcopy(panel.region)
												clip.isClip = true
												table.insert(layer.clips,clip)
												panel.region = {}
											end
										})
									else
										panel.scrubbing=true
										panel.region=nil
									end
								else
									panel.scrubbing=true
								end
								editor.changeLayer(l)
								panel.frame = f
								--editor.setAbsoluteFrame(panel)
								editor.openContextMenu(items,{y=mouse.y-15,up=true,width=140,subWidth=120}) 
							end,true)
						end
					end

				

					-- DRAW TIMELINE LINES + CIRCLES --- 
					local dotSelected 	= (l==panel.layer and f==panel.frame)
					local dotBefore 	= (l==panel.layer and ((layer.loop and panel.frame==1) and f==#panel.frames or f==panel.frame-1) and (panel.onion.before.enabled and panel.onion.enabled))
					local dotAfter 		= (l==panel.layer and ((layer.loop and panel.frame==panel.frames) and f==1 or f==panel.frame+1) and (panel.onion.after.enabled and panel.onion.enabled))


					local r,g,b = 1,1,1
					if dotBefore then 
						local bef = panel.onion.before.tint
						r,g,b = bef.r,bef.g,bef.b
					elseif dotAfter then 
						local aft = panel.onion.after.tint
						r,g,b = aft.r,aft.g,aft.b
					end
					local a = l==panel.layer and (dotSelected and 1 or (LOVR and 0.9 or 0.75)) or (LOVR and 2 or 0.5)
					gfx.setColor(r,g,b,a)

					
					local x1,x2 = frameDot.x+frameWidth/2+frameDot.r,frameDot.x+frameWidth/2+frameDot.r*1.8+frameGap.w
					local y1,y2,y3 = frameDot.y+7,frameDot.y+panel.row-7,frameDot.y+panel.row/2

					if frame.tween and frame.tween.enabled and frame.l>1 then 
						frame.tween.easeIn = frame.tween.easeIn or 0
						frame.tween.easeOut = frame.tween.easeOut or 0
						gfx.setLineWidth(1)

						local n = frame.l+1
						for i=0,n,1 do 

							local p1 = (i/n)
							local p2 = p1<0.5 and ((p1*2)^(1+frame.tween.easeIn))/2 or 1-math.abs(p1*2-2)^(1+frame.tween.easeOut)/2
							local x = lerp(x1+frameWidth/3,x2-frameWidth/3,p2)
							local y4 = (panel.tweenDrag.side=="" or panel.tweenDrag.frame==frame) and 
													((side=="in" and i<n/2) and 2 or ((side=="out" and i>n/2) and 2 or 0)) or 0
							gfx.line(x,y1-y4,x,y2+y4)
						end
					end

				

					if frame.tween and frame.tween.blend then 
						gfx.setLineWidth(1)
						gfx.line(	x1, 	y1,  x2, 	y1)
						gfx.line(	x1, 	y2,  x2, 	y2)
					elseif  not frame.blanker then 
						gfx.setAlpha((LOVR and 15 or 1)*(frame.blank and 0.1 or 1)*0.1*(panel.layer==l and 1 or 0.5))
						if config.flashFrames then 
							gfx.setLineWidth(1)
							local a=(0.5+a)*0.5*(frame.blank and 0.5 or 0.9)
							gfx.setColor(r*a,g*a,b*a,1)
							gfx.rectangle("fill",frameDot.x, 	frameDot.y+1,frameGap.w+frameWidth,panel.row-2)
							gfx.setColor(0,0,0,1)
							gfx.rectangle("line",frameDot.x, 	frameDot.y+1,frameGap.w+frameWidth,panel.row-2)
							gfx.setColor(r*a,g*a,b*a,1)
						else
							gfx.push("all")
							gfx.setColor(r*a,g*a,b*a, l==panel.layer and 0.2 or 0.1)
							gfx.setLineWidth(dotSelected and 8 or 4)
							gfx.line(	x1-1, 	y3,  x2+2, 	y3)
							gfx.setLineWidth(dotSelected and 2 or 1)
							gfx.pop()
						end
					end

					if not config.flashFrames then 
						gfx.setColor(r*a,g*a,b*a,1)
						-- gfx.setColor(r,g,b,1)
					end

					if layer.iqm and frame.anim then 
						local x,y = frameDot.x+frameWidth/2,frameDot.y+panel.row/2
						gfx.polygon("fill",x-3,y-5, x-3,y+5, x+5,y)
						--gfx.circle( "line", x,y-2, frameDot.r/(dotSelected and 1 or 1.3)+0.5,16 ) 
					else
						local fill = (not (frameDot.hoved or frame.blank) or fillFrame)  and "fill" or "line"
						if layer.type == "model" then
							local size = frameWidth*0.8
							gfx.push()
								gfx.translate(frameDot.x+frameWidth/2, frameDot.y+panel.row/2)
								gfx.rotate(pi/4)
								gfx.rectangle("fill",-size/2,-size/2,size,size)
							gfx.pop()
						else
							if config.showLoaded then 
								if frame.released then 
									gfx.setColor(1,0.2,0.2,1)
								else 
									gfx.setColor(0.2,1,0.2,1)
								end
							end
							if config.flashFrames then 
								gfx.setColor(0,0,0,1)
								-- if frame.isKey then 
								-- 	gfx.rectangle(fill,frameDot.x+frameWidth/2-5/2,frameDot.y+panel.row*0.2,5,panel.row*0.6)
								-- 	gfx.draw(circleImg)-- gfx.circle(fill , frameDot.x+frameWidth/2, frameDot.y+panel.row*0.7, 2.5, 16 )
								-- else
								-- 	gfx.draw(circleImg)-- gfx.circle(fill , frameDot.x+frameWidth/2, frameDot.y+panel.row*0.7, 2.5, 16 )
								-- 	gfx.draw(circleImg)-- gfx.circle("line" , frameDot.x+frameWidth/2, frameDot.y+panel.row*0.7, 2, 16 )
								-- end
								if frame.l>1 then 
									gfx.rectangle("line",frameDot.x+frameGap.w+frameWidth*0.2,frameDot.y+panel.row*0.5,frameWidth*0.6,panel.row*0.4)
								end
							else
								if frame.isKey then 
									gfx.rectangle(fill,frameDot.x+frameWidth/6,frameDot.y+panel.row*0.2,frameWidth-frameWidth/3,panel.row*0.6,2)
									gfx.rectangle("line",frameDot.x+frameWidth/6,frameDot.y+panel.row*0.2,frameWidth-frameWidth/3,panel.row*0.6,2)
								else
									-- gfx.setColor(1,1,1,1)
									local circleSize = (2/circleScale)*(fillFrame and 0.5 or 1)*(frameDot.r/(dotSelected and 0.9 or 1.1))
									
									gfx.draw(
										frame.blank and panel.circleLine or panel.circleFill,
										frameDot.x+frameWidth/2-circleSize*circleScale*0.5, 
										frameDot.y+panel.row/2-circleSize*circleScale*0.5, 
										0,circleSize,circleSize
									)
									-- gfx.circle("fill" , frameDot.x+frameWidth/2, frameDot.y+panel.row/2,(fillFrame and 0.5 or 1)*(frameDot.r/(dotSelected and 0.9 or 1.1)), frameWidth )
								end
							end
						end
					end
				end
			end

			if mouseIn(layerBack) and panel.scrubbing  and panel.region and not panel.topScrub then 
				panel.region.layers.first = panel.region.layers.first or l
				panel.region.layers.last = l
			end

			-- ADD FRAME HOVER
			if l==panel.layer then 
				panel.frameHover = panel.frameHover or {x=0,y=0}
				if mouse.x>panel.x+layerWidth+3 and mouseIn(lume.merge(timeline,{h=timeline.h-panel.row})) then 
					panel.frameHover = {
						x = framesX+(mf((mouse.x-framesX)/frameWidth))*frameWidth, --mf((mouse.x-framesX+frameWidth/2)/frameWidth)*frameWidth 
						y = panel.sy-panel.row+  mc(1,mf((mouse.y-panel.sy+panel.row)/panel.row),#panel.layers)  *panel.row
					}
				end

				if not( panel.region and mouseIn(panel.region.rect)) and (mouseIn(lume.merge(timeline,{h=timeline.h-panel.row})) or contextMenu.open ) then 
					gfx.setColor(1,1,1,0.03)
					gfx.rectangle("fill", panel.frameHover.x, panel.frameHover.y, frameWidth, panel.row-2, 2 )
				end
			end

			
			for c,clip in ipairs(layer.clips) do 
				clip.l1,clip.l2=l,l
				-- drawClip(panel,clip)
			end

			
			gfx.setScissor()

			

			-- DRAG LAYER  
			if panel.draggedLayer and panel.draggedLayer==layer.id then 
				layerswap = {l, mc(1,#panel.layers-1-lume.round((layer.element.y-panel.y)/panel.row)+2,#panel.layers)}
			end

			editor.updatePanelHeight(panel)
			
		end


		 -- DRAW CURRENT FRAME BACK -- 
		 gfx.setScissor( timeline.x,0,timeline.w,timeline.h )
		if config.flashFrames then 
			gfx.setColor(1,0.2,0.2,0.6)
			gfx.rectangle("fill", framesX+(panel.currentFrame-0.77)*frameWidth, panel.y-3, frameWidth*0.6, 20)
			gfx.rectangle("fill", framesX+(panel.currentFrame-0.5)*frameWidth-1, panel.sy-3, 2, #panel.layers*panel.row)
		else
			gfx.setColor(1,1,1,0.02)
			gfx.rectangle("fill", framesX+(panel.currentFrame-1)*frameWidth, panel.y+10, frameWidth, panel.savedHeight-12-panel.row,2)
		end
		gfx.setLineStyle("smooth")
		gfx.setLineWidth(1)
		gfx.setBlendMode('alpha')
		gfx.setColor(1,1,1,0.5)

		if not (config.flashFrames or panel.l.remodel) then 
			gfx.circle("fill",framesX+(panel.currentFrame-1+0.5)*frameWidth,panel.y+4,2)
		end

		gfx.setScissor()

		if panel.region and panel.region.selected  then 
			drawClip(panel,panel.region)
			trace("REGION")
		end

		if panel.draggingFrame and panel.copiedRegion then 
			gfx.setColor(0.2,0.2,0.25,0.5)
			panel.regionPreviewPosition = {
				f=mf((mouse.x-panel.copiedRegion.offset.x-framesX)/frameWidth),
				l=mc(1,mf((mouse.y-panel.copiedRegion.offset.y-panel.sy+panel.row*1.5)/panel.row),#panel.layers)
			}
			-- print("panel.regionPreviewPosition.l",panel.regionPreviewPosition.l)
			local dragX = (panel.regionPreviewPosition.f * frameWidth) +framesX
			local dragY = panel.sy-panel.row+  panel.regionPreviewPosition.l  *panel.row
			gfx.rectangle("fill",dragX,dragY,panel.copiedRegion.rect.w,panel.copiedRegion.rect.h,2)
			gfx.setColor(0.6,0.6,1,1)
			gfx.rectangle("line",dragX,dragY,panel.copiedRegion.rect.w,panel.copiedRegion.rect.h,2)
		end

		for l,layer in ipairs(panel.layers) do 
			for c,clip in ipairs(layer.clips) do 
				if not clip.canDrag then clip.canLoop = false end
				if  clip.canLoop then 
					trace("loopael") 
					mouse.set(function()
						editor.startLoopFrames(panel,clip)
					end)
				elseif  clip.canDrag then 
					mouse.set(function()
						editor.startDragFrames(panel,clip)
					end)
					mouse.setR(function() 
						clip.loopMode = clip.loopMode or "repeat"
						editor.openContextMenu({
							editor.makeModes(clip,"loopMode",panel.loopModes),
							{name="release clip",func=function()
								table.remove(layer.clips,c)
							end}
						})
					end)
				end
			end
		end

		
		if panel.region and panel.region.canDrag then 
			mouse.set(function()
				editor.startDragFrames(panel,panel.region)
			end)
		end

		if mouseIn(timelineTop) then 
			mouse.setR(function()
				panel.preScrub = {panel.currentFrame,panel.scrollPos}
				editor.openContextMenu ({{
					name="scrub",
					func=function() end,
					update=function(item)
						trace((mouse.x-item.x)/item.width ) 
						if item.hovered then 
							local scr = ((mouse.x-item.x)/item.width)
							panel.currentFrame = scr * panel.animation.length
							keyTime=3
							panel.scrollPos = easeTo(panel.scrollPos,mc(0,panel.currentFrame*panel.frameWidth-(screenWidth-panel.layerWidth)/2, panel.animation.length*frameWidth),1.3)
						end
					end
				}},{y=panel.y-32,width=300})
			end)
		end

		if noSeek then 
			panel.currentFrame,panel.scrollPos = panel.preScrub[1],panel.preScrub[2]
		end

		-- CHANGE LAYER
		if #layerswap>0 then 
			local moving = panel.layers[layerswap[1]]
			table.remove(panel.layers,layerswap[1])
			table.insert(panel.layers,layerswap[2] ,moving)
			editor.changeLayer(layerswap[2])
		end

		if panel.waveForm then 
			gfx.setScissor()
			gfx.setScissor(panel.x+panel.layerWidth,	0,	panel.width-panel.layerWidth,9999)
			gfx.setColor(1,1,1,panel.mute and 0.1 or 1)
			gfx.draw(panel.waveForm,panel.x+panel.layerWidth-panel.scrollPos,panel.y+panel.height+panel.row/3,0,panel.frameWidth*panel.animation.fps,1)
			gfx.setScissor()
		end

		panel.currentFrame = scrubPoint or panel.currentFrame

		if mouse.release() then 
			if panel.draggingFrame and panel.copiedRegion then 
				print("release")
				-- move region

				if not altDown then 
					editor.deleteRegion(panel,panel.region)
				end

				editor.pasteRegion(panel,
					mf((mouse.x-panel.copiedRegion.offset.x-framesX)/frameWidth+1),
					panel.regionPreviewPosition.l,
					panel.copiedRegion
				)					
				if shiftDown then 
					-- insert
				end
			end
			if panel.activeClip then 
				panel.activeClip.foff=nil
			end
			panel.scrubbing = false
			panel.topScrub  = false
			panel.draggingFrame=false 
			panel.draggedLayer=nil
			panel.draggedFrameEnd=nil
			panel.draggingLoop = false
			panel.panTimeline = false
			panel.tweenDrag = {side="",frame=0,layer=0}
		end

		if contextMenu.open then 
			panel.scrubbing = false
		end

		


		gfx.pop()

		-- panel.height = panel.height +26
		panel.ty = panel.y
		panel.th = panel.height
	end


	if mouse.y>screenHeight-22 then 
		mouse.set(function()
			panel.panTimeline = true 
		end)
	end
	if panel.panTimeline then
		panel.scrollPos = panel.scrollPos - mouse.change.x
	end

	panel.height = panel.th or panel.height
	panel.y = panel.ty or panel.y

	panel.timelineMousing = mouseIn(panel)

	gfx.pop()

	pushPost()
	gfx.setColor(1,1,1,1)
	gfx.setBlendMode("alpha","premultiplied")
	if  panel.timelineCanvas then 
		gfx.setMeshCullMode("none")
		gfx.draw(panel.timelineCanvas,0,mf(panel.y))
		-- gfx.setMeshCullMode("front")
	end
	popPost()
	gfx.setBlendMode("alpha")

	
end

function editor.processRegion(panel,region,proc)
	if not region.l1 then return end
	for l=region.l1,region.l2,1 do 
		local prev = panel.layers[l].frames[editor.getKeyFrame(panel,l,region.f1-1)]
		local pk=0
		for f=region.f1,region.f2,1 do 
			local k = editor.getKeyFrame(panel,l,f)
			if k~=pk then 
				local frame = panel.layers[l].frames[k]
				if frame then 
					proc(l,f,k,frame,prev)
				end
			end
			pk = k 
		end
	end
end

function editor.deleteRegion(panel,region)
	editor.processRegion(panel,region,function(l,f,k,frame,prev)
		local abs  = editor.getAbsoluteFrame(panel,l,k,frame,prev)
		if abs>=region.f1 and abs<=region.f2 then 
			prev.l = prev.l + frame.l
			table.remove(panel.layers[l].frames, k)
		end
	end)
end

function editor.pasteRegion(panel,f,l,copied,insert)
	if insert then 

	else

		panel.region.f1=f
		panel.region.f2=panel.region.f1+copied.length-1
		print("l,height",l,copied.height)

		local add =copied.height-1
		-- print("(l/l+h)f",#panel.layers-l+1,#panel.layers-(l+add)+1)
		panel.region.l1=#panel.layers-(l+add)+1
		panel.region.l2=#panel.layers-l+1
		print("l1/l2",panel.region.l1,panel.region.l2)
		
		print("copied.l1",copied.l1,panel.region.l1)
		editor.deleteRegion(panel,panel.region)

		local offset=0
		for l2=1,#panel.layers,1 do
			if copied.layers[l2] then 
				local k = editor.getKeyFrame(panel,l2,f)+1
				local skipFirst = false
				print("same keys",k-1,copied.layers[l2][1].index)
				if copied.l1==panel.region.l1 and k-1==copied.layers[l2][1].index and copied.layers[l2][1].pad then 
					panel.layers[l2].frames[k-1].l=f+copied.layers[l2][1].l-panel.layers[l2].frames[k-1].abs
					skipFirst=true
					print("SKIPPPPP")
				else
					print("k",k)
					print("#panel.layers[l2].frames",panel.layers[l2].frames)
					panel.layers[l2].frames[k-1].l=f-panel.layers[l2].frames[k-1].abs
					print("dontSKIPPPPP")
				end
				for f2,frame in ipairs(copied.layers[l2]) do
					if panel.layers[l2].frames[k] and f2 == #copied.layers[l2] then 
						frame.l = frame.l + (panel.layers[l2].frames[k].abs-panel.region.f2)-1
					end
					if not (f2==1 and skipFirst) then 
						-- local l3 = l+l2-1
						-- local f3 = f+offset
						-- offset = offset + frame.l
						table.insert(panel.layers[l2].frames,k,frame)
						print("INSERT")
						k=k+1
					end
				end
			end
		end
	end
end

function editor.pasteFrame(panel,l,f,frame)
	--find key 
	local k = editor.getKeyFrame(panel,l,f)
	print("paste",l,k)
	table.insert(panel.layers[l].frames,k,frame)
end

function editor.copyRegion(panel,region,cut)
	local copied = {
		l1    = region.l1,
		rect  =region.rect,
		length=region.fw,
		height=region.lh,
		offset=vec2(mouse.x-region.rect.x,mouse.y-region.rect.y),
		layers={}
	}

	editor.processRegion(panel,region,function(l,f,k,frame,prev)
		copied.layers[l] = copied.layers[l] or {}
		table.insert(copied.layers[l],editor.copyFrame(panel,frame,panel.layers[l]))
		copied.layers[l][#copied.layers[l]].index = k
		if #copied.layers[l]==1 then 
			local abs = editor.getAbsoluteFrame(panel,l,k)
			if abs~=region.f1 then 
				local diff = abs+frame.l-region.f1
				copied.layers[l][1].l=diff
				copied.layers[l][1].pad=true
			end
		end
	end)

	for l=1,#panel.layers,1 do
		if copied.layers[l] then 
			local frame = copied.layers[l][#copied.layers[l]]
			frame.l = region.f2-editor.getAbsoluteFrame(panel,l,frame.index)+1
		end
	end

	return copied
end

function editor.startDragFrames(panel,f,l)
	local f1,f2,l1,l2
	if type(f)=="table" and f.k1 then 
		panel.activeClip = f
		panel.copiedRegion = editor.copyRegion(panel,f)
		print("STARTDRAGREGION")
	end
	panel.pushUndoState()
	panel.draggingFrame 	= true

end

function editor.startLoopFrames(panel,clip)
	panel.activeClip = clip
	local f,l,f2,l2 = clip.k1,clip.l1,clip.k2
	panel.pushUndoState() 
	editor.startDragFrames(panel,f2+1,l)
	panel.draggingLoop = true
	clip.f3 = clip.f3 or 0
	clip.sf3 = clip.f3
end

function editor.scrollTimeline(panel)
	
	if mouseIn(panel) then 
		
		panel.scrollSpeed = panel.scrollSpeed+mouseScroll.x*16
	end

	local headPos = panel.currentFrame*panel.frameWidth-panel.scrollPos
	local safeZone = 150
	local left,right = panel.layerWidth+safeZone, panel.width-safeZone
	
	panel.scrollSpeed =  panel.scrollSpeed+(panel.draggingFrame and (
				mouse.x<left  and -(left-mouse.x)/safeZone
		or( 
				mouse.x>right and (mouse.x-right)/safeZone
	or 0))*10 or 0)

	left,right = safeZone, panel.width-panel.layerWidth-safeZone
	local pos = headPos<left and (headPos-left)*1 or (headPos>right and (headPos-right)*1 or 0)


	if panel.timelineTracking and ( anyKeyDown({"1","2","w","q","left","right","backspace"})) and not panel.playing then 
		panel.trackPos = panel.scrollPos+pos
		panel.trackHead = math.abs(pos)>0
		panel.keyTime = 5
	end

	if mouseIn(panel) then 
		panel.trackHead = false 
	end
	if panel.playing then 
		panel.trackHead=false 
	end
	if panel.timelineTracking and (panel.playing or panel.trackHead) then 
		if panel.playing then 
			panel.playTrackSpeed = 4--mc(8,panel.playTrackSpeed-1,128)
		end
		local mid = panel.currentFrame*panel.frameWidth-panel.width/2
		panel.scrollPos=easeTo(
			panel.scrollPos,
			panel.trackHead and panel.trackPos or mid,
			panel.skipTrack and 1 or (panel.trackHead and 4 or panel.playTrackSpeed)
		)
		panel.skipTrack = false
		if pos<left and math.abs(panel.framesX-panel.layerWidth)<5 then 
			panel.trackHead = false
		end
		if pos == 0 then 
			panel.trackHead = false
		end
	elseif panel.trackHead then 

	end

	panel.scrollSpeed 	= easeTo(panel.scrollSpeed,0,2)
	panel.scrollPos 	= panel.scrollPos+panel.scrollSpeed
	panel.scrollPos 	= mc(0,panel.scrollPos,math.max(panel.animation.length*panel.frameWidth-panel.width/2,0),4)
	
end

function editor.timelineSliders(panel)
	if panel.exporting  then return end
	gfx.fontSize(9)
	panel.fpsSlider = panel.fpsSlider or { 	
			align = "center",
			height 	= panel.row-4,
			pct 	= (panel.animation.fps-1)/59,
			state 	= "non",
			opacity = 1,
			col 	= {r=0.05,g=0.05,b=0.05},
			text 	= "fps",
			sliding = false,
			click = function() panel.fpsSlider.sliding = true  end
	} 
	panel.sizeSlider = panel.sizeSlider or { 	
			align = "center",
			height 	= panel.row-4,
			pct 	= editor.debug.timelineZoom or 0.5,
			state 	= "non",
			opacity = 1,
			col 	= {r=0.05,g=0.05,b=0.05},
			text 	= "zoom",
			sliding = false,
			click = function() panel.sizeSlider.sliding = true  end
	} 


	mouse.pushRelease 	(function() 	
		panel.fpsSlider.sliding = false 
		panel.sizeSlider.sliding = false 
	end)

	panel.fpsSlider.width 		= mc(0, (panel.layerWidth)/2.1, 150)
	panel.fpsSlider.x 			= panel.x 
	panel.fpsSlider.y 			= panel.y+panel.height
	panel.fpsSlider.pct 		= panel.fpsSlider.sliding and mc(0,(mouse.x-panel.fpsSlider.x)/panel.fpsSlider.width,1)  or panel.fpsSlider.pct 
	if panel.anims[panel.anim].fps ~= round(1+panel.fpsSlider.pct*59,0) then 
		log(panel.time)
		panel.time = panel.currentFrame/round(1+panel.fpsSlider.pct*59,0)
		log(panel.time)
	end
	panel.anims[panel.anim].fps = round(1+panel.fpsSlider.pct*59,0)
	panel.fpsSlider.text 		= "fps: "..panel.anims[panel.anim].fps


	panel.sizeSlider.width 		= mc(0, (panel.layerWidth)/4, 150)
	panel.sizeSlider.x 			= panel.x+panel.layerWidth-	panel.sizeSlider.width-2
	panel.sizeSlider.y 			= panel.y+panel.height
	panel.sizeSlider.pct 		= panel.sizeSlider.sliding and mc(0.05,(mouse.x-panel.sizeSlider.x)/panel.sizeSlider.width,1)  or panel.sizeSlider.pct 
	panel.frameWidth  			= 6+panel.sizeSlider.pct*11
	editor.debug.timelineZoom = panel.sizeSlider.pct
	
	editor.drawButton( panel.fpsSlider)
	editor.drawButton( panel.sizeSlider)
end  

function editor.timelineOnionIndicator(panel)
	panel.onion.x = panel.x+ (panel.layerWidth)/1.62-13
	panel.onion.y = panel.y+panel.height-3
	if mouseIn({x=panel.onion.x-15,y=panel.onion.y,w=50,h=20}) then 
		editor.setToolTip("Onion Skin")
	end
	gfx.setColor(1,1,1,panel.onion.enabled and 0.6 or 0.1)
	gfx.draw(getImage("onionIcon"),panel.onion.x,panel.onion.y	,0,0.7,0.7)
		
	local bef,aft = panel.onion.before.tint,panel.onion.after.tint
	gfx.setColor(0,0,0,panel.onion.enabled 	and 0.8 or 0)
	gfx.draw(getImage("playIcon"),panel.onion.x-1,	panel.onion.y+3,0,-0.5,0.5)
	gfx.setColor(bef.r,bef.g,bef.b,(panel.onion.enabled and panel.onion.before.enabled) 	and 1 or 0.1)
	gfx.draw(getImage("playIcon"),panel.onion.x-2,	panel.onion.y+4,0,-0.4,0.4)

	gfx.setColor(0,0,0,panel.onion.enabled 	and 0.8 or 0)
	gfx.draw(getImage("playIcon"),panel.onion.x+24,panel.onion.y+3,0,0.5,0.5)
	gfx.setColor(aft.r,aft.g,aft.b,(panel.onion.enabled and panel.onion.after.enabled ) 	and 1 or 0.1)
	gfx.draw(getImage("playIcon"),panel.onion.x+25,panel.onion.y+4,0,0.4,0.4)
end

function editor.timelineAudio(panel)
	if not panel.animation.audio then return end
	panel.audioButton  = {
		text="audio: "..(panel.animation.audio or "none"),
		y=panel.y-2,
		x=panel.x+panel.layerWidth-100,
		w=100,
		h=panel.row-4,
		tip="Drag an mp3 or ogg into the window",
		func = function()
			panel.mute = not panel.mute
			afx.setVolume( panel.mute and 0 or 1 )
		end
	}

	editor.drawButton(panel.audioButton)

	

end

function editor.resetTimlineHeight(panel)
	panel.savedHeight = panel.height
end

function editor.timelineTitleBottomToggle(panel)

	-- DROP IT
	panel.docked = not panel.bottom
	drawingPanel.bottom = panel.bottom
	if panel.bottom then 
		if not panel.sizeSlider or not panel.sizeSlider.sliding then 
			panel.width = panel.l.remodel and panel.layerWidth or
				mc(panel.fullWidth and screenWidth-4 or  panel.minWidth, panel.layerWidth+panel.animation.length*panel.frameWidth,screenWidth-4)
		end
		--panel.height = math.max(drawingPanel.height,panel.height)
		panel.y 	= panel.visible and easeTo(panel.y, screenHeight-panel.savedHeight+(panel.l.remodel and panel.row or 0),panel.hideSpeed) or easeTo(panel.y, screenHeight+5,panel.hideSpeed)
		panel.x 	= 2
	else 
		panel.y 	= panel.y+2
	end

	-- OTHER STUFF
	panel.sy 		=  panel.y+sidebar.titleH
	panel.height  	= 0

	if  panel.exporting then 
		return 
	end
	-- TITLE  
	gfx.setFont(fonts.inconsolata,11)

	local tWidth = gfx_copy.currentFont:getWidth(panel.animation.name)+16
	
	if  panel.l.remodel then  panel.titleButton = nil return end
	panel.titleButton = {
		align 	= 	"left",
		col    = {a=1},
		release = 	 function()
			if not panel.listOpen then 
				local items = {}
				for a,anim in pairs(panel.anims) do 
					local current = (panel.anim == anim.key)
					table.insert(items, {
						--not current and {	size=1, name="-",align="center", 	 col = {r=200,g=50,b=50,a=100}, func = function() editor.deleteAnimation(panel.key,anim.key) return "remove" end } or {	size=0,name="",},
						{ 	size = 1, name="", a=a, align="center", func= function() objects[panel.key].default=a; return "" end, update = function(x) x.name = (panel.object.default==x.a) and "»" or "•" end  },
						{ 	size = 7, name=anim.name, tcol=current and {a=1} or nil, func = not current and function()  editor.switchAnimation(a)  return "" end},
						{	size=1, name="···", align="center",	 col = {r=0,g=0,b=0,a=0.5}, func = function() editor.renameAnimation(panel.key,anim.key) return "rename" end } ,
						-- {	size=1, name="D", align="center",	col = {r=0.1,g=0.2,b=0.4,a=0.9}, func = function() editor.newAnimation(nil,true) end } ,
					}) 
				end
				table.insert(items, {name="New "..(level.isAnim and "Cut" or "Animation"), func = editor.newAnimation, update=function() panel.listOpen = true end ,col={r=0.3,g=0.8,b=0.35,a=0.4}})

				editor.openContextMenu (items,{x=panel.x-8,y=(panel.bottom and panel.y-(lume.count(panel.anims)+1.7)*20 or panel.y+panel.height+sidebar.titleH/2),width=200})
			end
		end
	}
	
	panel.titleButton.text 	= ellipses(panel.animation.name,math.min(200,panel.width/3))
	panel.titleButton.w 		=	math.min(tWidth,panel.width/3) 
	panel.titleButton.x 		=	panel.x
	panel.titleButton.y 		=	panel.y-2
	panel.titleButton.h 		= sidebar.titleH or panel.row


	panel.splitButton =  {
		align 	= 	"center",
		release = 	 function()
			panel.object.splitFrames = not panel.object.splitFrames
		end
	}
	
	-- panel.splitButton.text 	= panel.object.splitFrames and "split" or "sheet"
	-- panel.splitButton.w 		= 50
	-- panel.splitButton.h 		= panel.titleButton.h
	-- panel.splitButton.x 		=	panel.x + (panel.layerWidth or panel.baseLayerWidth)
	-- panel.splitButton.y 		=	panel.titleButton.y

	-- editor.drawButton(panel.splitButton)
	panel.listOpen = false 


	-- PLAYING INDICATOR
	if panel.playing and panel.animation.length==1 then 
		gfx.fontSize(12)
		gfx.printf("playing...",panel.x+panel.layerWidth,panel.y,100,"left")
	end--
end