-- creation and function scripts for the Axis interpolator plugin
-- NB Ctrl+D will color script making it easier to read

	
-------------------

fn AutoAxisInterp obj =
	(
	-- legacy "do nothing" function
	return (eulerangles 0 0 0)
	)

fn AutoAxisInterpRotate obj =
	(
	-- if (classof obj != AxisInterpBox) do ( return (eulerangles 0 0 0) )
	if ((obj == undefined) or (obj.sib == undefined) or (obj.sib.parent == undefined)) do ( return (eulerangles 0 0 0) )

	parentSpace = obj.sib.parent.objectTransform
	siblingRotation = orthogonalize (obj.sib.transform * inverse parentSpace)

	array = #()

	array[1] = ((eulerangles obj.rotangles[1]  obj.rotangles[2]  obj.rotangles[3]) as quat)
	array[2] = ((eulerangles obj.rotangles[4]  obj.rotangles[5]  obj.rotangles[6]) as quat)
	array[3] = ((eulerangles obj.rotangles[7]  obj.rotangles[8]  obj.rotangles[9]) as quat)
	array[4] = ((eulerangles obj.rotangles[10] obj.rotangles[11]  obj.rotangles[12]) as quat)
	array[5] = ((eulerangles obj.rotangles[13] obj.rotangles[14]  obj.rotangles[15]) as quat)
	array[6] = ((eulerangles obj.rotangles[16] obj.rotangles[17]  obj.rotangles[18]) as quat)

	case obj.shear_axis of
		(
		1:	( dir = siblingRotation.row1 )
		2:	( dir = siblingRotation.row2 )
		3:	( dir = siblingRotation.row3 )
		)
		
	if (obj.dumpvalues) do print dir

	q1 = if dir.x > 0 then array[1] else array[2]
	q2 = if dir.y > 0 then array[3] else array[4]
	q3 = if dir.z > 0 then array[5] else array[6]

	a1 = abs dir.x
	a2 = abs dir.y
	a3 = abs dir.z

	q = slerp q2 q1 (a1 / (a1 + a2))
	q = slerp q q3 (a3 / (a1 + a2 + a3))

	--print q
	output = (normalize q) as eulerangles
	--print dir
	return output
	)


fn AutoAxisInterpPos obj =
	(
	-- if (classof obj != AxisInterpBox) do return [ 0, 0, 0 ]
	if ((obj == undefined) or (obj.sib == undefined) or (obj.sib.parent == undefined)) do ( return [ 0, 0, 0 ] )

	parentSpace = obj.sib.parent.objectTransform
	siblingRotation = orthogonalize (obj.sib.transform * inverse parentSpace)

	array = #()

	array[1] = [ obj.movements[1],  obj.movements[2],   obj.movements[3] ]
	array[2] = [ obj.movements[4],  obj.movements[5],   obj.movements[6] ]
	array[3] = [ obj.movements[7],  obj.movements[8],   obj.movements[9] ]
	array[4] = [ obj.movements[10], obj.movements[11],  obj.movements[12] ]
	array[5] = [ obj.movements[13], obj.movements[14],  obj.movements[15] ]
	array[6] = [ obj.movements[16], obj.movements[17],  obj.movements[18] ]

	case obj.shear_axis of
		(
		1:	( dir = siblingRotation.row1 )
		2:	( dir = siblingRotation.row2 )
		3:	( dir = siblingRotation.row3 )
		)
		
	p1 = if dir.x > 0 then array[1] else array[2]
	p2 = if dir.y > 0 then array[3] else array[4]
	p3 = if dir.z > 0 then array[5] else array[6]

	a1 = abs dir.x
	a2 = abs dir.y
	a3 = abs dir.z

	p = p1 * (a1 / (a1 + a2 + a3)) + p2 * (a2 / (a1 + a2 + a3)) + p3 * (a1 / (a1 + a2 + a3))

	return p + [ obj.basepos[1], obj.basepos[2], obj.basepos[3] ]
	)


