Published using Google Docs
Main.txt

#import a class, TransformEditController  

#   setTemplate on/off

#   setVisible  on/off

"""example            

        !!!the dynPar nodes will be deleted from maya scene

        make sure before using this tool you have no nodes by these names

       

        !!if you dont see anything happening

        !you might have to call stop

       

        !!if youre getting nowhere

        !make sure the thing you want to move is in a group

       

import Transform

import PositionCalculator

import HierarchyCalculator

import ConnectionCalculator

import AttributeCalculator

import ShapeConstraint

import BasicConstraint

import ConstraintCopier

import DisplayEditor

import SceneCheck

import Main

reload(Transform)

reload(PositionCalculator)

reload(HierarchyCalculator)

reload(ConnectionCalculator)

reload(AttributeCalculator)

reload(ShapeConstraint)

reload(BasicConstraint)

reload(ConstraintCopier)

reload(DisplayEditor)

reload(SceneCheck)

reload(Main)

       

       

dynPar = Main.Main('parent' , 'child', 'childGrp')

dynPar.start()

dynPar.stop()

       

"""

import Transform as trf

import PositionCalculator as pc

import HierarchyCalculator as hc

import ShapeConstraint as cnt

import BasicConstraint as bnt

import ConstraintCopier as cpy

import DisplayEditor as dpy

import SceneCheck as sc

import maya.cmds as mc

