-- Lorenz Attractor by Jerry Ylilammi

-- #############################################################################################
-- #################################/ Reset                    \################################
-- #############################################################################################

global lorenzAttractor
try(destroyDialog lorenzAttractor)catch()

-- #############################################################################################
-- #################################/ Rollout definition       \################################
-- #############################################################################################

rollout lorenzAttractor "Lorenz Attractor" width:130 (
	-- #################### // User interface \\ ####################
	group "Parameters" (
		spinner sp_A "A" range:[0,1000,10] type:#Float
		spinner sp_B "B" range:[0,1000,28] type:#Float
		spinner sp_C "C" range:[0,1000,(8./3)] type:#Float
	)
	
	group "Starting point" (
		spinner sp_X "X" range:[-10000,10000,.1] type:#Float
		spinner sp_Y "Y" range:[-10000,10000,.1] type:#Float
		spinner sp_Z "Z" range:[-10000,10000,.1] type:#Float
	)

	group "Final" (
		spinner knots "Knots" range:[1,100000,1000] type:#Integer
		spinner iter "Iterations" range:[1,100,1] type:#Integer
	)

	group "Preview" (
		spinner knots_P "Knots" range:[1,100000,1000] type:#Integer
		spinner iter_P "Iterations" range:[1,100,1] type:#Integer
	)

   checkbutton preview "Preview" across:2 toolTip:""
	button create "Create" toolTip:""

   -- #################### // Variables \\ ####################
	local a = 10
	local b = 28
	local c = 8./3
	local scale = .018
	local previewObject = undefined

	-- #################### // Functions \\ ####################
	fn Lorenz p = ( [p.x+(a*(p.y - p.x))*scale, p.y+(p.x*(b-p.z)-p.y)*scale, p.z+(p.x*p.y-p.z*c)*scale] )

	fn createLorenz spline start numKnots numIter = (
		local p3 = start
		for i in 1 to numKnots do (
			for j in 1 to numIter do p3 = Lorenz p3
			addKnot spline 1 #smooth #curve p3
		)
	)

	-- Updates preview
	fn update = (
		try(delete previewObject)catch()
		if preview.checked then (
			disableSceneRedraw()
			local startingPoint = [sp_X.value, sp_Y.value,sp_Z.value]
			local spline = SplineShape()
			spline.wirecolor = (color 8 8 136)
			spline.steps = 2
			addNewSpline spline
	     	createLorenz spline startingPoint knots_P.value iter_P.value
			updateShape spline
			freeze spline
			spline.showFrozenInGray = false
			previewObject = spline
			enableSceneRedraw()
		)
	)

	-- #################### // Events \\ ####################
	on create pressed do undo off (
		disableSceneRedraw()
      preview.checked = false
      update()
		local startingPoint = [sp_X.value, sp_Y.value,sp_Z.value]
		local spline = SplineShape()
		spline.wirecolor = (color 8 8 136)
		spline.steps = 2
		addNewSpline spline
     	createLorenz spline startingPoint knots.value iter.value
		updateShape spline
		enableSceneRedraw()
	)
	
	-- Triggers to update preview
	on sp_A changed val do (a=val;update())
	on sp_B changed val do (b=val;update())
	on sp_C changed val do (c=val;update())
	on sp_X changed val do (update())
	on sp_Y changed val do (update())
	on sp_Z changed val do (update())
	on knots_P changed val do (update())
	on iter_P changed val do (update())
	on preview changed val do (update())
)

-- #############################################################################################
-- #################################/ Initialize               \################################
-- #############################################################################################

CreateDialog lorenzAttractor style:#(#style_toolwindow, #style_sysmenu)