fn AutoAxisAngleInit refObject =
	(
--	print "AutoAxisAngleInit"
--	print refObject.shear_type
	
	refObject.movements = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,     0, 0, 0,     0, 0, 0 )

	case refObject.shear_type of
		(
		1:	(
			-- R shoulder
			refObject.rotangles = #(  60, 0, 0,    0, 0, 180,    -45, 0, 90,    45, 0, -90,    0, -90, 0,    0, 90, -45 )
			refObject.shear_axis = 1
			)	
		6:	(
			-- L shoulder
			refObject.rotangles = #( -60, 0, 0,     0, 0, 180,    45, 0, 90,    -45, 0, -90,    0, -90, -45,    0, 90, 0 )
			refObject.shear_axis = 1
			)	
		2:	(
			-- R Bicep
			refObject.rotangles = #( 45, 0, 0,    -45, 0, 0,    0, 0, 0,     -90, 0, 0,    -45, 0, 0,    90, 0, 0 )
			refObject.shear_axis = 2
			)	
		7:	(
			-- L Bicep
			refObject.rotangles = #( -45, 0, 0,    45, 0, 0,	0, 0, 0,	 90, 0, 0,    -90, 0, 0,    45, 0, 0 )
			refObject.shear_axis = 2
			)	
		3:	(
			-- R Elbow
			refObject.rotangles = #( 0, 0, 0,     0, 0, -90,    0, 0, 0,     0, 0, -45,    0, 0, 0,      0, 0, 0 )
			refObject.shear_axis = 1
			)
		8:	(
			-- L Elbow
			refObject.rotangles = #( 0, 0, 0,     0, 0, -90,	0, 0, 0,	 0, 0, -45,    0, 0, 0,	     0, 0, 0 )
			refObject.shear_axis = 1
			)
		4:	(
			-- R Ulna
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      -45, 0, 0,    45, 0, 0 )
			refObject.shear_axis = 3
			)	
		9:	(
			-- L Ulna
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      45, 0, 0,     -45, 0, 0 )
			refObject.shear_axis = 3
			)	
		5:	(
			-- R Wrist
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      -90, 0, 0,    90, 0, 0 )
			refObject.shear_axis = 3
			)	
		10:	(
			-- L Wrist
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      90, 0, 0,     -90, 0, 0 )
			refObject.shear_axis = 3
			)	
		11:	(
			-- R Hip
			refObject.rotangles = #( 0, 0, -60,   0, 0, 0,      0, 0, -30,   0, 0, 45,     0, 0, 0,      0, 0, 0 )
			refObject.shear_axis = 1
			)	
		14:	(
			-- L Hip
			refObject.rotangles = #( 0, 0, -60,   0, 0, 0,      0, 0, -30,   0, 0, 45,     0, 0, 0,      0, 0, 0 )
			refObject.shear_axis = 1
			)	
		12:	(
			-- R Quadricep
			refObject.rotangles = #( 60, 0, 0,    -60, 0, 0,    0, 0, 0,     -45, 0, 0,    60, 0, 0,     0, 0, 0 )
			refObject.shear_axis = 3
			)	
		15:	(
			-- L Quadricep
			refObject.rotangles = #( 60, 0, 0,    -60, 0, 0,    0, 0, 0,     -45, 0, 0,    60, 0, 0,     0, 0, 0 )
			refObject.shear_axis = 3
			)	
		13:	(
			-- R Knee
			refObject.rotangles = #( 0, 0, 0,     0, 0, -90,    0, 0, 0,     0, 0, -45,    0, 0, 0,      0, 0, 0 )
			refObject.shear_axis = 1
			)	
		16:	(
			-- L Knee
			refObject.rotangles = #( 0, 0, 0,    0, 0, -90,     0, 0, 0,     0, 0, -45,    0, 0, 0,      0, 0, 0 )
			refObject.shear_axis = 1
			)
		17:	(
			-- R Shin
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      45, 0, 0,    -45, 0, 0 )
			refObject.shear_axis = 2
			)	
		18:	(
			-- L Shin
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      45, 0, 0,     -45, 0, 0 )
			refObject.shear_axis = 2
			)	
		19:	(
			-- R Ankle
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      90, 0, 0,    -90, 0, 0 )
			refObject.shear_axis = 2
			)	
		20:	(
			-- L Ankle
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      90, 0, 0,    -90, 0, 0 )
			refObject.shear_axis = 2
			)	
		21:	(
			-- R Pectoral
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      0, 0, 0,    0, 0, 0 )
			refObject.movements = #( 3, 0, 0,    -3, 0, 0,      0, 2, 1.4,   0, -0.5, -1.4,    0, 0, 0,    0, 0, 0 )
			refObject.shear_axis = 1
			)	
		22:	(
			-- L Pectoral
			refObject.rotangles = #( 0, 0, 0,     0, 0, 0,      0, 0, 0,     0, 0, 0,      0, 0, 0,    0, 0, 0 )
			refObject.movements = #( 3, 0, 0,    -3, 0, 0,      0, 2, -1.4,   0, -0.5, 1.4,    0, 0, 0,    0, 0, 0 )
			refObject.shear_axis = 1
			)	
		)
	)



