- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# swissArmyManip.py

    #-
    # ==========================================================================
    # Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All
    # rights reserved.
    #
    # The coded instructions, statements, computer programs, and/or related
    # material (collectively the "Data") in these files contain unpublished
    # information proprietary to Autodesk, Inc. ("Autodesk") and/or its
    # licensors, which is protected by U.S. and Canadian federal copyright
    # law and by international treaties.
    #
    # The Data is provided for use exclusively by You. You have the right
    # to use, modify, and incorporate this Data into other products for
    # purposes authorized by the Autodesk software license agreement,
    # without fee.
    #
    # The copyright notices in the Software and this entire statement,
    # including the above license grant, this restriction and the
    # following disclaimer, must be included in all copies of the
    # Software, in whole or in part, and all derivative works of
    # the Software, unless such copies or derivative works are solely
    # in the form of machine-executable object code generated by a
    # source language processor.
    #
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
    # AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
    # WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
    # NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
    # PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
    # TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
    # BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
    # DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
    # AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
    # OR PROBABILITY OF SUCH DAMAGES.
    #
    # ==========================================================================
    #+

    #
    # Autodesk Script File
    # MODIFY THIS AT YOUR OWN RISK
    #
    # Creation Date:   27 September 2006
    #
    # swissArmyManip.py
    #
    # This plug-in is an example of a user-defined manipulator,
    # which is comprised of a variety of the base manipulators:
    # - MFnCircleSweepManip
    # - MFnDirectionManip
    # - MFnDiscManip
    # - MFnDistanceManip
    # - MFnFreePointTriadManip
    # - MFnStateManip
    # - MFnToggleManip
    # - MFnRotateManip
    # - MFnScaleManip
    #
    # To use this plug-in:
    #
    #   import maya.cmds as cmds
    #   cmds.createNode("spSwissArmyLocator")
    #
    #   click on the showManipTool
    #

    import maya.OpenMaya as OpenMaya
    import maya.OpenMayaUI as OpenMayaUI
    import maya.OpenMayaRender as OpenMayaRender
    import maya.OpenMayaMPx as OpenMayaMPx

    import math,sys

    glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
    glFT = glRenderer.glFunctionTable()

    kSwissArmyLocatorName = "spSwissArmyLocator"
    kSwissArmyLocatorId = OpenMaya.MTypeId(0x87006)
    kSwissArmyLocatorManipName = "spSwissArmyLocatorManip"
    kSwissArmyLocatorManipId = OpenMaya.MTypeId(0x87007)

    delta1 = 0.01
    delta2 = 0.02
    delta3 = 0.03
    delta4 = 0.04

    # Locator Data
    centre = [  [  0.10, 0.0,  0.10 ],
                [  0.10, 0.0, -0.10 ],
                [ -0.10, 0.0, -0.10 ],
                [ -0.10, 0.0,  0.10 ],
                [  0.10, 0.0,  0.10 ] ]
    state1 = [  [  1.00, 0.0,  1.00 ],
                [  1.00, 0.0,  0.50 ],
                [  0.50, 0.0,  0.50 ],
                [  0.50, 0.0,  1.00 ],
                [  1.00, 0.0,  1.00 ] ]
    state2 = [  [  1.00, 0.0, -1.00 ],
                [  1.00, 0.0, -0.50 ],
                [  0.50, 0.0, -0.50 ],
                [  0.50, 0.0, -1.00 ],
                [  1.00, 0.0, -1.00 ] ]
    state3 = [  [ -1.00, 0.0, -1.00 ],
                [ -1.00, 0.0, -0.50 ],
                [ -0.50, 0.0, -0.50 ],
                [ -0.50, 0.0, -1.00 ],
                [ -1.00, 0.0, -1.00 ] ]
    state4 = [  [ -1.00, 0.0,  1.00 ],
                [ -1.00, 0.0,  0.50 ],
                [ -0.50, 0.0,  0.50 ],
                [ -0.50, 0.0,  1.00 ],
                [ -1.00, 0.0,  1.00 ] ]
    arrow1 = [  [  0.00, 0.0,  1.00 ],
                [  0.10, 0.0,  0.20 ],
                [ -0.10, 0.0,  0.20 ],
                [  0.00, 0.0,  1.00 ] ]
    arrow2 = [  [  1.00, 0.0,  0.00 ],
                [  0.20, 0.0,  0.10 ],
                [  0.20, 0.0, -0.10 ],
                [  1.00, 0.0,  0.00 ] ]
    arrow3 = [  [  0.00, 0.0, -1.00 ],
                [  0.10, 0.0, -0.20 ],
                [ -0.10, 0.0, -0.20 ],
                [  0.00, 0.0, -1.00 ] ]
    arrow4 = [  [ -1.00, 0.0,  0.00 ],
                [ -0.20, 0.0,  0.10 ],
                [ -0.20, 0.0, -0.10 ],
                [ -1.00, 0.0,  0.00 ] ]
    perimeter=[ [  1.10, 0.0,  1.10 ],
                [  1.10, 0.0, -1.10 ],
                [ -1.10, 0.0, -1.10 ],
                [ -1.10, 0.0,  1.10 ],
                [  1.10, 0.0,  1.10 ] ]

    kCentreCount = 5
    kState1Count = 5
    kState2Count = 5
    kState3Count = 5
    kState4Count = 5
    kArrow1Count = 4
    kArrow2Count = 4
    kArrow3Count = 4
    kArrow4Count = 4
    kPerimeterCount = 5

    ########################################################################
    ########################################################################

    class swissArmyLocatorManip(OpenMayaMPx.MPxManipContainer):
        def __init__(self):
            OpenMayaMPx.MPxManipContainer.__init__(self)

            self.fCircleSweepManip = OpenMaya.MDagPath()
            self.fDirectionManip = OpenMaya.MDagPath()
            self.fDiscManip = OpenMaya.MDagPath()
            self.fDistanceManip = OpenMaya.MDagPath()
            self.fFreePointTriadManip = OpenMaya.MDagPath()
            self.fStateManip = OpenMaya.MDagPath()
            self.fToggleManip = OpenMaya.MDagPath()
            self.fRotateManip = OpenMaya.MDagPath()
            self.fScaleManip = OpenMaya.MDagPath()
            self.fNodePath = OpenMaya.MDagPath()

        def createChildren(self):
            # FreePointTriadManip
            self.fFreePointTriadManip = self.addFreePointTriadManip("freePointTriadManip", "point")
            freePointTriadManipFn = OpenMayaUI.MFnFreePointTriadManip(self.fFreePointTriadManip)

            # DirectionManip
            self.fDirectionManip = self.addDirectionManip("directionManip", "direction")
            directionManipFn = OpenMayaUI.MFnDirectionManip(self.fDirectionManip)

            # ToggleManip
            self.fToggleManip = self.addToggleManip("toggleManip", "toggle")
            toggleManipFn = OpenMayaUI.MFnToggleManip(self.fToggleManip)

            # StateManip
            self.fStateManip = self.addStateManip("stateManip", "state")
            stateManipFn = OpenMayaUI.MFnStateManip(self.fStateManip)

            # DiscManip
            self.fDiscManip = self.addDiscManip("discManip", "angle")
            discManipFn = OpenMayaUI.MFnDiscManip(self.fDiscManip)

            # CircleSweepManip
            self.fCircleSweepManip = self.addCircleSweepManip("circleSweepManip", "angle")
            circleSweepManipFn = OpenMayaUI.MFnCircleSweepManip(self.fCircleSweepManip)
            circleSweepManipFn.setCenterPoint(OpenMaya.MPoint(0, 0, 0))
            circleSweepManipFn.setNormal(OpenMaya.MVector(0, 1, 0))
            circleSweepManipFn.setRadius(2.0)
            circleSweepManipFn.setDrawAsArc(True)

            # DistanceManip
            self.fDistanceManip = self.addDistanceManip("distanceManip", "distance")
            distanceManipFn = OpenMayaUI.MFnDistanceManip(self.fDistanceManip)
            distanceManipFn.setStartPoint(OpenMaya.MPoint(0, 0, 0))
            distanceManipFn.setDirection(OpenMaya.MVector(0, 1, 0))

            # RotateManip
            self.fRotateManip = self.addRotateManip("RotateManip", "rotation")
            rotateManipFn = OpenMayaUI.MFnRotateManip(self.fRotateManip)

            # ScaleManip
            self.fScaleManip = self.addScaleManip("scaleManip", "scale")
            scaleManipFn = OpenMayaUI.MFnScaleManip(self.fScaleManip)

        def connectToDependNode(self, node):
            # Get the DAG path
            dagNodeFn = OpenMaya.MFnDagNode(node)
            dagNodeFn.getPath(self.fNodePath)
            parentNode = dagNodeFn.parent(0)
            parentNodeFn = OpenMaya.MFnDagNode(parentNode)

            # Connect the plugs
            nodeFn = OpenMaya.MFnDependencyNode()
            nodeFn.setObject(node)

            # FreePointTriadManip
            freePointTriadManipFn = OpenMayaUI.MFnFreePointTriadManip(self.fFreePointTriadManip)
            try:
                translationPlug = parentNodeFn.findPlug("t")
                freePointTriadManipFn.connectToPointPlug(translationPlug)
            except:
                pass

            # DirectionManip
            directionManipFn = OpenMayaUI.MFnDirectionManip()
            directionManipFn.setObject(self.fDirectionManip)
            try:
                directionPlug = nodeFn.findPlug("arrow2Direction")
                directionManipFn.connectToDirectionPlug(directionPlug)
                startPointIndex = directionManipFn.startPointIndex()
                self.addPlugToManipConversion(startPointIndex)
            except:
                pass

            # DistanceManip
            distanceManipFn = OpenMayaUI.MFnDistanceManip()
            distanceManipFn.setObject(self.fDistanceManip)
            try:
                sizePlug = nodeFn.findPlug("size")
                distanceManipFn.connectToDistancePlug(sizePlug)
                startPointIndex = distanceManipFn.startPointIndex()
                self.addPlugToManipConversion(startPointIndex)
            except:
                pass

            # CircleSweepManip
            circleSweepManipFn = OpenMayaUI.MFnCircleSweepManip(self.fCircleSweepManip)
            try:
                arrow1AnglePlug = nodeFn.findPlug("arrow1Angle")
                circleSweepManipFn.connectToAnglePlug(arrow1AnglePlug)
                centerIndex = circleSweepManipFn.centerIndex()
                self.addPlugToManipConversion(centerIndex)
            except:
                pass

            # DiscManip
            discManipFn = OpenMayaUI.MFnDiscManip(self.fDiscManip)
            try:
                arrow3AnglePlug = nodeFn.findPlug("arrow3Angle")
                discManipFn.connectToAnglePlug(arrow3AnglePlug)
                centerIndex = discManipFn.centerIndex()
                self.addPlugToManipConversion(centerIndex)
            except:
                pass

            # StateManip
            stateManipFn = OpenMayaUI.MFnStateManip(self.fStateManip)
            try:
                statePlug = nodeFn.findPlug("state")
                stateManipFn.connectToStatePlug(statePlug)
                positionIndex = stateManipFn.positionIndex()
                self.addPlugToManipConversion(positionIndex)
            except:
                pass

            # ToggleManip
            toggleManipFn = OpenMayaUI.MFnToggleManip(self.fToggleManip)
            try:
                togglePlug = nodeFn.findPlug("toggle")
                toggleManipFn.connectToTogglePlug(togglePlug)
                startPointIndex = toggleManipFn.startPointIndex()
                self.addPlugToManipConversion(startPointIndex)
            except:
                pass

            # Determine the transform node for the locator
            transformPath = OpenMaya.MDagPath(self.fNodePath)
            transformPath.pop()

            transformNode = OpenMaya.MFnTransform(transformPath)

            # RotateManip
            rotateManipFn = OpenMayaUI.MFnRotateManip(self.fRotateManip)
            try:
                rotatePlug = transformNode.findPlug("rotate")
                rotateManipFn.connectToRotationPlug(rotatePlug)
                rotateManipFn.displayWithNode(node)
            except:
                pass

            # ScaleManip
            scaleManipFn = OpenMayaUI.MFnScaleManip(self.fScaleManip)
            try:
                scalePlug = transformNode.findPlug("scale")
                scaleManipFn.connectToScalePlug(scalePlug)
                scaleManipFn.displayWithNode(node)
            except:
                pass

            self.finishAddingManips()
            OpenMayaMPx.MPxManipContainer.connectToDependNode(self, node)

        def draw(self, view, path, style, status):
            OpenMayaMPx.MPxManipContainer.draw(self, view, path, style, status)
            view.beginGL()
            textPos = OpenMaya.MPoint(self.nodeTranslation())
            view.drawText("Swiss Army Manipulator", textPos, OpenMayaUI.M3dView.kLeft)
            view.endGL()

        def plugToManipConversion(self, theIndex):
            numData = OpenMaya.MFnNumericData()
            numDataObj = numData.create(OpenMaya.MFnNumericData.k3Float)
            vec = self.nodeTranslation()
            numData.setData3Float(vec.x, vec.y, vec.z)
            manipData = OpenMayaUI.MManipData(numDataObj)
            return manipData

        def nodeTranslation(self):
            dagFn = OpenMaya.MFnDagNode(self.fNodePath)
            path = OpenMaya.MDagPath()
            dagFn.getPath(path)
            path.pop()  # pop from the shape to the transform
            transformFn = OpenMaya.MFnTransform(path)
            return transformFn.getTranslation(OpenMaya.MSpace.kWorld)

    ########################################################################
    ########################################################################

    class swissArmyLocator(OpenMayaMPx.MPxLocatorNode):
        aSize = OpenMaya.MObject()         # The size of the locator
        aPoint = OpenMaya.MObject()
        aPointX = OpenMaya.MObject()
        aPointY = OpenMaya.MObject()
        aPointZ = OpenMaya.MObject()
        aArrow1Angle = OpenMaya.MObject()
        aArrow2Direction = OpenMaya.MObject()
        aArrow2DirectionX = OpenMaya.MObject()
        aArrow2DirectionY = OpenMaya.MObject()
        aArrow2DirectionZ = OpenMaya.MObject()
        aArrow3Angle = OpenMaya.MObject()
        aArrow4Distance = OpenMaya.MObject()
        aState = OpenMaya.MObject()
        aToggle = OpenMaya.MObject()

        def __init__(self):
            OpenMayaMPx.MPxLocatorNode.__init__(self)

        def compute(self, plug, data):
            return OpenMaya.kUnknownParameter

        def draw(self, view, path, style, status):

            # Get the size
            thisNode = self.thisMObject()

            plug = OpenMaya.MPlug(thisNode, swissArmyLocator.aSize)
            sizeVal = plug.asMDistance()

            arrow1AnglePlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aArrow1Angle)
            arrow1Angle = arrow1AnglePlug.asMAngle()
            angle1 = -arrow1Angle.asRadians() - 3.1415927/2.0

            arrow3AnglePlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aArrow3Angle)
            arrow3Angle = arrow3AnglePlug.asMAngle()
            angle3 = arrow3Angle.asRadians()

            statePlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aState)
            state = statePlug.asInt()

            togglePlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aToggle)
            toggle = togglePlug.asBool()

            directionXPlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aArrow2DirectionX)
            directionYPlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aArrow2DirectionY)
            directionZPlug = OpenMaya.MPlug(thisNode, swissArmyLocator.aArrow2DirectionZ)
            dirX = directionXPlug.asDouble()
            dirY = directionYPlug.asDouble()
            dirZ = directionZPlug.asDouble()

            angle2 = math.atan2(dirZ, dirX)
            angle2 += 3.1415927

            multiplier = sizeVal.asCentimeters()

            view.beginGL()

            if ((style == OpenMayaUI.M3dView.kFlatShaded) or
                    (style == OpenMayaUI.M3dView.kGouraudShaded)):
                # Push the color settings
                glFT.glPushAttrib(OpenMayaRender.MGL_CURRENT_BIT)

                if (status == OpenMayaUI.M3dView.kActive):
                    view.setDrawColor(13, OpenMayaUI.M3dView.kActiveColors)
                else:
                    view.setDrawColor(13, OpenMayaUI.M3dView.kDormantColors)

                if (toggle):
                    if (status == OpenMayaUI.M3dView.kActive):
                        view.setDrawColor(15, OpenMayaUI.M3dView.kActiveColors)
                    else:
                        view.setDrawColor(15, OpenMayaUI.M3dView.kDormantColors)
                    glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                    last = kCentreCount - 1
                    for i in range(last):
                        glFT.glVertex3f(centre[i][0] * multiplier,
                                   centre[i][1] * multiplier,
                                   centre[i][2] * multiplier)
                    glFT.glEnd()

                if (state == 0):
                    if (status == OpenMayaUI.M3dView.kActive):
                        view.setDrawColor(19, OpenMayaUI.M3dView.kActiveColors)
                    else:
                        view.setDrawColor(19, OpenMayaUI.M3dView.kDormantColors)
                    glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                    last = kState1Count - 1
                    for i in range(last):
                        glFT.glVertex3f(state1[i][0] * multiplier,
                                        state1[i][1] * multiplier,
                                        state1[i][2] * multiplier)
                    glFT.glEnd()

                if (state == 1):
                    if (status == OpenMayaUI.M3dView.kActive):
                        view.setDrawColor(21, OpenMayaUI.M3dView.kActiveColors)
                    else:
                        view.setDrawColor(21, OpenMayaUI.M3dView.kDormantColors)
                    glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                    last = kState2Count - 1
                    for i in range(last):
                        glFT.glVertex3f(state2[i][0] * multiplier,
                                        state2[i][1] * multiplier,
                                        state2[i][2] * multiplier)
                    glFT.glEnd()

                if (state == 2):
                    if (status == OpenMayaUI.M3dView.kActive):
                        view.setDrawColor(18, OpenMayaUI.M3dView.kActiveColors)
                    else:
                        view.setDrawColor(18, OpenMayaUI.M3dView.kDormantColors)
                        glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                        last = kState3Count - 1
                        for i in range(last):
                            glFT.glVertex3f(state3[i][0] * multiplier,
                                            state3[i][1] * multiplier,
                                            state3[i][2] * multiplier)
                        glFT.glEnd()

                if (state == 3):
                    if (status == OpenMayaUI.M3dView.kActive):
                        view.setDrawColor(17, OpenMayaUI.M3dView.kActiveColors)
                    else:
                        view.setDrawColor(17, OpenMayaUI.M3dView.kDormantColors)
                    glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                    last = kState4Count - 1
                    for i in range(last):
                        glFT.glVertex3f(state4[i][0] * multiplier,
                                        state4[i][1] * multiplier,
                                        state4[i][2] * multiplier)
                    glFT.glEnd()

                if (status == OpenMayaUI.M3dView.kActive):
                    view.setDrawColor(12, OpenMayaUI.M3dView.kActiveColors)
                else:
                    view.setDrawColor(12, OpenMayaUI.M3dView.kDormantColors)
                glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                last = kArrow1Count - 1
                for i in range(last):
                    glFT.glVertex3f((-arrow1[i][0] * multiplier * math.cos(angle1) - arrow1[i][2] * multiplier * math.sin(angle1)),
                                    (arrow1[i][1] * multiplier + delta1),
                                    (arrow1[i][2] * multiplier * math.cos(angle1) - arrow1[i][0] * multiplier * math.sin(angle1)))
                glFT.glEnd()

                if (status == OpenMayaUI.M3dView.kActive):
                    view.setDrawColor(16, OpenMayaUI.M3dView.kActiveColors)
                else:
                    view.setDrawColor(16, OpenMayaUI.M3dView.kDormantColors)
                glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                last = kArrow2Count - 1
                for i in range(last):
                    glFT.glVertex3f((-arrow2[i][0] * multiplier * math.cos(angle2) - arrow2[i][2] * multiplier * math.sin(angle2)),
                                    (arrow2[i][1] * multiplier + delta2),
                                    (arrow2[i][2] * multiplier * math.cos(angle2) - arrow2[i][0] * multiplier * math.sin(angle2)))
                glFT.glEnd()

                if (status == OpenMayaUI.M3dView.kActive):
                    view.setDrawColor(13, OpenMayaUI.M3dView.kActiveColors)
                else:
                    view.setDrawColor(13, OpenMayaUI.M3dView.kDormantColors)
                glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                last = kArrow3Count - 1
                for i in range(last):
                    glFT.glVertex3f((-arrow3[i][0] * multiplier * math.cos(angle3) - arrow3[i][2] * multiplier * math.sin(angle3)),
                                    (arrow3[i][1] * multiplier + delta3),
                                    (arrow3[i][2] * multiplier * math.cos(angle3) - arrow3[i][0] * multiplier * math.sin(angle3)))
                glFT.glEnd()

                if (status == OpenMayaUI.M3dView.kActive):
                    view.setDrawColor(5, OpenMayaUI.M3dView.kActiveColors)
                else:
                    view.setDrawColor(5, OpenMayaUI.M3dView.kDormantColors)
                glFT.glBegin(OpenMayaRender.MGL_TRIANGLE_FAN)
                last = kArrow4Count - 1
                for i in range(last):
                    glFT.glVertex3f((arrow4[i][0] * multiplier),
                                    (arrow4[i][1] * multiplier + delta4),
                                    (arrow4[i][2] * multiplier))
                glFT.glEnd()

                glFT.glPopAttrib()

            # Draw the outline of the locator
            glFT.glBegin(OpenMayaRender.MGL_LINES)

            if toggle:
                last = kCentreCount - 1
                for i in range(last):
                    glFT.glVertex3f(centre[i][0] * multiplier,
                                    centre[i][1] * multiplier,
                                    centre[i][2] * multiplier)
                    glFT.glVertex3f(centre[i+1][0] * multiplier,
                                    centre[i+1][1] * multiplier,
                                    centre[i+1][2] * multiplier)

            if (state == 0):
                last = kState1Count - 1
                for i in range(last):
                    glFT.glVertex3f(state1[i][0] * multiplier,
                                    state1[i][1] * multiplier,
                                    state1[i][2] * multiplier)
                    glFT.glVertex3f(state1[i+1][0] * multiplier,
                                    state1[i+1][1] * multiplier,
                                    state1[i+1][2] * multiplier)

            if (state == 1):
                last = kState2Count - 1
                for i in range(last):
                    glFT.glVertex3f(state2[i][0] * multiplier,
                                    state2[i][1] * multiplier,
                                    state2[i][2] * multiplier)
                    glFT.glVertex3f(state2[i+1][0] * multiplier,
                                    state2[i+1][1] * multiplier,
                                    state2[i+1][2] * multiplier)

            if (state == 2):
                last = kState3Count - 1
                for i in range(last):
                    glFT.glVertex3f(state3[i][0] * multiplier,
                                    state3[i][1] * multiplier,
                                    state3[i][2] * multiplier)
                    glFT.glVertex3f(state3[i+1][0] * multiplier,
                                    state3[i+1][1] * multiplier,
                                    state3[i+1][2] * multiplier)

            if (state == 3):
                last = kState4Count - 1
                for i in range(last):
                    glFT.glVertex3f(state4[i][0] * multiplier,
                                    state4[i][1] * multiplier,
                                    state4[i][2] * multiplier)
                    glFT.glVertex3f(state4[i+1][0] * multiplier,
                                    state4[i+1][1] * multiplier,
                                    state4[i+1][2] * multiplier)

            last = kArrow1Count - 1
            for i in range(last):
                glFT.glVertex3f((-arrow1[i][0] * multiplier * math.cos(angle1) - arrow1[i][2] * multiplier * math.sin(angle1)),
                                (arrow1[i][1] * multiplier + delta1),
                                (arrow1[i][2] * multiplier * math.cos(angle1) - arrow1[i][0] * multiplier * math.sin(angle1)))
                glFT.glVertex3f((-arrow1[i+1][0] * multiplier * math.cos(angle1) - arrow1[i+1][2] * multiplier * math.sin(angle1)),
                                (arrow1[i+1][1] * multiplier + delta1),
                                (arrow1[i+1][2] * multiplier * math.cos(angle1) - arrow1[i+1][0] * multiplier * math.sin(angle1)))

            last = kArrow2Count - 1
            for i in range(last):
                glFT.glVertex3f((-arrow2[i][0] * multiplier * math.cos(angle2) - arrow2[i][2] * multiplier * math.sin(angle2)),
                                (arrow2[i][1] * multiplier + delta2),
                                (arrow2[i][2] * multiplier * math.cos(angle2) - arrow2[i][0] * multiplier * math.sin(angle2)))
                glFT.glVertex3f((-arrow2[i+1][0] * multiplier * math.cos(angle2) - arrow2[i+1][2] * multiplier * math.sin(angle2)),
                                (arrow2[i+1][1] * multiplier + delta2),
                                (arrow2[i+1][2] * multiplier * math.cos(angle2) - arrow2[i+1][0] * multiplier * math.sin(angle2)))

            last = kArrow3Count - 1
            for i in range(last):
                glFT.glVertex3f((-arrow3[i][0] * multiplier * math.cos(angle3) - arrow3[i][2] * multiplier * math.sin(angle3)),
                                (arrow3[i][1] * multiplier + delta3),
                                (arrow3[i][2] * multiplier * math.cos(angle3) - arrow3[i][0] * multiplier * math.sin(angle3)))
                glFT.glVertex3f((-arrow3[i+1][0] * multiplier * math.cos(angle3) - arrow3[i+1][2] * multiplier * math.sin(angle3)),
                                (arrow3[i+1][1] * multiplier + delta3),
                                (arrow3[i+1][2] * multiplier * math.cos(angle3) - arrow3[i+1][0] * multiplier * math.sin(angle3)))

            last = kArrow4Count - 1
            for i in range(last):
                glFT.glVertex3f((arrow4[i][0] * multiplier),
                                (arrow4[i][1] * multiplier + delta4),
                                (arrow4[i][2] * multiplier))
                glFT.glVertex3f((arrow4[i+1][0] * multiplier),
                                (arrow4[i+1][1] * multiplier + delta4),
                                (arrow4[i+1][2] * multiplier))

            last = kPerimeterCount - 1
            for i in range(last):
                glFT.glVertex3f(perimeter[i][0] * multiplier,
                                perimeter[i][1] * multiplier,
                                perimeter[i][2] * multiplier)
                glFT.glVertex3f(perimeter[i+1][0] * multiplier,
                                perimeter[i+1][1] * multiplier,
                                perimeter[i+1][2] * multiplier)

            glFT.glEnd()

            view.endGL()

        def isBounded(self):
            return True

        def boundingBox(self):
            thisNode = self.thisMObject()
            plug = OpenMaya.MPlug(thisNode, swissArmyLocator.aSize)
            sizeVal = plug.asMDistance()

            multiplier = sizeVal.asCentimeters()

            corner1 = OpenMaya.MPoint(-1.1, 0.0, -1.1)
            corner2 = OpenMaya.MPoint(1.1, 0.0, 1.1)

            corner1 = corner1 * multiplier
            corner2 = corner2 * multiplier

            return OpenMaya.MBoundingBox(corner1, corner2)

    ########################################################################
    ########################################################################

    def locatorCreator():
        return OpenMayaMPx.asMPxPtr(swissArmyLocator())

    def locatorInit():
        unitFn = OpenMaya.MFnUnitAttribute()
        numericFn = OpenMaya.MFnNumericAttribute()

        # aSize
        swissArmyLocator.aSize = unitFn.create("size", "sz", OpenMaya.MFnUnitAttribute.kDistance, 10.0)
        unitFn.setStorable(True)
        unitFn.setWritable(True)

        # aPoint
        swissArmyLocator.aPointX = numericFn.create("pointX", "ptx", OpenMaya.MFnNumericData.kDouble, 0.0)
        swissArmyLocator.aPointY = numericFn.create("pointY", "pty", OpenMaya.MFnNumericData.kDouble, 0.0)
        swissArmyLocator.aPointZ = numericFn.create("pointZ", "ptz", OpenMaya.MFnNumericData.kDouble, 0.0)
        swissArmyLocator.aPoint = numericFn.create("point", "pt", swissArmyLocator.aPointX, swissArmyLocator.aPointY, swissArmyLocator.aPointZ)

        # aArrow1Angle
        swissArmyLocator.aArrow1Angle = unitFn.create("arrow1Angle", "a1a", OpenMaya.MFnUnitAttribute.kAngle, 0.0)

        # aArrow2Direction
        swissArmyLocator.aArrow2DirectionX = numericFn.create("arrow2DirectionX", "a2x", OpenMaya.MFnNumericData.kDouble, 1.0)
        swissArmyLocator.aArrow2DirectionY = numericFn.create("arrow2DirectionY", "a2y", OpenMaya.MFnNumericData.kDouble, 0.0)
        swissArmyLocator.aArrow2DirectionZ = numericFn.create("arrow2DirectionZ", "a2z", OpenMaya.MFnNumericData.kDouble, 0.0)
        swissArmyLocator.aArrow2Direction = numericFn.create("arrow2Direction", "dir", swissArmyLocator.aArrow2DirectionX, swissArmyLocator.aArrow2DirectionY, swissArmyLocator.aArrow2DirectionZ)

        # aArrow3Angle
        swissArmyLocator.aArrow3Angle = unitFn.create("arrow3Angle", "a3a", OpenMaya.MFnUnitAttribute.kAngle, 0.0)
        # aArrow4Distance
        swissArmyLocator.aArrow4Distance = unitFn.create("arrow2Distance", "dis", OpenMaya.MFnUnitAttribute.kDistance, 0.0)

        # aState
        swissArmyLocator.aState = numericFn.create("state", "s", OpenMaya.MFnNumericData.kLong, 0)

        # aToggle
        swissArmyLocator.aToggle = numericFn.create("toggle", "t", OpenMaya.MFnNumericData.kBoolean, False)

        swissArmyLocator.addAttribute(swissArmyLocator.aPoint)
        swissArmyLocator.addAttribute(swissArmyLocator.aArrow1Angle)
        swissArmyLocator.addAttribute(swissArmyLocator.aArrow2Direction)
        swissArmyLocator.addAttribute(swissArmyLocator.aArrow3Angle)
        swissArmyLocator.addAttribute(swissArmyLocator.aArrow4Distance)
        swissArmyLocator.addAttribute(swissArmyLocator.aState)
        swissArmyLocator.addAttribute(swissArmyLocator.aToggle)
        swissArmyLocator.addAttribute(swissArmyLocator.aSize)

        OpenMayaMPx.MPxManipContainer.addToManipConnectTable(kSwissArmyLocatorId)

    def locatorManipCreator():
         return OpenMayaMPx.asMPxPtr(swissArmyLocatorManip())

    def locatorManipInit():
        OpenMayaMPx.MPxManipContainer.initialize()

    # initialize the script plug-in
    def initializePlugin(mobject):
        mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")

        try:
            mplugin.registerNode(kSwissArmyLocatorName,
                                    kSwissArmyLocatorId,
                                    locatorCreator,
                                    locatorInit,
                                    OpenMayaMPx.MPxNode.kLocatorNode)
        except:
            print "Failed to register context command: %s" % kSwissArmyLocatorName
            raise

        try:
            mplugin.registerNode(kSwissArmyLocatorManipName,
                                    kSwissArmyLocatorManipId,
                                    locatorManipCreator,
                                    locatorManipInit,
                                    OpenMayaMPx.MPxNode.kManipContainer)
        except:
            print "Failed to register node: %s" % kSwissArmyLocatorManipName
            raise

    # uninitialize the script plug-in
    def uninitializePlugin(mobject):
        mplugin = OpenMayaMPx.MFnPlugin(mobject)

        try:
            mplugin.deregisterNode(kSwissArmyLocatorId)
        except:
            print "Failed to deregister context command: %s" % kSwissArmyLocatorName
            raise

        try:
            mplugin.deregisterNode(kSwissArmyLocatorManipId)
        except:
            print "Failed to deregister node: %s" % kSwissArmyLocatorManipName
            raise