rollout WobbleRollOut "Wobble" rolledUp:true (
	-- init GUI
	include "$scripts\\pteroTools\\_propGroupUI.ms"
	label		lblAngl		"Angle:"														offset:[9,0]	align:#left	across:2
	label		lblSpd		"Speed:"														offset:[-7,0]	align:#right
	spinner		spnAnglX	"X:"		range:[0, 360, 0]	type:#float		FieldWidth:35	offset:[-5,0]	align:#left	across:3
	angle		angAnglX	""			range:[0, 360, 0]	dir:#ccw		diameter:17		offset:[-5,0]	align:#center		color:(color 255 255 0)
	spinner		spnSpdX		"X:"		range:[0, 999, 0]	type:#float		FieldWidth:35	offset:[5,0]
	spinner		spnAnglY	"Y:"		range:[0, 360, 0]	type:#float		FieldWidth:35	offset:[-5,0]	align:#left	across:3
	angle		angAnglY	""			range:[0, 360, 0]	dir:#ccw		diameter:17		offset:[-5,0]	align:#center		color:(color 255 255 0)
	spinner		spnSpdY		"Y:"		range:[0, 999, 0]	type:#float		FieldWidth:35	offset:[5,0]
	spinner		spnAnglZ	"Z:"		range:[0, 360, 0]	type:#float		FieldWidth:35	offset:[-5,0]	align:#left	across:3
	angle		angAnglZ	""			range:[0, 360, 0]	dir:#ccw		diameter:17		offset:[-5,0]	align:#center		color:(color 255 255 0)
	spinner		spnSpdZ		"Z:"		range:[0, 999, 0]	type:#float		FieldWidth:35	offset:[5,0]

	-- Init RollOut
	fn fnName		= WobbleRollOut
	fn fnLabel		= "Wobble"
 	fn fnKeyNames	= #( (fnLabel()) )
 	fn fnKeyUI		= #( #( spnAnglX, spnAnglY, spnAnglZ, spnSpdX, spnSpdY, spnSpdZ ) )
	fn fnAngUI		= #( #( angAnglX, angAnglY, angAnglZ ) )
 	fn fnKeyDef		= #( #( 0, 0, 0, 0, 0, 0) )
	fn fnUpdateAng	keyIDX:1 angUI:#(#()) keyUI:#(#()) c:3 = for n = 1 to c do try ( angUI[keyIDX][n].degrees = keyUI[keyIDX][n].value ) catch ()
	fn fnInitRollOut = (
		fnAppendRollOut (fnName()) (fnLabel())
	)
	
 	
	-- fnApply()
	fn fnApply obj keyIDX type acqObj = (
		local keys		= _keyTableDef (fnKeyNames()) (fnKeyUI()) (fnKeyDef())
		local keyArray	= _keyDef keys.names[keyIDX] (keys.names[keyIDX] + "=undefined") #("undefined")
		local angUI		= fnAngUI()
		
		-- SAVE PRESSET
		if type == #save do (
			----
			for n = 1 to 6 do keys.values[keyIDX][n] = keys.controls[keyIDX][n].value
			----
			fnSetDefs (keys.names[keyIDX] as string) (keys.values[keyIDX] as string)
			return true
		)

		if obj != undefined do (
			-- DELETE
			if type == #delete do (
				fnDeleteProp obj keys.names[keyIDX]
				type = #read
			)
			-- ACQUIRE or READ
			keyArray = fnReadProp (if type == #acquire then acqObj else obj) keys.names[keyIDX]
		)
		
		-- UPDATE UI
		if type == #read or type == #load or type == #acquire do (
			-- LOAD PRESSET
			if type == #load do keyArray.values = fnGetDefs keys.names[keyIDX]
			----
			for n = 1 to 6 do (
				if (keyArray.values[n] == "") or (keyArray.values[n] as string == "undefined") do
					keyArray.values[n] = keys.values[keyIDX][n]
				keys.controls[keyIDX][n].value = keyArray.values[n] as float
			)
			fnUpdateAng angUI:angUI keyUI:keys.controls
			----
			if type == #read do return true
			if btnAuto.checked do type = #write
		)

		-- WRITE
		if type == #write do (
			keyArray.keyName = keys.names[keyIDX]
			----
			type = #delete
			for n = 1 to 6 do (
				keyArray.values[n] = keys.controls[keyIDX][n].value as string
				if keys.controls[keyIDX][n].value > 1 do type = #write
			)
			----
			if obj != undefined do
				if type == #delete then
					fnDeleteProp obj keys.names[keyIDX]
				else
					fnWriteprop obj keyArray
			return true
		)
	)

	-- fnUpdate()
	fn fnUpdate keyIDX:1 type:#none acqObj:undefined inner:true = (
		if btnAuto.checked and type == #none do type = #write

		case selection.count of (
			0:		 fnApply undefined keyIDX type acqObj
			default: for obj in selection do fnApply obj keyIDX type acqObj
		)
			
		if inner or type == #acquire do _mainRollout.name.fnUtilize (fnName()) info:true
	)

	-- Event Handler
	on angAnglX			changed value	do (spnAnglX.value = value; fnUpdate())
	on spnAnglX			entered			do (angAnglX.degrees = spnAnglX.value; fnUpdate())
	on angAnglY			changed value	do (spnAnglY.value = value; fnUpdate())
	on spnAnglY			entered			do (angAnglY.degrees = spnAnglY.value; fnUpdate())
	on angAnglZ			changed value	do (spnAnglZ.value = value; fnUpdate())
	on spnAnglZ			entered			do (angAnglZ.degrees = spnAnglZ.value; fnUpdate())
	on spnSpdX			entered			do fnUpdate()
	on spnSpdY			entered			do fnUpdate()
	on spnSpdZ			entered			do fnUpdate()
	on btnSet			pressed			do fnUpdate type:#write
	on btnDef			pressed			do fnUpdate type:#load
	on btnSav			pressed			do fnUpdate type:#save
	on btnDel			pressed			do fnUpdate type:#delete
	on btnAcq			changed state	do fnAcquire (fnName())
	on WobbleRollOut	open			do fnOpenRollOut (fnName())
	on WobbleRollOut	close			do fnCloseRollOut (fnName())
)