---------------------------------------------------------------------
-- this is the definition of the interpolator object
---------------------------------------------------------------------

Plugin Geometry AxisInterpBox\
	name:"AxisInterpBox"\
	extends:box\
	replaceUI:true\
	classID:#(0x84d5489a, 0x4f48a366)
	version:3
(


parameters UI rollout:Display
	(
	height		type:#WorldUnits	ui:height 	default:10 	-- the dummy's height
	width		type:#WorldUnits	ui:width 	default:10 	-- "      " width
	length		type:#WorldUnits	ui:length	default:10 	-- "      " length
	dumpvalues	type:#boolean		ui:dumpvalues default:false	-- print out debugging values
	
	on height set val do
		(
		delegate.height = val
		if classof selection[1] == AxisInterpBox do selection[1].objectoffsetpos = [0,0,(-.5 * val)]
		)
	on width set val do
		(delegate.width = val)
	on length set val do
		(delegate.length = val)
	)

fn SetPos obj =
	(
	if ((obj.parent != obj.posbone) and (obj.parent != obj.posbone.parent)) then
		(
		-- not connect to either, place it at the parent origin
		obj.basepos[1] = 0;
		obj.basepos[2] = 0;
		obj.basepos[3] = 0;
		)
	else
		(
		if (obj.posbone != undefined) do
			(
			-- move between sibling and sib's parent

			parentSpace = orthogonalize (obj.posbone.parent.objectTransform)
			siblingRotation = (obj.posbone.transform * inverse parentSpace)
			p = (obj.bonedist/100.0) * siblingRotation.row4;
			obj.basepos[1] = p.x
			obj.basepos[2] = p.y
			obj.basepos[3] = p.z
			)
		)
	)
	
	

	
rollout Display "Display"
	(
	group "AxisInterpolator Object"
		(
		spinner height "Height " align:#center fieldwidth:40
		spinner width	"Width " align:#center fieldwidth:40
		spinner length	"Length" align:#center fieldwidth:40
		)

	group "Debug"
		(
		checkbox dumpvalues "Echo to MAXScript" align:#center
		)	
		
	)
		
parameters Behave rollout:Behavior
	(
	Sib			type:#node			ui:picksib				-- the node of the lower bone
	Par 		type:#node			ui:pickpar				-- the node of the upper bone
	Posbone		type:#node			ui:pickposbone			-- the node of the "positioning" bone
	boneDist	type:#integer		ui:boneDist default:0	-- placement of a shear bone along centerline of link
	basepos		type:#floattab		animatable:false	tabsize:3	tabSizeVariable:false \
				ui:(basepos1, basepos2, basepos3 )

	shear		type:#boolean	ui:shear 		animatable:false	default:false	-- is this a shear bone?
	shear_axis	type:#integer	ui:shearaxis 	animatable:false	default:1		-- which is the shear axis? usually will be X
	shear_type 	type:#integer	ui:sheartype	animatable:false	default:1		

	on shear set val do
		(
		if (classof selection[1] == AxisInterpBox) do
			(
			obj = selection[1]
			if (obj.shear == true) then
				(
				obj.sib = obj.posbone.parent
				)
			else
				(			
				obj.sib = obj.posbone
				)
			setPos obj
			)
		)

	on shear_type set val do
		(
--		print "shear_type changed"
		if (classof selection[1] == AxisInterpBox) do
			(
			AutoAxisAngleInit selection[1]
			)
		)
	)
	
rollout Behavior "Behavior"
	(

	group "Connection"
		(
		pickbutton pickpar "Parent"
		pickbutton picksib "Sibling"
		pickbutton pickposbone "Position"
		)

	group "Shear"
		(
		checkbox shear "This is a shear bone" align:#center
		radiobuttons shearAxis "Axis" labels:#("X ","Y ","Z ") enabled:true
		spinner sheartype "Type " type:#integer range:[1,22,1] align:#center fieldwidth:32 
		)
		
	group "Placement"
		(
		Spinner	BoneDist "Link % " type:#integer range:[0,100,50] fieldwidth:32 align:#center
		spinner basepos1 "" type:#float range:[-100,100,0] width:42 across:3 align:#left
		spinner basepos2 "" type:#float range:[-100,100,0] width:42 align:#left
		spinner basepos3 "" type:#float range:[-100,100,0] width:42 align:#left
		)		

	on pickpar picked obj do -- changed the bone that's being followed
		(
		if classof selection[1] == AxisInterpBox do
			(
			pickpar.text = obj.name
			selection[1].parent = obj
			SetPos selection[1]
			)
		)

	on picksib picked obj do -- changed the bone that's being followed
		(
		if classof selection[1] == AxisInterpBox do
			(
			picksib.text = obj.name
			selection[1].sib = obj
			SetPos selection[1]
			)
		)

	on pickposbone picked obj do -- changed the bone that's being followed
		(
		if classof selection[1] == AxisInterpBox do
			(
			pickposbone.text = obj.name
			selection[1].posbone = obj
			SetPos selection[1]
			)
		)

	on BoneDist changed val do	-- positions the object along the centerline of a link if the bone is a shear bone
		(
		if classof selection[1] == AxisInterpBox do
			(
			SetPos selection[1]
			)
		)

	on behave open do
		(
		shear_axis.enabled = shear.checked
		)
	)


parameters Rotate rollout:Rotangle
	(
	rotangles	type:#angleTab	animatable:false	tabsize:18	tabSizeVariable:false \
				ui:(rotangle11, rotangle12, rotangle13, \
					rotangle21, rotangle22, rotangle23, \
					rotangle31, rotangle32, rotangle33, \
					rotangle41, rotangle42, rotangle43, \
					rotangle51, rotangle52, rotangle53, \
					rotangle61, rotangle62, rotangle63 )

	)


rollout Rotangle "Rotation"
	(
	group "Angles X+"
		(
		spinner rotangle11 "" type:#integer range:[-180,180,0] width:42 across:3 align:#left
		spinner rotangle12 "" type:#integer range:[-180,180,0] width:42 align:#left
		spinner rotangle13 "" type:#integer range:[-180,180,0] width:42 align:#left
		)
	group "Angles X-"
		(
		spinner rotangle21 "" type:#integer range:[-180,180,0] width:42 across:3 align:#left
		spinner rotangle22 "" type:#integer range:[-180,180,0] width:42 align:#left
		spinner rotangle23 "" type:#integer range:[-180,180,0] width:42 align:#left
		)
	group "Angles Y+"
		(
		spinner rotangle31 "" type:#integer range:[-180,180,0] width:44 across:3 align:#left
		spinner rotangle32 "" type:#integer range:[-180,180,0] width:44 align:#left
		spinner rotangle33 "" type:#integer range:[-180,180,0] width:44 align:#left
		)
	group "Angles Y-"
		(
		spinner rotangle41 "" type:#integer range:[-180,180,0] width:44 across:3 align:#left
		spinner rotangle42 "" type:#integer range:[-180,180,0] width:44 align:#left
		spinner rotangle43 "" type:#integer range:[-180,180,0] width:44 align:#left
		)
	group "Angles Z+"
		(
		spinner rotangle51 "" type:#integer range:[-180,180,0] width:44 across:3 align:#left
		spinner rotangle52 "" type:#integer range:[-180,180,0] width:44 align:#left
		spinner rotangle53 "" type:#integer range:[-180,180,0] width:44 align:#left
		)
	group "Angles Z-"
		(
		spinner rotangle61 "" type:#integer range:[-180,180,0] width:44 across:3 align:#left
		spinner rotangle62 "" type:#integer range:[-180,180,0] width:44 align:#left
		spinner rotangle63 "" type:#integer range:[-180,180,0] width:44 align:#left
		)
	)



parameters Move rollout:movement
	(
	movements	type:#floatTab	animatable:false	tabsize:18	tabSizeVariable:false \
				ui:(movement11, movement12, movement13, \
					movement21, movement22, movement23, \
					movement31, movement32, movement33, \
					movement41, movement42, movement43, \
					movement51, movement52, movement53, \
					movement61, movement62, movement63 )
	)


rollout movement "Movement"
	(
	group "Shift X+"
		(
		spinner movement11 "" type:#float range:[-10,10,0] width:42 across:3 align:#left
		spinner movement12 "" type:#float range:[-10,10,0] width:42 align:#left
		spinner movement13 "" type:#float range:[-10,10,0] width:42 align:#left
		)
	group "Shift X-"
		(
		spinner movement21 "" type:#float range:[-10,10,0] width:42 across:3 align:#left
		spinner movement22 "" type:#float range:[-10,10,0] width:42 align:#left
		spinner movement23 "" type:#float range:[-10,10,0] width:42 align:#left
		)
	group "Shift Y+"
		(
		spinner movement31 "" type:#float range:[-10,10,0] width:44 across:3 align:#left
		spinner movement32 "" type:#float range:[-10,10,0] width:44 align:#left
		spinner movement33 "" type:#float range:[-10,10,0] width:44 align:#left
		)
	group "Shift Y-"
		(
		spinner movement41 "" type:#float range:[-10,10,0] width:44 across:3 align:#left
		spinner movement42 "" type:#float range:[-10,10,0] width:44 align:#left
		spinner movement43 "" type:#float range:[-10,10,0] width:44 align:#left
		)
	group "Shift Z+"
		(
		spinner movement51 "" type:#float range:[-10,10,0] width:44 across:3 align:#left
		spinner movement52 "" type:#float range:[-10,10,0] width:44 align:#left
		spinner movement53 "" type:#float range:[-10,10,0] width:44 align:#left
		)
	group "Shift Z-"
		(
		spinner movement61 "" type:#float range:[-10,10,0] width:44 across:3 align:#left
		spinner movement62 "" type:#float range:[-10,10,0] width:44 align:#left
		spinner movement63 "" type:#float range:[-10,10,0] width:44 align:#left
		)
	)




on create do
	(
	)

on load do
	(
	)	
	


)







