#BPYCONSTRAINT
'''
	This is an alternative TrackTo constraint that may be better
	in some situations than the built-in TrackTo.
	It attempts to minimize the twisting of the object relative
	to its starting position while it tracks the target.
'''

import Blender
from Blender import Draw
from Blender import Mathutils
from math import *

'''
 This variable specifies the number of targets 
 that this constraint can use
'''
NUM_TARGETS = 1






'''
 This function is called to evaluate the constraint
	obmatrix:		(Matrix) copy of owner's 'ownerspace' matrix
	targetmatrices:	(List) list of copies of the 'targetspace' matrices of the targets (where applicable)
	idprop:			(IDProperties) wrapped data referring to this 
					constraint instance's idproperties
'''
def doConstraint(obmatrix, targetmatrices, idprop):
	# Get user-settable parameters
	if not idprop.has_key('axis'):
		idprop['axis'] = 2
		
	axis = idprop['axis']
	
	
	# Find the vector that the chosen axis is currently pointing in
	if axis == 1:    #X
		obvec = Mathutils.Vector(1,0,0)
	elif axis == 2:  #Y
		obvec = Mathutils.Vector(0,1,0)
	elif axis == 3:  #Z
		obvec = Mathutils.Vector(0,0,1)
	elif axis == 4:  #-X
		obvec = Mathutils.Vector(-1,0,0)
	elif axis == 5:  #-Y
		obvec = Mathutils.Vector(0,-1,0)
	elif axis == 6:  #-Z
		obvec = Mathutils.Vector(0,0,-1)
		
	obvec = Mathutils.VecMultMat(obvec, obmatrix.rotationPart())
	obvec.normalize()
	
	
	# Find the vector pointing to the target from the object
	tarvec = targetmatrices[0].translationPart() - obmatrix.translationPart()
	tarvec.normalize()
	
	
	# Create a rotation matrix representing the shortest
	# possible rotation between the two aforementioned vectors
	rotaxis = Mathutils.CrossVecs( obvec, tarvec )
	rotangle = acos(  max(-1.0, min(1.0, Mathutils.DotVecs( obvec, tarvec )))  ) * (180/pi)
	rotmat = Mathutils.RotationMatrix(rotangle, 3, "r", rotaxis)
	
	# Apply the rotation to the object
	outputmatrix = obmatrix * rotmat.resize4x4()
	outputmatrix[3][0] = obmatrix[3][0]
	outputmatrix[3][1] = obmatrix[3][1]
	outputmatrix[3][2] = obmatrix[3][2]

	# Return the new matrix.
	return outputmatrix









'''
 User-settings menu.
'''
def getSettings(idprop):
	# Define user-settable parameters.
	if not idprop.has_key('axis'):
		idprop['axis'] = 2

	# define and draw pupblock
	retval = Draw.PupMenu( "Tracking Axis%t | X%x1 | Y%x2 | Z%x3 | %l | -X%x4 | -Y%x5 | -Z%x6" )
	
	# update id-property values after user changes settings
	if retval > 0:
		idprop['axis']= retval