import sys 
import math
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
"""
import maya.cmds as cmds

nodePath='/aimNode.py'
cmds.loadPlugin(nodePath)
cmds.createNode("AimNode")
cmds.connectAttr('aimBase.translate', 'AimNode1.inTranslate', f=True)
cmds.connectAttr('up.worldMatrix[0]', 'AimNode1.upVector', f=True)
cmds.connectAttr('aimTarget.worldMatrix[0]', 'AimNode1.driverMatrix', f=True)
cmds.connectAttr('AimNode1.outRotate', 'aimBase.rotate', f=True)
"""
nodeName = 'AimNode'
nodeId   = OpenMaya.MTypeId(0x100fff)

class AimNode(OpenMayaMPx.MPxNode):
    # create attribte handle
    inTranslateX    = OpenMaya.MObject()
    inTranslateY    = OpenMaya.MObject()
    inTranslateZ    = OpenMaya.MObject()
    inTranslate     = OpenMaya.MObject()   
    outRotateX      = OpenMaya.MObject()    
    outRotateY      = OpenMaya.MObject()
    outRotateZ      = OpenMaya.MObject()    
    outRotate       = OpenMaya.MObject()
    driverMatrix    = OpenMaya.MObject()
    upVector        = OpenMaya.MObject()

    def __init__(self):
        OpenMayaMPx.MPxNode.__init__(self)

    def compute(self, plug, dataBlock):
        """"""
        if ( plug==AimNode.outRotate or plug==AimNode.outRotateX or plug==AimNode.outRotateY or plug==AimNode.outRotateZ ):
            
            # GET INPUT VALUES
            driverMatrixDataHandle   = dataBlock.inputValue(AimNode.driverMatrix)
            upVectorMatrixDataHandle = dataBlock.inputValue(AimNode.upVectorMatrix)
            inTranslateDataHandle    = dataBlock.inputValue(AimNode.inTranslate)
            driverMatrixV   = driverMatrixDataHandle.asMatrix()
            upVectorMatrixV = upVectorMatrixDataHandle.asMatrix()
            inTranslateV    = inTranslateDataHandle.asVector()
            
            # DO CALCULATION
            driverMatrixPos   = OpenMaya.MVector(  driverMatrixV(3,0),  driverMatrixV(3,1),  driverMatrixV(3,2))
            upVectorMatrixPos = OpenMaya.MVector(upVectorMatrixV(3,0),upVectorMatrixV(3,1),upVectorMatrixV(3,2))
            # compute needed vectors
            upVec  = OpenMaya.MVector( upVectorMatrixPos - inTranslateV )
            aimVec = OpenMaya.MVector( driverMatrixPos   - inTranslateV )
            cross = OpenMaya.MVector(aimVec ^ upVec)
            upVec = cross ^ aimVec
            upVec.normalize()
            aimVec.normalize()
            cross.normalize()
            # build a rotation matrix
            rotMatrix = OpenMaya.MMatrix()
            matrixList =[aimVec.x       , aimVec.y       , aimVec.z       , 0,
                         upVec.x        , upVec.y        , upVec.z        , 0,
                         cross.x        , cross.y        , cross.z        , 0,
                         inTranslateV[0], inTranslateV[1], inTranslateV[2], 1]
            OpenMaya.MScriptUtil.createMatrixFromList(matrixList, rotMatrix)
            print '{},{},{},{},'.format( rotMatrix(0,0),rotMatrix(0,1),rotMatrix(0,2),rotMatrix(0,3) )
            print '{},{},{},{},'.format( rotMatrix(1,0),rotMatrix(1,1),rotMatrix(1,2),rotMatrix(1,3) )
            print '{},{},{},{},'.format( rotMatrix(2,0),rotMatrix(2,1),rotMatrix(2,2),rotMatrix(2,3) )          
            print '{},{},{},{} '.format( rotMatrix(3,0),rotMatrix(3,1),rotMatrix(3,2),rotMatrix(3,3) )          

            # SET OUTPUT VALUES
            euler    = OpenMaya.MTransformationMatrix(rotMatrix).eulerRotation() * (180/math.pi)#rad to degree
            dataHandleRotate = dataBlock.outputValue(AimNode.outRotate)
            dataHandleRotate.set3Float(euler[0], euler[1], euler[2])
            print '{},{},{}'.format( euler[0], euler[1], euler[2] )
            
            dataBlock.setClean(plug)
        else:
            return OpenMaya.kUnknownParameter

def nodeCreator():
    return OpenMayaMPx.asMPxPtr( AimNode() )