----------------------------------------------------------------------
-- this function generates and positions an interpolator for two bones
----------------------------------------------------------------------
-- Note: I think this may be moved into the body of the AxisInterp definition
-- later. I'm not sure if that's a better way to handle it.

fn DoesExist matchName =
	(
	matches = for items in objects where (items.name == matchName) collect items
	return (matches.count > 0)
	)

fn FindObj matchName =
	(
	matches = for items in objects where (items.name == matchName) collect items
	if (matches.count > 0) then ( return matches[1] ) else ( return undefined )
	)


fn MakeAxisInterp newName topB botB =
	(
	if (DoesExist newName) do ( print "already defined"; clearNodeSelection redraw:false; return undefined )

	if (topB == undefined) do ( messagebox "parent bone undefined" title:"Error"; return undefined )
	if (botB == undefined) do ( messagebox "follower bone undefined" title:"Error"; return undefined )
	
	--- make and initialize a new object
	try (newAxisInterp = AxisInterpBox name:newName) catch (return undefined)

	--- setup the script controller
	newAxisInterp.rotation.controller = rotation_script()
	newAxisInterp.position.controller = position_script()

	--- initialize the object		
	newAxisInterp.wirecolor = topB.wirecolor
	newAxisInterp.delegate.width = 3
	newAxisInterp.delegate.length = 4
	newAxisInterp.delegate.height = 3
	-- calling the delegate but not the local doesn't seem to work when the object is loaded
	-- the width, lenght, and height are reset to the "default" values
	newAxisInterp.width = newAxisInterp.delegate.width
	newAxisInterp.length = newAxisInterp.delegate.length
	newAxisInterp.height = newAxisInterp.delegate.height
	newAxisInterp.objectoffsetpos = [0,0,(-.5 * newAxisInterp.height)]
	
	newAxisInterp.parent = topB
	newAxisInterp.posbone = botB
	newAxisInterp.sib = botB
	
	-- move it to its origin
	newAxisInterp.basepos[1] = 0
	newAxisInterp.basepos[2] = 0
	newAxisInterp.basepos[3] = 0
	
	-- create the script for the rotation interpolator
	RS = "" as stringstream
	format "-- automatic interpolator script v 2.0\n" to:RS
	format "-- Kenb 7/12/01\n\n" to:RS
	format "-- singlequoted name below must match name of the interp object\n" to:RS
	-- format "if (AutoAxisInterpRotate != undefined) do\n" to:RS
	format "AutoAxisInterpRotate $'%'\n" newName to:RS
	format "\n" to:RS
	RS = (RS as string)
	newAxisInterp.rotation.controller.script = RS

	-- create the script for the position interpolator
	PS = "" as stringstream
	format "-- automatic interpolator script v 2.0\n" to:PS
	format "-- Kenb 7/12/01\n\n" to:PS
	format "-- singlequoted name below must match name of the interp object\n" to:PS
	-- format "if (AutoAxisInterpPosition != undefined) do\n" to:PS
	format "AutoAxisInterpPos $'%'\n" newName to:PS
	format "\n" to:PS
	PS = (PS as string)
	newAxisInterp.position.controller.script = PS

	newAxisInterp
)


