'/// ChainCreater 1.0 for XSI 3.5+
'/// By Homam Bahnassi - In|Framez 2004
'--------------------------------------

set oSelection = CreateObject("XSI.Collection")
set oSelection = Application.Selection
if oSelection.count <> 0 then
	valid = GetParams(inRad, inSecRad, inLength, inRes)
	if valid = true then ChainMaker oSelection(0), inRad, inSecRad, inLength, inRes
else
	PickChainReturn = PickChain (pChainElement)
	if PickChainReturn = true then
		valid = GetParams(inRad, inSecRad, inLength, inRes)
		if valid = true then ChainMaker pChainElement, inRad, inSecRad, inLength, inRes
	end if
end if

function ChainMaker(pChainElement,inRad,inSecRad,inLength,inRes)
'-- Checking Input...
if pChainElement.Type <> "bone"_
and pChainElement.Type <> "eff"_
and pChainElement.Type <> "root" then
	PickChainReturn = PickChain (pChainElement)
	if PickChainReturn = false then exit function
end if

'-- Creating return collection...
set ChainMaker = CreateObject("XSI.Collection")

'-- Creating Base Element...
set baseChainElement = CreateChainElement(inRad,inSecRad,inLength,inRes)
ChainMaker.Add baseChainElement

'-- Get Chain Root
set oChainRoot = pChainElement.Root
set oChainBones = oChainRoot.Bones
set oProgressBar = XSIUIToolkit.ProgressBar
oProgressBar.maximum = oChainBones.Count
oProgressBar.step = 1
oProgressBar.visible = true
oProgressBar.caption = "Processing Bones..."

for each oBone in oChainBones
	Logmessage "Duplicating..."
	set ClonedChains = CloneChain (oBone, baseChainElement, inSecRad, inLength)
	oProgressBar.caption = "Processing Bone:: " & oBone.Name
	oProgressBar.Increment

	for each ClonedChain in ClonedChains
		ChainMaker.Add ClonedChain
	next
next

end function

'-- Clone Base Element & Position it...
function CloneChain(Bone,BaseElement,SecRad,Length)
	set CloneChain = CreateObject("XSI.Collection")
	ParentObj Bone, BaseElement
	ResetTransform BaseElement, siObj, siSRT, siXYZ
	BaseElement.Kinematics.Global.Parameters("sclx").value = 1/Bone.Kinematics.Global.Parameters("sclx").value

	BoneLength = Bone.Parameters("length").value * Bone.Kinematics.Global.Parameters("sclx").value
	ChainCount = Round(BoneLength / length,0)
	for ChainIndex = 0 to ChainCount-1
		Switch = round(abs(sin(ChainIndex*1.5707963267948966192313216916398)))
		set ChainItemsCol = Clone(BaseElement, 1, siSharedParent,_
		siNoGrouping, siDuplicateProperties, siDuplicateAnimation,_
		siDuplicateConstraints, siNoSelection,siGlobalXForm,_
		1,1,1, 0,0,0, 0,0,0, True)
		set ChianItem = ChainItemsCol(0)
		ChianItem.Kinematics.Local.Parameters("posx").value = (1/Bone.Kinematics.Global.Parameters("sclx").value)*length*ChainIndex
		ChianItem.Kinematics.Local.Parameters("rotx").value = Switch*90
		ChianItem.Kinematics.Local.Parameters("sclx").value = 1/Bone.Kinematics.Global.Parameters("sclx").value
		CloneChain.Add ChianItem
	next
end function

function PickChain(ChainElement)
	PickChain = true
	logmessage "Please Select Chain Element..."
	PickElement "chain_element", "Select Chain Element", "Select Chain Element", ChainElement, Button
	if Button = 0 then
		logmessage "Cancelled By User"
		PickChain = false
	end if
end function

function CreateChainElement(rad,secrad,length,res)
	set CreateChainElement = CreatePrim ("Torus", "MeshSurface","Chain0")

	CreateChainElement.Parameters("radius").value = rad
	CreateChainElement.Parameters("sectionradius").value = secrad

	select case res
		case 0 '-- Low Resolution...
			CreateChainElement.Parameters("subdivu").value = 6
			CreateChainElement.Parameters("subdivv").value = 4
			Translate CreateChainElement & ".pnt[8-19]", length-rad, 0, 0, siRelative, siGlobal, siObj, siX
		case 1 '-- Medieum Resolution...
			CreateChainElement.Parameters("subdivu").value = 10
			CreateChainElement.Parameters("subdivv").value = 8
			Translate CreateChainElement & ".pnt[24-63]", length-rad, 0, 0, siRelative, siGlobal, siObj, siX
		case 2 '-- High Resolution...
			CreateChainElement.Parameters("subdivu").value = 18
			CreateChainElement.Parameters("subdivv").value = 16
			Translate CreateChainElement & ".pnt[80-223]", length-rad, 0, 0, siRelative, siGlobal, siObj, siX
	end select
end function

function GetParams(Radius, SecRadius, Length, Res)

	GetParams = false
	set oRoot = ActiveProject.ActiveScene.Root
	Set oDial = AddProp("Custom_Parameter_List", oRoot, , "General_Options").Value("Value")
	OptionSliders = oRoot & "." & oDial

	SIAddCustomParameter OptionSliders, "Radius", siDouble, 0.4, 0.001, 999.000,, siPersistable+siSilent  , 0.01, 10,, "Ring Radius"
	SIAddCustomParameter OptionSliders, "SecRadius", siDouble, 0.175, 0.001, 999.000,, siPersistable+siSilent  , 0.01, 10.000,, "Section Radius"
	SIAddCustomParameter OptionSliders, "Length", siDouble, 0.8, 0.001, 999.000,, siPersistable+siSilent, 0.01, 10.000,, "Ring Length"
	SIAddCustomParameter OptionSliders, "Resolution", siUByte, 0.000, 0.000, 2.000,, siPersistable+siSilent, 0.000, 2.000,, "Ring Resolution"
	
	on error resume next
	InspectObj OptionSliders ,,,SIModal

	if Err.Number <> 0 then
		DeleteObj OptionSliders
		exit function
	end if
	
	Radius = GetValue(OptionSliders & ".Radius")
	SecRadius = GetValue(OptionSliders & ".SecRadius")
	Length = GetValue(OptionSliders & ".Length")
	Res = GetValue(OptionSliders & ".Resolution")
	
	DeleteObj OptionSliders
	GetParams = true

end function