plugin modifier NeckLaceMakerModifier
name:"Necklace Maker"
classID:#(0x73312119, 0x032233501)
extends:edit_spline
replaceui:true
(
	fn getTheSpline=
	(

			theClass=this
			if(theCLass!=undefined) then
			(
				theParent=(for it in (refs.dependents theClass) where isvalidnode it collect it)[1]
			)
			
			theParent
	)
	
	fn updateThem =
	(
		
		theParent=getTheSpline()

		
		if(theParent!=undefined) then
		(
			theLength=curveLength theParent 1
			theDistance=this.initialOffset
			
			theNodes=for it in theParent.children where getUserProp it "timeStamp"==this.theId collect it
		
			theAngle=[this.initXRotate,this.initYRotate,this.initZRotate]
			theScale=[this.uscale/ 100.0, this.uscale/ 100.0, this.uscale/ 100.0]
			
			seed 100.0
			for i=1 to theNodes.count do
			(
				theCopy=theNodes[i]
				
				theAngle=theAngle+[this.xRotate,this.yRotate,this.zRotate]
				addAngle=[0.0,0.0,0.0]
				if((mod i 2)==0.0 )then
				(	
					addAngle=[this.xOtherRotate,this.yOtherRotate,this.zOtherRotate]
				)
				addAngle+=[(random -this.xRandRotate this.xRandRotate),(random -this.yRandRotate this.yRandRotate),(random -this.zRandRotate this.zRandRotate)]
				
				theScale*=(this.incScale/100.0)
				theScaleAdd=theScale+((random -this.randScale this.randScale)/100.0)
				
				theDistance+=(100*this.distanceOffset/theLength) * (100*theScale[1]/this.uScale)
				
				theCopy.rotation=(eulerangles (theAngle[1]+addAngle[1]) (theAngle[2]+addAngle[2]) (theAngle[3]+addAngle[3]))
				theCopy.scale=theScaleAdd
				theCopy.objectoffsetpos=[this.xOffset,this.yOffset,this.zOffset]

				theCopy.pos.controller.percent =amin#(theDistance,100.0)
				theCopy.pos.controller.Follow=this.followOn
				
				theCopy.pos.controller.axis=this.axis-1
				theCopy.pos.controller.axisFlip = this.flipOn
				theCopy.pos.controller.bank = this.bank
				theCopy.pos.controller.bankAmount =this.bankAmount 
				theCopy.pos.controller.smoothness=this.smoothness
				
			)
		)
	)

	parameters main rollout:params
	(
		
		distanceOffset type:#float ui:distanceOffsetSpr default:1.0 
		count type:#integer ui:countSpr
		theNode type:#node
		initialOffset type:#float ui:initialOffsetSpr
		theId type:#integer
		uScale type:#float ui:uScaleSpr default:100.0
		incScale type:#float ui:incScaleSpr default:100.0
		randScale type:#float ui:randScaleSpr default:0.0
		
		xOffset type:#float ui:xOffsetSpr default:0.0
		yOffset type:#float ui:yOffsetSpr default:0.0
		zOffset type:#float ui:zOffsetSpr default:0.0
		
		initXRotate type:#float ui:xInitRotateSpr default:0.0
		initYRotate type:#float ui:yInitRotateSpr default:0.0
		initZRotate type:#float ui:zinitRotateSpr default:0.0
		xRotate type:#float ui:xRotateSpr default:0.0
		yRotate type:#float ui:yRotateSpr default:0.0
		zRotate type:#float ui:zRotateSpr default:0.0
		xOtherRotate type:#float ui:xOtherRotateSpr default:0.0
		yOtherRotate type:#float ui:yOtherRotateSpr default:0.0
		zOtherRotate type:#float ui:zOtherRotateSpr default:0.0
		xRandRotate type:#float ui:xRandRotateSpr default:0.0
		yRandRotate type:#float ui:yRandRotateSpr default:0.0
		zRandRotate type:#float ui:zRandRotateSpr default:0.0

		followOn type:#boolean ui:followOnChk default:true
		flipOn type:#boolean ui:flipOnChk default:false
		axis type:#integer ui:axisRadio default:1
		
		
		bank type:#boolean ui:bankChk default:false
		bankAmount type:#float ui:bankAmountSpr default:0.5
		smoothness type:#float ui:smoothnessSpr default:0.5
		wireColor type:#Color ui:wireColorPrk default:(color 28 89 177)

		
		on distanceOffset set value do
		(
			updateThem()
		)
		on uscale set value do 	updateThem()
		on incScale set value do updateThem()
		on randScale set value do updateThem()
		
		on count set value do
		(
			theParent=getTheSpline()
			with undo off
			(
				if(isvalidnode theParent) and (isvalidnode theNode) then
				(
					theNodes=for it in theParent.children where getUserProp it "timeStamp"==theId collect it
					if(theNodes.count>count) then
					(	for i=1 to (theNodes.count-count) do
							delete theNodes[i]
					)
					else if(theNodes.count<count) then
					(
						for i=1 to (count-theNodes.count) do
							(
								theCopy=instance theNode
								theCopy.parent=theParent
								theCopy.pos.controller = Path_Constraint ()
								theCopy.pos.controller.Path=theParent
								theCopy.pos.controller.Follow = on
								theParent.layer.addnode theCopy
								deleteKeys 	theCopy.pos.controller.percent.keys #allkeys
								setUserProp theCopy "timeStamp" theId
								theCopy.wireColor=this.wireColor

							)
						
					)
					
					updateThem()
					
				)
			)

		)

		on initialOffset set value do updateThem()
		
		on xOffset set value do updateThem()
		on yOffset set value do updateThem()
		on zOffset set value do updateThem()
		
		on initxRotate set value do updateThem()		
		on inityRotate set value do updateThem()
		on initzRotate set value do updateThem()
		
		
		on xRotate set value do updateThem()		
		on yRotate set value do updateThem()
		on zRotate set value do updateThem()
		
				
		on xOtherRotate set value do updateThem()		
		on yOtherRotate set value do updateThem()
		on zOtherRotate set value do updateThem()
		
		on xRandRotate set value do updateThem()		
		on yRandRotate set value do updateThem()
		on zRandRotate set value do updateThem()
		
			
		on followon set value do updateThem()
		on flipOn set value do updateTHem()
		on axis set value do updateThem()
		
		
		on bank set value do updateThem()
		on bankAmount set value do updateThem()
		on smoothness set value do updateThem()
		on wireColor set value do
		(
			theParent=getTheSpline()
			if( isvalidnode theParent) then
				theNodes=for it in theParent.children where getUserProp it "timeStamp"==theId do it.wireColor=wireCOlor
			
		)
		

	)
	
	rollout params "spline" width:379 height:723
	(
		checkbutton pickTheNode "Pick The Bead" pos:[4,7] width:151 height:21
		spinner distanceOffsetSpr "   Spacing" pos:[50,50] width:104 height:16 range:[0,10000,0] type:#float
		spinner countSpr "Count" pos:[72,31] width:82 height:16 range:[0,10000,0] type:#integer
		spinner initialOffsetSpr "  Start Offset" pos:[39,70] width:115 height:16 range:[-100000,10000,0] type:#float
		spinner uScaleSpr "Uniform Scale" pos:[32,306] width:122 height:16 range:[-100000,10000,0] type:#float
		spinner incScaleSpr "Incremental Scale" pos:[13,324] width:141 height:16 range:[-100000,10000,0] type:#float
		spinner xOffsetSpr "X" pos:[14,105] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner yOffsetSpr "Y" pos:[65,105] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner zOffsetSpr "Z" pos:[116,105] width:40 height:16 range:[-100000,10000,0] type:#float
		
		spinner xInitRotateSpr "X" pos:[14,145] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner yInitRotateSpr "Y" pos:[64,145] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner zinitRotateSpr "Z" pos:[115,145] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner xRotateSpr "X" pos:[14,186] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner yRotateSpr "Y" pos:[64,186] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner zRotateSpr "Z" pos:[114,186] width:40 height:16 range:[-100000,10000,0] type:#float
		
		button makeToMesh "Convert To Mesh" pos:[53,499] width:98 height:21
		checkbox followOnChk "Follow" pos:[22,383] width:54 height:15
		button deleteButton "Delete" pos:[5,498] width:47 height:21
		GroupBox grp1 "Initial Rotation" pos:[3,130] width:154 height:40
		radiobuttons axisRadio "" pos:[13,462] width:97 height:16 labels:#("X", "Y", "Z") columns:3
		GroupBox grp6 "Axis" pos:[4,443] width:157 height:37
		checkbox flipOnChk "Flip" pos:[113,462] width:37 height:13
		GroupBox grp2 "Incremental Rotation" pos:[3,172] width:154 height:40
		GroupBox grp3 "Utility" pos:[3,485] width:158 height:61
		GroupBox grp7 "Pivot Offset" pos:[3,89] width:155 height:41
		label lbl1 "Lukas Lepicovsky, 2008" pos:[16,560] width:130 height:17
		HyperLink lbl2 "Lukashi.com" pos:[16,574] width:116 height:18 address:"http://www.lukashi.com"
		HyperLink lbl3 "Lukashi@gmail.com" pos:[16,590] width:116 height:18 address:"mailto:lukashi@gmail.com"
		
		GroupBox grp12 "Created By" pos:[3,547] width:159 height:60
		checkbox bankChk "Bank" pos:[82,382] width:79 height:18
		spinner bankAmountSpr "Bank Amount" pos:[21,403] width:112 height:16
		spinner smoothnessSpr "Smoothness" pos:[27,421] width:106 height:16 range:[0,100,0]
		GroupBox grp21 "Path Options" pos:[5,365] width:157 height:79
		GroupBox grp29 "" pos:[2,-4] width:155 height:93
		button fitButton "Auto" pos:[33,32] width:30 height:14
		button reactorButton "Prep For Reactor" pos:[52,522] width:97 height:20
		GroupBox grp9 "Every Other Rotation" pos:[3,213] width:154 height:40
		spinner xOtherRotateSpr "X" pos:[14,227] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner yOtherRotateSpr "Y" pos:[64,227] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner zOtherRotateSpr "Z" pos:[114,227] width:40 height:16 range:[-100000,10000,0] type:#float
		
		GroupBox grp19 "Random Rotation" pos:[2,249] width:154 height:40
		spinner xRandRotateSpr "X" pos:[13,267] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner yRandRotateSpr "Y" pos:[63,267] width:40 height:16 range:[-100000,10000,0] type:#float
		spinner zRandRotateSpr "Z" pos:[113,267] width:40 height:16 range:[-100000,10000,0] type:#float
		colorPicker wireColorPrk "" pos:[2,522] width:50 height:20
		
		spinner randScaleSpr "Random Scale" pos:[28,343] width:125 height:16 range:[-100000,10000,0] type:#float
		GroupBox grp60 "Scale" pos:[3,290] width:156 height:73
		groupBox grp121 "Tip" pos:[3,609] width:164 height:73
		label lbl32 "Reset the transfrom of the bead and spline before applying this modifier.  Utilities->Reset Xform" pos:[12,627] width:148 height:52
		
		fn activeButton=
		(
			if(isvalidnode theNode) then
				pickTheNode.text=theNode.name
			
			 distanceOffsetSpr.enabled=(isvalidnode theNode)
			 countSpr.enabled=(isvalidnode theNode)
		)





		on params open do
		(
			activeButton()
		)
		on pickTheNode changed state do
		(
			global zztheOriginal=getTheSpline()
			theNode=pickObject filter:(fn filt obj= obj!=zztheOriginal)
			if(theNode !=undefined) then
			(	
				
				count=0
				x=nodeLocalBoundingBox theNode
				
				distanceOffset=abs(x[1][1]- x[2][1])
				splineLength= curveLength (getTheSpline()) 1
				count=(splineLength/distanceOffset) as integer
				activeButton()
			)
			pickTheNode.state=false
		)
		on makeToMesh pressed do
		(
			theParent=getTheSpline()
			if(theParent!=undefined) then
			(
				theNodes=for it in theParent.children where getUserProp it "timeStamp"==this.theId collect it
				if(theNodes.count > 1) then
				(
					convertToMesh theNodes[1]
					for i=2 to theNodes.count do
					(
						attach theNodes[1] theNodes[i]
					)
					setUserProp theNodes[1] "timeStamp" "-1"
					count=0
				)
			)
			---
		)
		on deleteButton pressed do
		(
			this.count=0
			theClass=(this)
			
			deleteModifier (getTheSpline()) theClass
		)
		on fitButton pressed do
		(
			theSpline=getTheSpline()
			len=curveLength theSpline 1
			num=((len-initialOffset)/distanceOffset) as integer
			if(num < 0) then num=0
			
			flag=true
			if(num>400) then flag=QueryBox (num as string + " instances will be created, continue?")
			
			if(flag) then
				count = num+1
			
			
		)
		on reactorButton pressed do
		(
			theSpline=getTheSpline()
			if(isvalidnode theSpline) then
			(
				 
				addmodifier theSpline (normalize_Spl())
				theSpline.modifiers[1].length = (curveLength theSpline 1)/15.0
				addmodifier theSpline (reactor_Rope ())
				theSpline.modifiers[1].type = 1
		
				
				theSpline.modifiers[1].thickness=(curveLength theSpline 1)/50.0
				theNodes=for it in theSpline.children where getUserProp it "timeStamp"==theId collect it
				if(isvalidnode theNodes[1]) then
					theSpline.modifiers[1].thickness=(distance (nodeLocalBoundingBox theNodes[1])[1] (nodeLocalBoundingBox theNodes[1])[2])/2.0
				
				rpL=for it in $objects where iskindof it RPCollection collect it
				rp=rpL[1]
				if not (rp!=undefined) then
					rp=RPCollection()
				rp.ropes=append rp.ropes theSpline
			)
			
		)
	)

	on create do
	(
		theId=timeStamp()
		subobjectLevel = 0
		print "Created"
	)
	on clone original do
	(
		for it in $objects[$objects.count].modifiers where (iskindof it NeckLaceMakerModifier ) do
		(
			back=it.count
			it.count=0
			it.count=back
		)
		
	)

	on deleted do
	(
		print "Deleted"
	)
	
)