fn AxisInterpInit obj type dist shear =
	(
	if (obj != undefined) do
		(
		select obj
		if (classof selection[1] == AxisInterpBox) do
			(
			obj.shear_type = type
			obj.boneDist = dist
			obj.shear = shear
			AutoAxisAngleInit obj
			)
		)
	)

fn AxisInterpBasepos obj x y z =
	(
	if (obj != undefined) do
		(
		select obj
		if (classof selection[1] == AxisInterpBox) do
			(
			obj.basepos[1] = x
			obj.basepos[2] = y
			obj.basepos[3] = z
			)
		)
	)

fn AxisInterpSize obj height width length =
	(
	if (obj != undefined) do
		(
		select obj
		if (classof selection[1] == AxisInterpBox) do
			(
			obj.height = height
			obj.width = width
			obj.length = length
			)
		)
	)
	
	
fn SetupAxisInterp bone1 bone2 =
	(
	
	--- find top bone	
	case of 
		(
		(bone2.parent == bone1): (topB = bone1; botB = bone2)
		(bone1.parent == bone2): (topB = bone2; botB = bone1)
		default: return "bones are not parent and child"
		)
		
	---- make a name for new object	
	try -- for bipeds
		( 
		root = (parentBipOf topB).name
		newName = case (bipstrip topB) of
			(
			"L Clavicle": " L Bicep"
			"L Forearm": " L Wrist"
			"R Clavicle": " R Bicep"
			"R Forearm": " R Wrist"	
			"Neck": " NeckSmooth"
			)
		)	
		
	catch -- for non-bipeds
		(
		root = ""
		newName = " AxisInterpolator"
		)
		
	if newName == undefined then newName = " AxisInterpolator"

	newName = uniqueName(root + newName)
--	print newName
	MakeAxisInterp newName topB botB
	)



