# oj_FR_PoseToolsPlugin
# Initial code generated by Softimage SDK Wizard
# Executed Tue Sep 10 17:24:42 UTC+0200 2013 by juarez
# 
# Tip: To add a command to this plug-in, right-click in the 
# script editor and choose Tools > Add Command.
import win32com.client
from win32com.client import constants as c
from win32com.client import Dispatch as DD
import re


DD 
xsi = Application
lm = xsi.LogMessage

null = None
false = 0
true = 1

def XSILoadPlugin( in_reg ):
    in_reg.Author = "Oscar Juarez"
    in_reg.Name = "oj_FR_PoseToolsPlugin"
    in_reg.Major = 1
    in_reg.Minor = 0

    in_reg.RegisterCommand("oj_FR_PoseTools","oj_FR_PoseTools")
    in_reg.RegisterMenu(c.siMenuMainTopLevelID, 'fr_tools', True)
    #RegistrationInsertionPoint - do not remove this line

    return true

def XSIUnloadPlugin( in_reg ):
    strPluginName = in_reg.Name
    lm(str(strPluginName) + str(" has been unloaded."),c.siVerbose)
    return true

##Menu
def fr_tools_Init(in_ctxt):
    oMenu = in_ctxt.Source

    oSubMenuSO = oMenu.AddItem('Face Robot', 2)
    oSubMenuSO = DD(oSubMenuSO)
    oSubMenuSO.AddCallbackItem('Select Right Controls', 'oj_FR_selectRight_onCall')
    oSubMenuSO.AddCallbackItem('Select Left Controls', 'oj_FR_selectLeft_onCall')
    oSubMenuSO.AddSeparatorItem()
    oSubMenuSO.AddCallbackItem('Flip Pose', 'oj_FR_FlipPose_onCall')
    oSubMenuSO.AddCallbackItem('Mirror Left/Right', 'oj_FR_LeftToRight_onCall')
    oSubMenuSO.AddCallbackItem('Mirror Right/Left', 'oj_FR_RightToLeft_onCall')

def oj_FR_selectRight_onCall(in_ctxt):
    xsi.oj_FR_PoseTools(0, False)


def oj_FR_selectLeft_onCall(in_ctxt):
    xsi.oj_FR_PoseTools(0, True)


def oj_FR_FlipPose_onCall(in_ctxt):
    xsi.oj_FR_PoseTools(1)


def oj_FR_LeftToRight_onCall(in_ctxt):
    xsi.oj_FR_PoseTools(2, True)


def oj_FR_RightToLeft_onCall(in_ctxt):
    xsi.oj_FR_PoseTools(2, False)


def getLControlsList(rControlsList):
    lControlsList = [eachControl.replace('Face.Right', 'Face.Left').replace('Face.R', 'Face.L')
                 for eachControl in rControlsList]
    return lControlsList


def selectOneSide(rControlsList, lControlsList, selectLeft):
    xsi.Selection.Clear()
    selList = rControlsList
    if selectLeft:
        selList = lControlsList
        
    xsi.Selection.SetAsText(','.join(selList))


def mirrorPose(rControlsList, lControlsList, useLeft=True):
    srcControlsCol = DD("XSI.Collection")
    targetControlsCol = DD("XSI.Collection")

    if useLeft:
        srcControlsCol.SetAsText(",".join(lControlsList))
        targetControlsCol.SetAsText(",".join(rControlsList))
    else:
        srcControlsCol.SetAsText(",".join(rControlsList))
        targetControlsCol.SetAsText(",".join(lControlsList))

    for i in range(srcControlsCol.Count):
        srcKine = srcControlsCol(i).Kinematics.Local
        targetKine = targetControlsCol(i).Kinematics.Local

        targetKine.Parameters('posx').Value = -srcKine.Parameters('posx').Value
        targetKine.Parameters('posy').Value = srcKine.Parameters('posy').Value
        targetKine.Parameters('posz').Value = srcKine.Parameters('posz').Value
        targetKine.Parameters('rotx').Value = srcKine.Parameters('rotx').Value
        targetKine.Parameters('roty').Value = -srcKine.Parameters('roty').Value
        targetKine.Parameters('rotz').Value = -srcKine.Parameters('rotz').Value


def switchPose(rControlsList, lControlsList):
    rControlsCol = DD("XSI.Collection")
    lControlsCol = DD("XSI.Collection")

    rControlsCol.SetAsText(",".join(rControlsList))
    lControlsCol.SetAsText(",".join(lControlsList))

    for i in range(rControlsCol.Count):
        rKine = rControlsCol(i).Kinematics.Local
        lKine = lControlsCol(i).Kinematics.Local

        lPosX = lKine.Parameters('posx').Value
        lPosY = lKine.Parameters('posy').Value
        lPosZ = lKine.Parameters('posz').Value
        lRotX = lKine.Parameters('rotx').Value
        lRotY = lKine.Parameters('roty').Value
        lRotZ = lKine.Parameters('rotz').Value


        lKine.Parameters('posx').Value = -rKine.Parameters('posx').Value
        lKine.Parameters('posy').Value = rKine.Parameters('posy').Value
        lKine.Parameters('posz').Value = rKine.Parameters('posz').Value
        lKine.Parameters('rotx').Value = rKine.Parameters('rotx').Value
        lKine.Parameters('roty').Value = -rKine.Parameters('roty').Value
        lKine.Parameters('rotz').Value = -rKine.Parameters('rotz').Value

        rKine.Parameters('posx').Value = -lPosX
        rKine.Parameters('posy').Value = lPosY
        rKine.Parameters('posz').Value = lPosZ
        rKine.Parameters('rotx').Value = lRotX
        rKine.Parameters('roty').Value = -lRotY
        rKine.Parameters('rotz').Value = -lRotZ


def oj_FR_PoseTools_Init( in_ctxt ):
    oCmd = in_ctxt.Source
    oCmd.Description = ""
    oCmd.ReturnValue = true

    oArgs = oCmd.Arguments
    oArgs.Add("command",c.siArgumentInput,0)
    oArgs.Add("useLeft", c.siArgumentInput, True)
    return true

def oj_FR_PoseTools_Execute( command, useLeft ):

    lm("oj_FR_PoseTools_Execute called",c.siVerbose)
    pattern = re.compile('Ri*g*h*t*[A-Z]*.+')

    root = xsi.ActiveSceneRoot
    faceModel = root.FindChild2('Face')

    if command == 0:
        controls = faceModel.Groups('Controls').Members

        controlsRightSide = [eachControl.FullName for eachControl in controls 
                         if pattern.match(eachControl.Name)]

        controlsLeftSide = getLControlsList(controlsRightSide)
        selectOneSide(controlsRightSide, controlsLeftSide, useLeft)
        return true

    sel = xsi.Selection

    if sel.Count > 0: 
        controls = sel
    else:
        controls = faceModel.Groups('Controls').Members

    controlsRightSide = [eachControl.FullName for eachControl in controls 
                         if pattern.match(eachControl.Name)]
    
    if command == 0:
        controlsLeftSide = getLControlsList(controlsRightSide)
        selectOneSide(controlsRightSide, controlsLeftSide, useLeft)
        return true

    if len(controlsRightSide) > 0:
        controlsLeftSide = getLControlsList(controlsRightSide)

        if command == 1:
            switchPose(controlsRightSide, controlsLeftSide)
        elif command == 2:
            mirrorPose(controlsRightSide, controlsLeftSide, useLeft)

    else:
        lm('No controls found to process, you must select at least one control on the right of the rig', 4)

    return true

