-- ActorFrame name, used for controlling the children from control actor (in FG).
local name = 'section4'

local base_param = ...
local sw,sh,scx,scy,songdir,rr,am,bt,hs,pe,hr,ease,wratio,hratio,paraph = base_param.sw,base_param.sh,base_param.scx,base_param.scy,base_param.songdir,base_param.rr,base_param.am,base_param.bt,base_param.hs,base_param.pe,base_param.hr,base_param.ease,base_param.wratio,base_param.hratio,base_param.paraph

-- Camera manipulation table
local Cameras = {
	Name=name,
	Tween={
		{10560, 'queuecommand', 'AddInputHandler'},
		{12012, 'queuecommand', 'DenaulayStart'},
		{12024, 'queuecommand', 'Divide'},
		{12036, 'queuecommand', 'Divide'},
		{12048, 'queuecommand', 'Divide'},
		{12060, 'queuecommand', 'Divide'},
		{12072, 'queuecommand', 'Divide'},
		{12084, 'queuecommand', 'Divide'},
		{12096, 'queuecommand', 'Parin'}
	}
}

-- Children manipulation table
local Actors = {
	Name=name,
	Tween={
		{'texture/contents/Frame1', 10176, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame2', 10188, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame3', 10200, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame4', 10212, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame5', 10224, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame6', 10236, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Frame7', 10248, 'queuecommand', 'MakeFrame'},
		{'texture/contents/Key1', 10272, {10320, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key2', 10284, {10332, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key3', 10296, {10344, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key4', 10308, {10356, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key5', 10320, {10368, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key6', 10332, {10380, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key7', 10344, {10392, 'accelerate', 'diffusealpha', 0, 1}},
		{'texture/contents/Key1', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key2', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key3', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key4', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key5', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key6', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture/contents/Key7', 10512, {10560, 'accelerate', 'diffusealpha', 1, 0}},
		{'texture', 12012, 'visible', false},
		{'texture', 12012+1, 'visible', true},
		{'texture', 12024, 'visible', false},
		{'texture', 12024+1, 'visible', true},
		{'texture', 12036, 'visible', false},
		{'texture', 12036+1, 'visible', true},
		{'texture', 12048, 'visible', false},
		{'texture', 12048+1, 'visible', true},
		{'texture', 12060, 'visible', false},
		{'texture', 12060+1, 'visible', true},
		{'texture', 12072, 'visible', false},
		{'texture', 12072+1, 'visible', true},
		{'texture', 12084, 'visible', false},
		{'texture', 12084+1, 'visible', true},
		{'texture', 12096, 'visible', false},
	}
}

local Players = {
	Tween={
	}
}

-- Shortcut to the 'FG' ActorFrame.
local FG

-- Input Handler.
local InputHandler = function(event)
	if not event then return end

	local a = FG:GetChild('elements'):GetChild('section4'):GetChild('texture'):GetChild('contents')
	if event.type == 'InputEventType_FirstPress' then
		if string.find(event.button, 'Key%d') then
			local key = string.match(event.button, 'Key(%d)')
			a:GetChild('Key'..key):finishtweening():diffusealpha(1)
			a:GetChild('Frame'..key):queuecommand('Do')
		elseif event.button == 'Scratch up' then
		elseif event.button == 'Scratch down' then
		end
	elseif event.type == 'InputEventType_Release' then
		if string.find(event.button, 'Key%d') then
			local key = string.match(event.button, 'Key(%d)')
			a:GetChild('Key'..key):accelerate(bt):diffusealpha(0)
		end
	end
end


------------------------------------------------Delaunay Triangulation-----------------------------------------------

local primes = {2,3,5,7,11,13,17,19,23,29}
local rratio = 0.9
local function vdC(i, base)
	local h = 0
	local bk = 1/base

	while i > 0 do
		h = h + paraph.fmod(i, base) * bk
		i = math.floor(i/base)
		bk = bk/base
	end
	return h
end

local function hammersley(n, prime)
	local h = {}
	local p = {primes[prime[1]], primes[prime[2]]}
	for j = 1, n do
		table.insert(h, {vdC(j, p[1])*rratio+math.random(0,100)/100*(1-rratio)-0.5, vdC(j, p[2])*rratio+math.random(0,100)/100*(1-rratio)-0.5})
	end
	return h
end

-- "triangle"s are given as {{x1, y1}, {x2, y2}, {x3, y3}} (x1 < x2 < x3)
-- "edge"s are given as {{x1, y1}, {x2, y2}} (x1 < x2)
-- "vert"s are given as {x1, y1}
local num = 32
local coords = hammersley(num, {math.random(1,5),math.random(6,10)})
local stack = {}
local itr = 1
local paraph_v = {}

local function getDistance(vert1, vert2)
	return ((vert1[1]-vert2[1])^2 + (vert1[2]-vert2[2])^2)^0.5
end

-- tri are given as {{x1, y1}, {x2, y2}, {x3, y3}}
local function getCircumscribed(tri)
	local a, c, e = tri[1][1], tri[2][1], tri[3][1]
	local b, d, f = tri[1][2], tri[2][2], tri[3][2]
	local x, y, l = 0, 0, 0
	y = ((e-a)*(a^2+b^2-c^2-d^2)-(c-a)*(a^2+b^2-e^2-f^2))/(2*(e-a)*(b-d)-2*(c-a)*(b-f))
	if c-a == 0 then
		x = (2*(b-f)*y-a^2-b^2+e^2+f^2)/(2*(e-a))
	else
		x = (2*(b-d)*y-a^2-b^2+c^2+d^2)/(2*(c-a))
	end
	l = ((a-x)^2+(b-y)^2)^0.5
	return {{x, y}, l}
end

-- divides paraph_v[i] = "tri" to three triangles using "vert"
local function divideTriangle(i, vert)
	local tri = paraph_v[i]
	local tri1 = {tri[1],tri[2],vert}
	local tri2 = {tri[2],vert,tri[3]}
	local tri3 = {vert,tri[3],tri[1]}
	table.sort(tri1, function(a,b) return (a[1] < b[1]) end)
	table.sort(tri2, function(a,b) return (a[1] < b[1]) end)
	table.sort(tri3, function(a,b) return (a[1] < b[1]) end)
	table.insert(paraph_v, tri1)
	table.insert(paraph_v, tri2)
	table.insert(paraph_v, tri3)
	table.remove(paraph_v, i)
end

-- search ID of triangle containing vert from v (array of triangles)
local function searchTriangle(vert, v)
	local found = false
	for i, tri in ipairs(v) do
		local Area = 0.5 *(-tri[2][2]*tri[3][1] + tri[1][2]*(-tri[2][1] + tri[3][1]) + tri[1][1]*(tri[2][2] - tri[3][2]) + tri[2][1]*tri[3][2])
		local s = 1/(2*Area)*(tri[1][2]*tri[3][1] - tri[1][1]*tri[3][2] + (tri[3][2] - tri[1][2])*vert[1] + (tri[1][1] - tri[3][1])*vert[2])
		local t = 1/(2*Area)*(tri[1][1]*tri[2][2] - tri[1][2]*tri[2][1] + (tri[1][2] - tri[2][2])*vert[1] + (tri[2][1] - tri[1][1])*vert[2])
		if 0 < s and s < 1 and 0 < t and t < 1 and 0 < 1-s-t and 1-s-t < 1 then
			found = true
			return i
		end
	end
	if not found then
		for i = 1, #v do
			local d = getDistance(getCircumscribed(v[i])[1], vert)
			if d < getCircumscribed(v[i])[2] then
				return i
			end
		end
	end
end

-- add edges of a triangle to "stack"
local function stackEdges(tri)
	table.insert(stack, {tri[1], tri[2]})
	table.insert(stack, {tri[1], tri[3]})
	table.insert(stack, {tri[2], tri[3]})
end

local function getstackedEdge(stack) if stack[1] then return stack[1] end end
local function removestackedEdge(stack) if stack[1] then table.remove(stack, 1) end end

-- find triangle containing edge from v. then flip AB to CD if d < abc
local function flipTriangle(edge)
	local tri1 = nil
	local tri2 = nil
	local t1, t2 = nil, nil
	local a, b, c, d = edge[1], edge[2], nil, nil

	for t = 1, #paraph_v do
		local tri = paraph_v[t]
		if edge[1] == tri[1] then
			if edge[2] == tri[2] then
				c = tri[3]
			elseif edge[2] == tri[3] then
				c = tri[2]
			end
		elseif edge[1] == tri[2] then
			if edge[2] == tri[3] then
				c = tri[1]
			end
		end
		if c then
			tri1 = {a, b, c}
			t1 = t
			table.remove(paraph_v, t)
			table.insert(paraph_v, tri)
			break
		end
	end
	for t = 1, #paraph_v-1 do
		local tri = paraph_v[t]
		if edge[1] == tri[1] then
			if edge[2] == tri[2] and tri[3] ~= c then
				d = tri[3]
			elseif edge[2] == tri[3] and tri[2] ~= c then
				d = tri[2]
			end
		elseif edge[1] == tri[2] then
			if edge[2] == tri[3] and tri[1] ~= c then
				d = tri[1]
			end
		end
		if d then
			tri2 = {a, b, d}
			table.remove(paraph_v, t)
			table.insert(paraph_v, tri)
			break
		end
	end

	if a and b and c and d then
		if getDistance(getCircumscribed(tri1)[1], d) < getCircumscribed(tri1)[2] then
			table.remove(paraph_v)
			table.remove(paraph_v)
			table.insert(paraph_v, {a, c, d})
			stackEdges(paraph_v[#paraph_v])
			table.remove(stack, #stack)
			table.sort(paraph_v[#paraph_v], function(a,b) return (a[1] < b[1]) end)
			table.insert(paraph_v, {b, c, d})
			stackEdges(paraph_v[#paraph_v])
			table.remove(stack, #stack)
			table.sort(paraph_v[#paraph_v], function(a,b) return (a[1] < b[1]) end)
		end
	end
end

local zratio = 2
local centerz = 90
local dist = sh/2
local thick = 96*zratio
local rot_m = 0.5
local amvs = Def.ActorFrame{InitializeCommand=function(self) end}
local w = {1,1,1,1}

for id = 1, #coords*2+1 do
	amvs[#amvs+1] = Def.ActorFrame{
		Name='fragment'..id,
		OnCommand=function(self) self:zoom(1/zratio) end,
		UpdateTrianglesMessageCommand=function(self)
			if paraph_v[id] then
				self['c'] = {(paraph_v[id][1][1]+paraph_v[id][2][1]+paraph_v[id][3][1])*sw/3, (paraph_v[id][1][2]+paraph_v[id][2][2]+paraph_v[id][3][2])*sh/3}
				self:align(self['c'][1],self['c'][2]):xy(self['c'][1]/zratio,self['c'][2]/zratio)
				for i = 1, self:GetNumChildren() do
					self:GetChild('amv'..i):queuecommand('SetTriangle')
				end
			end
			self:wag():bob():effectmagnitude(math.random(-6,6),math.random(-6,-6),math.random(-30,30)):effectperiod(math.random(16,32)*bt)
		end,
		ParinCommand=function(self)
			if self['c'] then
				local x, y = self['c'][1]/zratio, self['c'][2]/zratio
				if x == 0 then x = 0.001 end if y == 0 then y = 0.001 end
				local phi, psi = math.atan2(x, centerz), math.atan2(y, centerz)
				self:bezier(bt, {0,0, 0.05,0.8, 0.1,0.95, 1,1}):addx(dist*math.sin(phi)/2):addy(dist*math.sin(psi)/2):addz(-dist*math.cos(phi)/2)
				self:addrotationx(math.deg(phi)*rot_m):addrotationy(math.deg(psi)*rot_m):addrotationx(math.random(-120,120)/2)
				self:bezier(bt*1.5, {0,0, 0.45,0.1, 0.55,0.9, 1,1}):addx(dist*math.sin(phi)):addy(dist*math.sin(psi)):addz(-dist*math.cos(phi)*3)
				self:addrotationx(math.deg(phi)*rot_m):addrotationy(math.deg(psi)*rot_m):addrotationx(math.random(-120,120))
			end
		end,
		Def.ActorMultiVertex{
			Name='amv1',
			SetTriangleCommand=function(self)
				local v = {
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,0}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,0}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,0}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},	
				}
				self:SetVertices(v):SetDrawState{First=1, Num=-1, Mode='DrawMode_Triangles'}
				self:SetTexture(self:GetParent():GetParent():GetParent():GetChild('texture'):GetTexture())
			end,
		},
		Def.ActorMultiVertex{
			Name='amv2',
			SetTriangleCommand=function(self)
				local v = {
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,0}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,thick}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,0}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,thick}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,0}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},	
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,thick}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},	
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,0}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,thick}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
				}
				self:SetVertices(v):SetDrawState{First=1, Num=-1, Mode='DrawMode_QuadStrip'}
				self:diffuse(0.1,0.1,0.1,math.sqrt(id/(#coords*2+1))*0.75)
			end,
		},
		Def.ActorMultiVertex{
			Name='amv3',
			SetTriangleCommand=function(self)
				local v = {
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,thick}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,thick}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,thick}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,thick}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},	
				}
				self:SetVertices(v):SetDrawState{First=1, Num=-1, Mode='DrawMode_Triangles'}
				self:diffuse(0.7,0.7,0.75,(id/(#coords*2+1))^0.75*0.75)
			end,
		},
		Def.ActorMultiVertex{
			Name='amv4',
			SetTriangleCommand=function(self)
				local v = {
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,thick}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,thick}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,thick}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},	
				}
				self:SetVertices(v):SetDrawState{First=1, Num=-1, Mode='LineStrip'}:SetLineWidth(1*zratio)
				self:diffuse(1,1,1,math.sqrt(id/(#coords*2+1)))
			end,
		},
		Def.ActorMultiVertex{
			Name='amv5',
			SetTriangleCommand=function(self)
				local v = {
					{{(paraph_v[id][1][1])*sw*zratio, (paraph_v[id][1][2])*sh*zratio,0}, w, {(paraph_v[id][1][1]+0.5)*wratio, (paraph_v[id][1][2]+0.5)*hratio}},
					{{(paraph_v[id][2][1])*sw*zratio, (paraph_v[id][2][2])*sh*zratio,0}, w, {(paraph_v[id][2][1]+0.5)*wratio, (paraph_v[id][2][2]+0.5)*hratio}},
					{{(paraph_v[id][3][1])*sw*zratio, (paraph_v[id][3][2])*sh*zratio,0}, w, {(paraph_v[id][3][1]+0.5)*wratio, (paraph_v[id][3][2]+0.5)*hratio}},	
				}
				self:SetVertices(v):SetDrawState{First=1, Num=-1, Mode='LineStrip'}:SetLineWidth(1*zratio)
				self:diffuse(1,1,1,math.sqrt(id/(#coords*2+1)))
			end,
		},
	}
end

-- We can use "InitializeCommand" instead of usual "OnCommand", which is executed on the beginning of section.
-- This reduces that ridiculously large frame drop on beat 0.
return Def.ActorFrame{
Name=name,
InitCommand=function(self) FG = self:GetParent():GetParent() self:visible(false):zbuffer(1) end,
InitializeCommand=function(self)
	local c = FG:GetChild('Cameras')
	local a = FG:GetChild('Actors')
--	local plt = a[1].Tween
--	for i = 1, #Players do
--		plt[#plt+1] = Players[i]
--	end
	c[#c+1] = Cameras
	a[#a+1] = Actors
	self:fov(90)
	-- Reset the position of NoteField.
	FG:GetChild('PlayerAFTorig'):GetChild('Player'):addy(-PREFSMAN:GetPreference('VisualDelaySeconds')/(bt*GAMESTATE:GetSongOptionsObject('ModsLevel_Song'):MusicRate())*288)
	FG:GetChild('PlayerOrig'):GetChild('Combo'):visible(true)
	FG:GetChild('PlayerOrig'):GetChild('Judgment'):visible(true)
end,
DenaulayStartCommand=function(self)
	paraph_v = {{{(2^0.5)*math.cos(-math.pi/2),(2^0.5)*math.sin(-math.pi/2)},
				{(2^0.5)*math.cos(math.pi/6),(2^0.5)*math.sin(math.pi/6)},
				{(2^0.5)*math.cos(5*math.pi/6),(2^0.5)*math.sin(5*math.pi/6)}}}
	divideTriangle(1, coords[itr])
	itr = itr + 1
	Isstack = false
	self:queuecommand('Divide')
end,
DivideCommand=function(self)
	local id = searchTriangle(coords[itr], paraph_v)
	if id then
		stackEdges(paraph_v[id])
		divideTriangle(id, coords[itr])
		self:queuecommand('Solvestack')
	else
		MESSAGEMAN:Broadcast('UpdateTriangles')
	end
end,
SolvestackCommand=function(self)
	local s = getstackedEdge(stack)
	if s then 
		flipTriangle(s, paraph_v)
		removestackedEdge(stack)
	end
	if stack[1] then
		self:queuecommand('Solvestack')
	else
		itr = itr + 1
		if itr <= #coords then
			Isstack = false
			if itr == num/8 or itr == num*2/8 or itr == num*3/8 or itr == num*4/8 or itr == num*5/8 or itr == num*6/8 or itr == num*7/8 then
				MESSAGEMAN:Broadcast('UpdateTriangles')
			else
				self:queuecommand('Divide')
			end
		else
			MESSAGEMAN:Broadcast('UpdateTriangles')
		end
	end
end,
AddInputHandlerCommand=function(self)
	-- Load Input Handler.
	SCREENMAN:GetTopScreen():AddInputCallback(InputHandler)
end,
ParinCommand=function(self)
	SCREENMAN:GetTopScreen():RemoveInputCallback(InputHandler)
end,

paraph.AFT({})..{
	Name='texture',
	Def.ActorFrame{
		Name='contents',
		paraph.AFT({})..{
			Name='Pane',
			Def.ActorFrame{
				Def.Quad{
					Name='bg',
					InitializeCommand=function(self)
						self:zoomto(152*1.5+155*1.5,sh):diffuse(1,1,1,1)
					end
				},
				paraph.AMVQuad({})..{
					Name='NoteField',
					InitializeCommand=function(self)
						-- I know this is stupid but
						if pe[2] then self:addx(6) end
						self:SetTexture(FG:GetChild('PlayerAFTorig'):GetTexture())
						self:blend('BlendMode_InvertDest')
					end,
				},
				Def.Quad{
					Name='JudgeLine',
					InitializeCommand=function(self)
						self:zoomto((152+155)*1.5,4):xy(2,222):diffuse(1,1,1,1):blend('BlendMode_InvertDest')
					end
				},
				Def.Quad{
					InitializeCommand=function(self)
						self:zoomto(450,72):y(292):diffuse(0,0,0,1)
					end,
				},
				Def.Quad{
					InitializeCommand=function(self)
						self:zoomto(442,64):y(292):diffuse(1,1,1,1)
					end,
				},
				Def.Quad{
					InitializeCommand=function(self)
						self:horizalign('left'):xy(-219,292):zoomto(0,60):diffuse(0,0,0,1):queuecommand('Update')
					end,
					UpdateCommand=function(self)
						local pn = pe[1] and 0 or 1
						local life = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn):GetCurrentLife()
						local width = 438*life
						self:zoomto(width,60):sleep(rr):queuecommand('Update')
					end
				},
			},
		},
		paraph.AMVQuad({})..{
			Name='Key1',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy(-scx*3/6,scy/2):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key2',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy(-scx*2/6,-scy/3):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key3',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy(-scx*1/6,scy/2):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key4',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy(-scx*0/6,-scy/3):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key5',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy( scx*1/6,scy/2):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key6',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy( scx*2/6,-scy/3):zoom(1/3.05):diffusealpha(0)
			end
		},
		paraph.AMVQuad({})..{
			Name='Key7',
			InitializeCommand=function(self)
				self:SetTexture(self:GetParent():GetChild('Pane'):GetTexture())
				self:xy( scx*3/6,scy/2):zoom(1/3.05):diffusealpha(0)
			end
		},

		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame1', InitializeCommand=function(self) self:xy(-scx*3/6,scy/2) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame2', InitializeCommand=function(self) self:xy(-scx*2/6,-scy/3) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame3', InitializeCommand=function(self) self:xy(-scx*1/6,scy/2) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame4', InitializeCommand=function(self) self:xy(-scx*0/6,-scy/3) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame5', InitializeCommand=function(self) self:xy( scx*1/6,scy/2) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame6', InitializeCommand=function(self) self:xy( scx*2/6,-scy/3) end},
		loadfile(songdir..'fg/section4/frame.lua')(base_param)..{Name='Frame7', InitializeCommand=function(self) self:xy( scx*3/6,scy/2) end},
	},
},
paraph.AMVQuad({})..{
	InitializeCommand=function(self)
		self:SetTexture(self:GetParent():GetChild('texture'):GetTexture())
	end,
	ParinCommand=function(self) self:visible(false) end,
},
amvs,
}