Interactive/NudgeCameraCustom.py

##
## (C) Copyright 2012 Autodesk, Inc.  All rights reserved.
##
## Use of this software is subject to the terms of the Autodesk license
## agreement provided at the time of installation or download, or which
## otherwise accompanies this software in either electronic or hard copy
## form.
##

#           module = __import__(custom)
#           instance = module.instantiate()
#           self.__myCustoms.append(instance)

__all__ = ['NudgeCameraCustom', 'instantiate']

from awSupportApi       import ProjMatrix, Vector
from MessageInterpreter import MessageInterpreter
from UserCustomization  import UserCustomBase, CustomInfo
from MessageRegistry    import theMessageRegistry
from DisplayUtilities   import GetCameras

NUDGE_CAMERA_Doc=\
[(
"""
Shows Nudge Camera Left by 1 or Nudge Camera Right by 1.
"""
),
[[("direction"),("left or right")]
 ]
]
theMessageRegistry.register("NUDGE_CAMERA",
    (unicode,), 0, NUDGE_CAMERA_Doc)

class NudgeCameraCustom (UserCustomBase):
    def __init__(self):
        self.__myNudgeMenu = None
        self.__myNudgeLeftId = None
        self.__myNudgeRightId = None
        self.__myInterpreter = NudgeInterpreter()

    def getInterpreter(self,isInteractive):
        if isInteractive:
            return self.__myInterpreter
        return None

    def appendMenuItems(self,id,menu):
        if "View" == id:
            self.__myNudgeMenu = menu
            self.__myNudgeLeftId = menu.appendItem(_( 'Nudge Camera Left by 1' ),
                                                   self.__onNudgeCameraLeft )

            self.__myNudgeRightId = menu.appendItem(_( 'Nudge Camera Right by 1' ),
                                                   self.__onNudgeCameraRight )

            self.__myNudgeOverride = menu.appendItem(_( 'Nudge Camera use override' ),
                                                   self.__onOverride )

            self.__myNudgeNoOverride = menu.appendItem(_( 'Nudge Camera no override' ),
                                                   self.__onNoOverride )


    def enableMenuStates(self,id,enableStates):
        if "View" == id:
            enableStates[self.__myNudgeLeftId] = True
            enableStates[self.__myNudgeRightId] = True

    # ------------------------------------------------
    def __onNudgeCameraLeft( self, event ):
        self.__myInterpreter.override(True)
        self.__myInterpreter.NudgeCameraLeft( None )

    def __onNudgeCameraRight( self, event ):
        self.__myInterpreter.override(True)
        self.__myInterpreter.NudgeCameraRight( None )

    def __onNoOverride(self,event):
        self.__myInterpreter.override(False)

    def __onOverride(self,event):
        self.__myInterpreter.override(True)

# -----------------------------------------------------------------------

class NudgeInterpreter( MessageInterpreter ):

    __kNudgeUnit = 1

    def __init__( self ):
        MessageInterpreter.__init__( self )
        self.__myDisplay = None
        self.__myNudgeDistance = 0.0
        self.__myOverride = True # Whether to use the override API

    def override(self,flag):
        if not flag and self.__myOverride and self.__myDisplay:
            for camera in GetCameras( self.__myDisplay ):
                camera.setOverwriteCameraMatrices( False, False )
        self.__myOverride = flag

    def __nudgeCamera( self, distance ):
        if self.__myDisplay:
            for camera in GetCameras( self.__myDisplay ):
                position = camera.getPosition()
                right = camera.getRightVector()

                if self.__myOverride:
                    self.__myNudgeDistance += distance
                    nudgeDir = Vector( right )
                    nudgeDir *= self.__myNudgeDistance
                    position += nudgeDir
                    vector = Vector( position.p )

                    up = camera.getUpVector()
                    dir = camera.getDirection()

                    viewMtx = ProjMatrix( 1.0 )

                    viewMtx[0] = right.v[0]
                    viewMtx[4] = right.v[1]
                    viewMtx[8] = right.v[2]
                    viewMtx[12] = -right.dot( vector )

                    viewMtx[1] = up.v[0]
                    viewMtx[5] = up.v[1]
                    viewMtx[9] = up.v[2]
                    viewMtx[13] = -up.dot( vector )

                    viewMtx[2] = dir.v[0]
                    viewMtx[6] = dir.v[1]
                    viewMtx[10] = dir.v[2]
                    viewMtx[14] = -dir.dot( vector )

                    camera.setOverwriteCameraMatrices( True, False )
                    camera.setOverwriteCameraWorldToView( viewMtx, viewMtx.inverse() )
                else:
                    right *= distance
                    position += right

                    coi = camera.getCOI()
                    coi += right

                    camera.setPosition( position )
                    camera.setCOI( coi )

    def NudgeCameraLeft( self, event ):
        self.__nudgeCamera( -self.__kNudgeUnit )
        return True

    def NudgeCameraRight( self, event ):
        self.__nudgeCamera( self.__kNudgeUnit )
        return True

    def SET_DISPLAY( self, message ):
        ( self.__myDisplay, ) = message.data

    def NUDGE_CAMERA( self, message ):
        ( direction, ) = message.data
        if direction=='Left':
            self.NudgeCameraLeft(None)
        else:
            self.NudgeCameraRight(None)


# --------------------------------------------------------------------

def instantiate():
    # Are the relevant files elsewhere?
    # sys.path.append( "where the files are" )
    return NudgeCameraCustom()


def info():
    customInfo = CustomInfo()
    customInfo.vendor = 'Autodesk'
    customInfo.version = '3.0'
    customInfo.api = '2013'
    customInfo.shortInfo = "Nudge the camera left or right."
    customInfo.longInfo = \
"""Add two menu items under "View" menu to nudge the camera left or right.
"""
    return customInfo