class Main:

    def __init__(self,parentName ='_parent',childName = '_child', childParentName = '_childParent'):

        """

        needs arguments

       

        makes assumptions about input

            0. assumes input has no connections or constraints preventing them to move

            1. assumes input is on stage

            2. assumes group child control parent has one child the child control animator wants auto moved

            3. assumes the dummy name variables were never made by the animator for his/her scene

           

        makes assumption about type of connection animator wants

            1. assumes parent constraint is the way a child is auto moved

           

        Why?

            - does not make any cleaning up of backend nodes

            - does not make sure animator controls are at right place after cleanup

            - does not check if user input is on maya scene

            - does not check if user created objects of same name as

        """

       

       

       

        #user vars  DO NOT TOUCH

        self._userParentCtrlName = parentName

        self._userChildCtrl = childName

        self._userChildCtrlGrpParentName = childParentName  

        name = parentName+'_'+childName+'_'+childParentName

       

        #duumy var

        #start var

        self.sceneGrpName = 'naDynPar_do_not_touch_'+name

        self.sceneParentName = 'naDynPar_parent_'+name

        self.sceneChildName = 'naDynPar_child_'+name

        self.sceneParentWorldName = 'naDynPar_world_'+name

        #stop var

        self.whereIsParentLoc = 'naDynPar_whereIsParent_'+name

        self.whereIsChildLoc = 'naDynPar_whereIsChild_'+name

        #stop and stop var

        self.worldUserOption = 'world'

        self.isStartReady = True   #call start,stop,start,stop order good, start,start bad, or stop,stop bad

   

    #Move to UserInterfaceChecker

    #--assertIsParentChildAndGroupOnStage

    #--assertGroupOfChildCorrect

    #--assertOnInitializationPrivateVariablesNotOnStage

    #printMessageStartError

    #printMessageStopError

   

    #could add get and set methods for user input ?? may be beter in UserInterface class

   

    def start(self):

        """

        """

        #get current selection

        sceneChecker = sc.SceneCheck()

        currentSelection = sceneChecker.getCurrentSelection()

       

        if self.isStartReady == True:

            self.__startBackend()

            #dont call start again until it has been stopped first

            self.isStartReady = False

           

        #restore current selection    

        sceneChecker.restoreSelectionOrClear(currentSelection)

       

       

    def stop(self):

        """

        """

        #get current selection

        sceneChecker = sc.SceneCheck()

        currentSelection = sceneChecker.getCurrentSelection()

       

        if self.isStartReady == False:

            self.__stopBackend()

            self.isStartReady = True

           

        #restore current selection    

        sceneChecker.restoreSelectionOrClear(currentSelection)

       

       

    def parentSceneFolderToThisNull(self,_null):

        """

        This is not used by this tool only by others that want to help with cleaning

        This generally should not be called by the user

       

        assumes null exists on stage

        assumes it can move the pivot of this null

        """

        #to prevent skipping while parenting

        #match input nulls pivot to sceneGrp's pivot, that is where we will be parenting to

        #parent sceneGrp to null, no movement cause pivots are the same !!!

       

        sceneChecker = sc.SceneCheck()

        _isAllOnStage = False

        _isAllOnStage = sceneChecker.isAllOnStage( [self.sceneGrpName, _null])

       

        #do nothing unless everything is on scene

        if _isAllOnStage == True:

            sceneGrpName = self.sceneGrpName

            userNull = _null

           

            #snap the user null pivot to dummyGroup holder

            snapCalculator = pc.PositionCalculator()

            snapCalculator.matchPivot( sceneGrpName, userNull   )

           

            #put all dummy node into trashHolder

            parentCalculator = hc.HierarchyCalculator()

            parentCalculator.parent( sceneGrpName, userNull )        

        else:

            print 'did not parent to scene folder'

   

    #private

    def __startBackend(self):

        """

        This creates backend nulls, setups up connecting them, all to achieve a dynamic parenting

        sort of thing.

        """

        _userParentCtrlName = self._userParentCtrlName

        _userChildCtrl = self._userChildCtrl

        _userChildCtrlGrpParentName = self._userChildCtrlGrpParentName

       

       

        #make four dummy nodes

        #on every press of start tool resets so

        #--create a group to hold 2 trash back end nodes

        #--make an extra dummy node for the case _parentCtrlName is self.worldUserOption

        trashHolder = trf.TransformGroup(self.sceneGrpName)

        parentLoc = trf.TransformLocator(self.sceneParentName)

        childLoc = trf.TransformLocator(self.sceneChildName)

        worldLoc = trf.TransformLocator(self.sceneParentWorldName)

       

        #make tool created nulls harder to select by user

        self.__templateDynParStartDummyNode()

        self.__visibilityOffDynParStartDummyNode()

       

       

        #put all dummy node into trashHolder

        parentCalculator = hc.HierarchyCalculator()

        parentCalculator.parent( self.sceneParentName, self.sceneGrpName )

        parentCalculator.parent( self.sceneChildName, self.sceneGrpName )

        parentCalculator.parent( self.sceneParentWorldName, self.sceneGrpName )

       

       

        #SNAPPING

        #snap the user child arg group pivot to user child arg control

        #snap the child dummy to the users child argument

        snapCalculator = pc.PositionCalculator()

        snapCalculator.matchPivot( _userChildCtrl, _userChildCtrlGrpParentName   )

        snapCalculator.matchPositionAndOrientation( _userChildCtrlGrpParentName, self.sceneChildName   )

       

        #snapping the two dummy nodes to the maya scene objects

        ###parent snapping        

        if _userParentCtrlName == self.worldUserOption:

            snapCalculator.matchPositionAndOrientation( self.sceneParentWorldName, self.sceneParentName   )

        else:  

            #snap the parent dummy to the user parent arg

            snapCalculator.matchPositionAndOrientation( _userParentCtrlName, self.sceneParentName   )

       

       

        #CREATING CONSTRAINT

        ###make parent dummy drive child dummy by constraint

        #make type parent

        #draw

        cntDummyName = 'dynpar_constraint'

        constraintMaker = cnt.ShapeConstraint(cntDummyName)

        parentCntType = bnt.ParentBasicConstraint()

        maintainOffset = True

        constraintMaker.draw( self.sceneParentName,self.sceneChildName,parentCntType, maintainOffset = True)

       

       

       

        #make a copier

        #copy

        constraintCopier  = cpy.ConstraintCopier()

        if _userParentCtrlName != self.worldUserOption:

            #parent constraint between child dummy and parent dummy to user parent and user child

            constraintCopier.copy([self.sceneParentName,self.sceneChildName] , [_userParentCtrlName, _userChildCtrlGrpParentName])

        else:

            #parent constraint between child dummy and parent dummy to world dummy and user child

            constraintCopier.copy([self.sceneParentName,self.sceneChildName] , [self.sceneParentWorldName, _userChildCtrlGrpParentName])

           

       

               

       

       

    def __stopBackend(self):

        """

        stop should not be exposed unless

            --start has been called

       

        makes assumptions on animator input

            --assumes given start( a, b ) that stop is stop( a, b )  same arguments in both calls

           

        makes assumptions on animator removing tool created objects

            --assumes all backend things created by tool are not touched, deleted renamed moved etc by user

        """

   

        _userParentCtrlName = self._userParentCtrlName

        _userChildCtrl = self._userChildCtrl

        _userChildCtrlGrpParentName = self._userChildCtrlGrpParentName  

               

        #tool for remember where animator controls are now

        whereIsParentLoc = trf.TransformLocator(self.whereIsParentLoc)

        whereIsChildLoc = trf.TransformLocator(self.whereIsChildLoc)

       

        #tool for snapping dummys to user args

        snapCalculator = pc.PositionCalculator()

       

        #when world is not the parent

        #snap the dummy parent to the user parent arg

        #snap the dummy child to the user child arg

        if _userParentCtrlName != self.worldUserOption:

            snapCalculator.matchPositionAndOrientation(_userParentCtrlName, self.whereIsParentLoc)

        snapCalculator.matchPositionAndOrientation(_userChildCtrlGrpParentName, self.whereIsChildLoc)

        #assumes delete removes

        ## backend to backend constraints

        ## backend to user constraints

        ## backend group

        ## backend locators

        self.__deleteDynParStartDummyNode()

       

        if _userParentCtrlName != self.worldUserOption:

            #snap the user parent to the dummy parent

            snapCalculator.matchPositionAndOrientation( self.whereIsParentLoc, _userParentCtrlName   )

           

        #snap the user child arg to the dummy child

        snapCalculator.matchPositionAndOrientation( self.whereIsChildLoc, _userChildCtrlGrpParentName   )

         

        #delete temp dummy nodes

        self.__deleteDynParStopDummyNode()

        #match child parent pivot to child pivot

        snapCalculator.matchPivot(_userChildCtrl,_userChildCtrlGrpParentName)

       

    def __deleteDynParStartDummyNode(self):

        delList = [ self.sceneParentWorldName, self.sceneChildName, self.sceneParentName, self.sceneGrpName ]

        self.__deleteIfExists(delList)

        #mc.delete(delList)

       

    def __deleteDynParStopDummyNode(self):

        delList = [ self.whereIsParentLoc, self.whereIsChildLoc ]

        self.__deleteIfExists(delList)

        #mc.delete(delList)    

   

    def __deleteIfExists(self,_list):

        """

        add existence checks before deleting

        in case user has deleted scene objects

        or something else messed up here

        """

        dummyObjects = _list

        sceneChecker = sc.SceneCheck()

        for element in dummyObjects:

            isOnStage = sceneChecker.isAllOnStage( [element] )

            if isOnStage == True:

                mc.delete(element)

            else:

                print 'Thought: %s :should be on scene' %element

       

       

    def __templateDynParStartDummyNode(self):

        templateList = [self.sceneParentWorldName, self.sceneChildName, self.sceneParentName, self.sceneGrpName ]

        displayEditor = dpy.DisplayEditor(templateList)

        displayEditor.setTemplateOn()  

       

    def __visibilityOffDynParStartDummyNode(self):

        visibilityOffList = [self.sceneParentWorldName, self.sceneChildName, self.sceneParentName, self.sceneGrpName ]

        displayEditor = dpy.DisplayEditor(visibilityOffList)

        displayEditor.setVisibilityOff()