--------------------------------------------------------------------------
-- this is the function to interactively pick the bones for an interpolator
--------------------------------------------------------------------------
fn MakeSingleAxisInterp = 
	(
	messagebox "Pick the two bones which you wish to interpolate"
	Bonelist = pickObject count:2 "pick two bones to interpolate"
		(SetupAxisInterp boneList[1] bonelist[2])
	)

fn MakeAllAxisInterp = 
	(
	obj = (MakeAxisInterp "Bip01 R Shoulder" $'Bip01 R Clavicle' $'Bip01 R UpperArm')
	AxisInterpInit obj 1 100 false
	AxisInterpSize obj 1.5 3 4 -- H 1.5 W 3 L 4
	
	obj = (MakeAxisInterp "Bip01 R Bicep" $'Bip01 R UpperArm' $'Bip01 R ForeArm')
	AxisInterpInit obj 2 50 true
	
	obj = (MakeAxisInterp "Bip01 R Elbow" $'Bip01 R UpperArm' $'Bip01 R ForeArm')
	AxisInterpInit obj 3 100 false
	
	obj = (MakeAxisInterp "Bip01 R Ulna" $'Bip01 R ForeArm' $'Bip01 R Hand')
	AxisInterpInit obj 4 50 false
	
	obj = (MakeAxisInterp "Bip01 R Wrist" $'Bip01 R ForeArm' $'Bip01 R Hand')
	AxisInterpInit obj 5 100 false
	AxisInterpSize obj 3 1.5 4 -- H 3 W 1.5 L 4
	
	obj = (MakeAxisInterp "Bip01 L Shoulder" $'Bip01 L Clavicle' $'Bip01 L UpperArm')
	AxisInterpInit obj 6 100 false
	AxisInterpSize obj 1.5 3 4 -- H 1.5 W 3 L 4
	
	obj = (MakeAxisInterp "Bip01 L Bicep" $'Bip01 L UpperArm' $'Bip01 L ForeArm')
	AxisInterpInit obj 7 50 true
	
	obj = (MakeAxisInterp "Bip01 L Elbow" $'Bip01 L UpperArm' $'Bip01 L ForeArm')
	AxisInterpInit obj 8 100 false
	
	obj = (MakeAxisInterp "Bip01 L Ulna" $'Bip01 L ForeArm' $'Bip01 L Hand')
	AxisInterpInit obj 9 50 false

	obj = (MakeAxisInterp "Bip01 L Wrist" $'Bip01 L ForeArm' $'Bip01 L Hand')
	AxisInterpInit obj 10 100 false
	AxisInterpSize obj 3 1.5 4 -- H 3 W 1.5 L 4

	obj = (MakeAxisInterp "Bip01 R Hip" $'Bip01 Spine' $'Bip01 R Thigh')
	AxisInterpInit obj 11 100 false

	obj = (MakeAxisInterp "Bip01 R Quadricep" $'Bip01 R Thigh' $'Bip01 R Calf')
	AxisInterpInit obj 12 40 true
	AxisInterpSize obj 4 6 5 -- H 4 W 6 L 5

	obj = (MakeAxisInterp "Bip01 R Knee" $'Bip01 R Thigh' $'Bip01 R Calf')
	AxisInterpInit obj 13 100 false

	obj = (MakeAxisInterp "Bip01 L Hip" $'Bip01 Spine' $'Bip01 L Thigh')
	AxisInterpInit obj 14 100 false

	obj = (MakeAxisInterp "Bip01 L Quadricep" $'Bip01 L Thigh' $'Bip01 L Calf')
	AxisInterpInit obj 15 40 true
	AxisInterpSize obj 4 6 5 -- H 4 W 6 L 5
	
	obj = (MakeAxisInterp "Bip01 L Knee" $'Bip01 L Thigh' $'Bip01 L Calf')
	AxisInterpInit obj 16 100 false

	obj = (MakeAxisInterp "Bip01 R Shin" $'Bip01 R Calf' $'Bip01 R Foot')
	AxisInterpInit obj 17 50 false

	obj = (MakeAxisInterp "Bip01 L Shin" $'Bip01 L Calf' $'Bip01 L Foot')
	AxisInterpInit obj 18 50 false

	obj = (MakeAxisInterp "Bip01 R Ankle" $'Bip01 R Calf' $'Bip01 R Foot')
	AxisInterpInit obj 19 100 false

	obj = (MakeAxisInterp "Bip01 L Ankle" $'Bip01 L Calf' $'Bip01 L Foot')
	AxisInterpInit obj 20 100 false

	obj = (MakeAxisInterp "Bip01 R Pectoral" $'Bip01 Spine2' $'Bip01 R Clavicle')
	AxisInterpInit obj 21 100 false
	AxisInterpBasepos obj 4 3 -2
	AxisInterpSize obj 4 4 1.5 -- H 1.5 W 3 L 4

	obj = (MakeAxisInterp "Bip01 L Pectoral" $'Bip01 Spine2' $'Bip01 L Clavicle')
	AxisInterpInit obj 22 100 false
	AxisInterpBasepos obj 4 3 2
	AxisInterpSize obj 4 4 1.5 -- H 1.5 W 3 L 4

	obj = (MakeAxisInterp "Bip01 R Femoris" $'Bip01 R Thigh' $'Bip01 R Calf')
	AxisInterpInit obj 12 10 true
	AxisInterpSize obj 4 6 5 -- H 4 W 6 L 5

	obj = (MakeAxisInterp "Bip01 L Femoris" $'Bip01 L Thigh' $'Bip01 L Calf')
	AxisInterpInit obj 15 10 true
	AxisInterpSize obj 4 6 5 -- H 4 W 6 L 5

	)