def nodeInitializer():
    mFnNumAttr      = OpenMaya.MFnNumericAttribute()
    mFnTypedAttr    = OpenMaya.MFnTypedAttribute()
    mFnCompoundAttr = OpenMaya.MFnCompoundAttribute()
    mFnMatrixAtrr   = OpenMaya.MFnMatrixAttribute()
    mFnUnitAttr     = OpenMaya.MFnUnitAttribute()
    
    AimNode.driverMatrix = mFnMatrixAtrr.create('driverMatrix','drm')
    AimNode.upVectorMatrix = mFnMatrixAtrr.create('upVector', 'upvm')
    AimNode.addAttribute(AimNode.driverMatrix)
    AimNode.addAttribute(AimNode.upVectorMatrix)
        
    AimNode.inTranslateX = mFnNumAttr.create('inTranslateX','intx',OpenMaya.MFnNumericData.kDouble,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(1)
    mFnNumAttr.setStorable(1)
    mFnNumAttr.setKeyable(1)
    AimNode.addAttribute(AimNode.inTranslateX)
    AimNode.inTranslateY = mFnNumAttr.create('inTranslateY','inty',OpenMaya.MFnNumericData.kDouble,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(1)
    mFnNumAttr.setStorable(1)
    mFnNumAttr.setKeyable(1)
    AimNode.addAttribute(AimNode.inTranslateY)
    AimNode.inTranslateZ = mFnNumAttr.create('inTranslateZ','intz',OpenMaya.MFnNumericData.kDouble,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(1)
    mFnNumAttr.setStorable(1)
    mFnNumAttr.setKeyable(1)
    AimNode.addAttribute(AimNode.inTranslateZ)
    AimNode.inTranslate = mFnCompoundAttr.create('inTranslate','int')
    mFnCompoundAttr.addChild(AimNode.inTranslateX)
    mFnCompoundAttr.addChild(AimNode.inTranslateY)    
    mFnCompoundAttr.addChild(AimNode.inTranslateZ)      
    mFnCompoundAttr.setReadable(1)  
    mFnCompoundAttr.setWritable(1)  
    mFnCompoundAttr.setStorable(1)  
    mFnCompoundAttr.setKeyable(1)  
    AimNode.addAttribute(AimNode.inTranslate)
    
    AimNode.outRotateX = mFnNumAttr.create('outRotateX','orx',OpenMaya.MFnUnitAttribute.kAngle,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(0)
    mFnNumAttr.setStorable(0)
    mFnNumAttr.setKeyable(0)
    AimNode.addAttribute(AimNode.outRotateX)
    AimNode.outRotateY = mFnNumAttr.create('outRotateY','ory',OpenMaya.MFnUnitAttribute.kAngle,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(0)
    mFnNumAttr.setStorable(0)
    mFnNumAttr.setKeyable(0)
    AimNode.addAttribute(AimNode.outRotateY)
    AimNode.outRotateZ = mFnNumAttr.create('outRotateZ','orz',OpenMaya.MFnUnitAttribute.kAngle,0.0)
    mFnNumAttr.setReadable(1)
    mFnNumAttr.setWritable(0)
    mFnNumAttr.setStorable(0)
    mFnNumAttr.setKeyable(0)
    AimNode.addAttribute(AimNode.outRotateZ)
    AimNode.outRotate = mFnCompoundAttr.create('outRotate','or')
    mFnCompoundAttr.addChild(AimNode.outRotateX)
    mFnCompoundAttr.addChild(AimNode.outRotateY)    
    mFnCompoundAttr.addChild(AimNode.outRotateZ)      
    mFnCompoundAttr.setReadable(1)  
    mFnCompoundAttr.setWritable(0)  
    mFnCompoundAttr.setStorable(0)  
    mFnCompoundAttr.setKeyable(0)  
    AimNode.addAttribute(AimNode.outRotate)

    AimNode.attributeAffects(AimNode.inTranslate   , AimNode.outRotate)
    AimNode.attributeAffects(AimNode.upVectorMatrix, AimNode.outRotate)
    AimNode.attributeAffects(AimNode.driverMatrix  , AimNode.outRotate)

def initializePlugin(mobject):
    mplugin = OpenMayaMPx.MFnPlugin(mobject)
    try:
        mplugin.registerNode(nodeName,nodeId, nodeCreator, nodeInitializer)
    except:                                
        sys.stderr.write("Failed to register node:"+ nodeName)
        
def uninitializePlugin(mobject):
    mplugin = OpenMayaMPx.MFnPlugin(mobject)
    try:
        mplugin.deregisterNode(nodeId)
    except:                                 
        sys.stderr.write("Failed to unregister node:"+ nodeName)
    
    