fn SaveAllAxisInterp =
	(
	seedname = (maxFilePath) + (getFilenameFile maxFileName) + ".vpb"
	filepath = GetSaveFileName caption:"Export Procedural Bones" types:"*.vpb" filename:seedname
	
	if filepath == undefined do (return "no file destination supplied; export aborted")
	Output = createfile FilePath
	if Output == undefined do (return "export aborted")

	format "proceduralbones 0\n" to:Output
	for item in objects where (classof item == AxisInterpBox) do
		(
		format "bone \"%\" \"%\" \"%\" \"%\" %\n" item.name item.parent.name item.sib.name item.posbone.name item.shear_axis to:Output
		format "display % % %\n" item.height item.width item.length to:Output
		format "type % % %\n" item.shear_type item.bonedist item.shear to:Output
		
		format "basepos % % %\n" item.basepos[1] item.basepos[2] item.basepos[3] to:Output
		for a = 0 to 5 do
			(
			b = (a * 3)
			format "axis %  % % %  % % %\n" a \
				item.movements[ (b+1) ] item.movements[ (b+2) ] item.movements[ (b+3) ] \
				item.rotangles[ (b+1) ] item.rotangles[ (b+2) ] item.rotangles[ (b+3) ] to:Output
			)
		)

	format "end\n" to:Output
	close Output
	)
	
fn LoadAllAxisInterp =
	(
	seedname = (maxFilePath) + (getFilenameFile maxFileName) + ".vpb"
	filepath = GetOpenFileName caption:"Import Procedural Bones" types:"*.vpb" filename:seedname
	
	if filepath == undefined do (return "no file source supplied; inport aborted")
	Input = openfile FilePath
	if Input == undefined do (return "import aborted")
	
	obj = undefined
	while true do 
		(
		cmd = (readDelimitedString Input " ")
		
		case cmd of
			(
			undefined : ( close Input; return undefined )
			"" : ( close Input; return undefined )
			"--" : ( skipToNextLine Input )
			"//" : ( skipToNextLine Input )
			"proceduralbones" : ( skipToNextLine Input )
			"end" : ( close Input ; return undefined )
			"bone" :
				(
				name = readvalue Input
				parent = FindObj (readvalue Input)
				sib = FindObj (readvalue Input)
				posbone = FindObj (readvalue Input)
				axis = readvalue Input
				if (sib != undefined) then
					(
					obj = (MakeAxisInterp name parent sib)
					)
				else
					(
					obj = undefined
					)
				)
			"display" :
				(
				AxisInterpSize obj (readvalue Input) (readvalue Input) (readvalue Input)
				)
			"type" :
				(
				AxisInterpInit obj (readvalue Input) (readvalue Input) (readvalue Input)
				)
			"basepos" :
				(
				item.basepos[1] = readvalue Input
				item.basepos[2] = readvalue Input
				item.basepos[3] = readvalue Input
				)
			"axis" :
				(
				if (obj != undefined) then
					(
					a = readvalue Input
					obj.movements[ ((a*3)+1) ] = readvalue Input
					obj.movements[ ((a*3)+2) ] = readvalue Input
					obj.movements[ ((a*3)+3) ] = readvalue Input
					obj.rotangles[ ((a*3)+1) ] = readvalue Input
					obj.rotangles[ ((a*3)+2) ] = readvalue Input
					obj.rotangles[ ((a*3)+3) ] = readvalue Input
					)
				else
					(
					skipToNextLine Input
					)
				)
			)					
		)
	)			
