コード例 #1
0
    def startup(self, origin):
        origin.timer.stop()
        if psVersion == 1:
            origin.messageParent = MaxPlus.GetQMaxWindow()
        else:
            origin.messageParent = MaxPlus.GetQMaxMainWindow()
        MaxPlus.NotificationManager.Register(
            MaxPlus.NotificationCodes.FilePostOpenProcess, origin.sceneOpen)

        origin.startasThread()
コード例 #2
0
def CreateMaterials(y_position):
    CreateText(MaxPlus.Point3(-45, y_position, 0), "Materials")
    x_position = 0.0
    b = CreateTeapot()
    for m in GeneratePlugins(MaxPlus.SuperClassIds.Material, MaxPlus.Mtl):
        print m
        node = MaxPlus.Factory.CreateNode(b)
        node.Position = MaxPlus.Point3(x_position, y_position, 0)
        node.Material = m
        x_position += 10.0
コード例 #3
0
def Mirror(node, mirrorAxis):
    scale = None
    if mirrorAxis == "X":
        scale = MaxPlus.Point3(-1, 1, 1)
    elif mirrorAxis == "Y":
        scale = MaxPlus.Point3(1, -1, 1)
    elif mirrorAxis == "Z":
        scale = MaxPlus.Point3(1, 1, -1)
    else:
        print("Error axis do not match")
    node.Scaling = scale
コード例 #4
0
def show():
    try:
        qtwindow = MaxPlus.GetQMaxWindow()
    except:
        qtwindow = MaxPlus.GetQMaxMainWindow()
    se = scriptEditor.scriptEditorClass(parent=qtwindow)
    #se.installEventFilter(MaxDialogEvents())
    se.runCommand('import MaxPlus')
    #se.MaxEventFilter = MaxDialogEvents()
    #se.installEventFilter(se.MaxEventFilter)
    se.show()
コード例 #5
0
 def selectCam(self, origin):
     if self.isNodeValid(origin, origin.curCam):
         MaxPlus.SelectionManager_ClearNodeSelection()
         camNode = MaxPlus.INode.GetINodeByHandle(origin.curCam)
         if camNode.GetTarget().GetUnwrappedPtr() is not None:
             camNodes = MaxPlus.INodeTab()
             camNodes.Append(camNode)
             camNodes.Append(camNode.GetTarget())
             MaxPlus.SelectionManager_SelectNodes(camNodes)
         else:
             MaxPlus.SelectionManager_SelectNode(camNode)
コード例 #6
0
def CreateHelpers(y_position):
    CreateText(MaxPlus.Point3(-45, y_position, 0), "Helpers")
    x_position = 0.0
    for obj in GeneratePlugins(MaxPlus.SuperClassIds.Helper,
                               MaxPlus.HelperObject):
        node = MaxPlus.Factory.CreateNode(obj)
        node.Position = MaxPlus.Point3(x_position, y_position, 0)
        x_position += 10.0
        if ((x_position % 260.0) < 0.001):
            x_position = 0.0
            y_position += 20
    return y_position
コード例 #7
0
def getElements(node):
    obj = node.GetObject()
    objTriMesh = obj.AsTriObject()
    objMesh = objTriMesh.GetMesh()

    numVerts = objMesh.GetNumVertices()
    numFaces = objMesh.GetNumFaces()

    allElements = []

    faces = MaxPlus.BitArray(numFaces)
    faces.SetAll()
    verts = [[] for i in range(numVerts)]

    for i in range(0, numFaces):
        face = objMesh.GetFace(i)
    for k in range(0, 3):
        verts[face.GetVert(k)].append(i)

    for i in range(0, numFaces):
        if faces[i]:

            element = []
            element.append(i)
            faceBits = MaxPlus.BitArray(numFaces)
            vertBits = MaxPlus.BitArray(numVerts)

            #for j in range(0, len(element)):
            j = 0
            while j < len(element):
                fi = element[j]
                j += 1

            if not faceBits[fi]:
                face = objMesh.GetFace(fi)

            for k in range(0, 3):
                v = face.GetVert(k)

            if vertBits[v]:
                continue

    for singleFace in range(0, len(verts[v])):
        element.append(verts[v][singleFace])
        vertBits.Set(v, True)

        faceBits.Set(fi, True)
        faces.Clear(fi)

        allElements.append(MaxPlus.BitArray(faceBits))

    return allElements
コード例 #8
0
def setKeyPRS(node):
    """
    Set key base on the curreent TrnaformController
    :param node:
    :return: None
    """
    transformController = getTransformControl(node)
    posController = transformController.GetPositionController()
    rotController = transformController.GetRotationController()
    scaleController = transformController.GetScaleController()
    posController.AddNewKey(MaxPlus.Now(), MaxPlus.Constants.AddkeyFlagged)
    rotController.AddNewKey(MaxPlus.Now(), MaxPlus.Constants.AddkeyFlagged)
    scaleController.AddNewKey(MaxPlus.Now(), MaxPlus.Constants.AddkeyFlagged)
コード例 #9
0
def main():
    obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Sphere)
    obj.ParameterBlock.Radius.Value = 50.0
    node = MaxPlus.Factory.CreateNode(obj)
    vp = MaxPlus.ViewportManager.GetActiveViewport()
    hittype = MaxPlus.Constants.HittypeSolid
    hitflags = MaxPlus.Constants.HitAnysolid
    pt = MaxPlus.IPoint2(400, 200)
    hit = obj.HitTest(node, hittype, 1, hitflags, pt, vp)
    print 'hit succes', hit, 'for point', pt
    pt = MaxPlus.IPoint2(0, 0)
    hit = obj.HitTest(node, hittype, 1, hitflags, pt, vp)
    print 'hit success', hit, 'for point', pt
コード例 #10
0
def CreateObjects(y_position):
    CreateText(MaxPlus.Point3(-88, y_position, 0), "Geometric objects")
    x_position = 0.0
    for obj in GeneratePlugins(MaxPlus.SuperClassIds.GeomObject,
                               MaxPlus.GeomObject):
        node = MaxPlus.Factory.CreateNode(obj)
        node.Position = MaxPlus.Point3(x_position, y_position, 0)

        x_position += 10.0
        if ((x_position % 260.0) < 0.001):
            x_position = 0.0
            y_position += 20
    return y_position
コード例 #11
0
def CreateModifiers(y_position):
    CreateText(MaxPlus.Point3(-45, y_position, 0), "Modifiers")
    x_position = 0.0
    for m in GeneratePlugins(MaxPlus.SuperClassIds.Osm, MaxPlus.Modifier):
        b = CreateBox()
        node = MaxPlus.Factory.CreateNode(b)
        node.Position = MaxPlus.Point3(x_position, y_position, 0)
        node.AddModifier(m)
        x_position += 10.0
        if ((x_position % 260.0) < 0.001):
            x_position = 0.0
            y_position += 20
    return y_position
コード例 #12
0
def findObjectAndBake(target, dummyroot, suffix, oppositeSuffix,
                      copyDirection):
    bakeSources = list(sdknode.getChildren(dummyroot))
    targetChildrens = list(sdknode.getChildren(target))
    targetChildrens.append(target)
    bakeTargets = sdkutility.findObjectBySuffix(oppositeSuffix,
                                                targetChildrens)

    for bakeTarget in bakeTargets:
        bakeSource = findBakeSource(bakeTarget, bakeSources, oppositeSuffix,
                                    suffix)
        if bakeSource is not None:
            sdkutility.RemoveScaleKeys(bakeTarget)
            sdkutility.AddPositionListAndConstraint(bakeTarget)
            SetPositionConstraintTarget(bakeSource, bakeTarget)
            sdkutility.AddRotationListAndConstraint(bakeTarget)
            SetOrientationConstraintTarget(bakeSource, bakeTarget)

    selectionTab = MaxPlus.INodeTab()
    for n in bakeTargets:
        selectionTab.Append(n)
    MaxPlus.SelectionManager.SelectNodes(selectionTab)
    plotFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                            "plot.ms")
    plot = open(plotFile, "r")
    MaxPlus.Core.EvalMAXScript(plot.read())
コード例 #13
0
    def CreateBone(old_node, parent_node=None, newname=None):
        def maxify_point3(point):
            return "[{}, {}, {}]".format(
                point.GetX(), point.GetY(), point.GetZ()
            )

        pos_1 = maxify_point3(old_node.worldpos)
        pos_2 = pos_1
        zaxis = "[0, 0, 1]"

        if old_node.children:
            pos_2 = maxify_point3(old_node.children[0].worldpos)

        if old_node.node_in_max:
            axis_type = old_node.node_in_max.GetBoneAxis()
            if axis_type == 0:
                zaxis = maxify_point3(MaxPlus.Point3(0, 0, 1))
            else:
                raise Exception("Not implemented!")

        # generate maxscript
        gen_script = \
            "BoneSys.createBone {} {} {}".format(pos_1, pos_2, zaxis)

        # try to create bone, escape on fail
        fbnode = MaxPlus.Core.EvalMAXScript(gen_script)
        if not fbnode:
            return None

        maxnode = fbnode.GetNode()
        maxnode.SetName(newname or old_node.node_name)
        return maxnode
コード例 #14
0
def main():
    MaxPlus.FileManager.Reset(True)

    w = QtWidgets.QWidget(MaxPlus.GetQMaxMainWindow(), QtCore.Qt.Dialog)
    _GCProtector.widgets.append(w)
    w.resize(250, 100)
    w.setWindowTitle('Spinner Test')

    main_layout = QtWidgets.QVBoxLayout()
    label = QtWidgets.QLabel("Click button to create a cylinder in the scene")
    main_layout.addWidget(label)

    spinner = QtWidgets.QSpinBox()
    spinner.setRange(1, 10)
    spinner.setValue(1)
    main_layout.addWidget(spinner)
    #spinner.valueChanged.connect(function)

    cylinder_btn = QtWidgets.QPushButton("Cylinder")
    cylinder_btn.clicked.connect(make_cylinder)
    main_layout.addWidget(cylinder_btn)

    #    textEdit = QtWidgets.QLineEdit()
    #    textEdit.setText("Edit box")
    #    main_layout.addWidget(textEdit)
    w.setLayout(main_layout)
    w.show()
コード例 #15
0
def DeleteHierarchy(node):
    children = GetChildren(node)
    tab = MaxPlus.INodeTab()
    for i in children:
        tab.Append(i)
    MaxPlus.INode.DeleteNodes(tab)
    node.Delete()
コード例 #16
0
ファイル: genCalImages.py プロジェクト: windsor718/poseTrack
def createObject(x, y):
    """Create sphere object in 3dsmax"""
    boxObject = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Sphere)
    boxObject.ParameterBlock.Radius.Value = resolution / 4
    boxNode = MaxPlus.Factory.CreateNode(boxObject)
    boxNode.Position = MaxPlus.Point3(x, y, 0)
    return boxNode
    def execute(self, operation, in_frame=None, out_frame=None, **kwargs):
        """
        Main hook entry point
        
        :operation: String
                    Frame operation to perform
        
        :in_frame: int
                    in_frame for the current context (e.g. the current shot, 
                                                      current asset etc)
                    
        :out_frame: int
                    out_frame for the current context (e.g. the current shot, 
                                                      current asset etc)
                    
        :returns:   Depends on operation:
                    'set_frame_range' - Returns if the operation was succesfull
                    'get_frame_range' - Returns the frame range in the form (in_frame, out_frame)
        """

        if operation == "get_frame_range":
            ticks = MaxPlus.Core.EvalMAXScript("ticksperframe").GetInt()
            current_in = MaxPlus.Animation.GetAnimRange().Start() / ticks
            current_out = MaxPlus.Animation.GetAnimRange().End() / ticks
            return (current_in, current_out)
        elif operation == "set_frame_range":
            import MaxPlus
            ticks = MaxPlus.Core.EvalMAXScript("ticksperframe").GetInt()
            range = MaxPlus.Interval(in_frame * ticks, out_frame * ticks)
            MaxPlus.Animation.SetRange(range)
            return True
コード例 #18
0
ファイル: engine.py プロジェクト: shotgunsoftware/tk-3dsmax
    def _get_dialog_parent(self):
        """
        Get the QWidget parent for all dialogs created through :meth:`show_dialog` :meth:`show_modal`.

        :return: QT Parent window (:class:`PySide.QtGui.QWidget`)
        """
        # Older versions of Max make use of special logic in _create_dialog
        # to handle window parenting. If we can, though, we should go with
        # the more standard approach to getting the main window.
        if self._max_version_to_year(self._get_max_version()) > 2020:
            # getMAXHWND returned a float instead of a long, which was completely
            # unusable with PySide in 2017 to 2020, but starting 2021
            # we can start using it properly.
            # This logic was taken from
            # https://help.autodesk.com/view/3DSMAX/2020/ENU/?guid=__developer_creating_python_uis_html
            import shiboken2
            from sgtk.platform.qt import QtGui

            widget = QtGui.QWidget.find(pymxs.runtime.windows.getMAXHWND())
            return shiboken2.wrapInstance(
                shiboken2.getCppPointer(widget)[0], QtGui.QMainWindow)
        elif self._max_version_to_year(self._get_max_version()) > 2017:
            #
            return MaxPlus.GetQMaxMainWindow()
        else:
            return super(MaxEngine, self)._get_dialog_parent()
コード例 #19
0
def show():
    se = scriptEditor.scriptEditorClass(parent=MaxPlus.GetQMaxWindow())
    se.installEventFilter(MaxDialogEvents())
    se.runCommand('import MaxPlus')
    se.MaxEventFilter = MaxDialogEvents()
    se.installEventFilter(se.MaxEventFilter)
    se.show()
コード例 #20
0
	def sm_export_exportShotcam(self, origin, startFrame, endFrame, outputName):
		if startFrame == endFrame:
			self.setFrameRange(origin, startFrame = startFrame, endFrame = endFrame + 1)
		else:
			self.setFrameRange(origin, startFrame = startFrame, endFrame = endFrame)

		self.executeScript(origin, "AlembicExport.CoordinateSystem = #Maya")
		self.executeScript(origin, "AlembicExport.CacheTimeRange = #StartEnd")
		self.executeScript(origin, "AlembicExport.StepFrameTime = 1")
		self.executeScript(origin, "AlembicExport.StartFrameTime = %s" % startFrame)
		self.executeScript(origin, "AlembicExport.EndFrameTime = %s" % endFrame)
		self.executeScript(origin, "AlembicExport.ParticleAsMesh = False")
		if startFrame == endFrame:
			self.executeScript(origin, "FbxExporterSetParam \"Animation\" False", returnVal=False)
			MaxPlus.Animation.SetTime(startFrame*MaxPlus.Animation.GetTicksPerFrame(), False)
		else:
			self.executeScript(origin, "FbxExporterSetParam \"Animation\" True", returnVal=False)

		self.selectCam(origin)
		MaxPlus.FileManager.ExportSelected(outputName + ".abc", True)

		exportFBX = self.executeScript(origin, "(classof (maxOps.getNodeByHandle %s)) != Physical" % origin.curCam)

		if exportFBX:
			self.selectCam(origin)
			MaxPlus.FileManager.ExportSelected(outputName + ".fbx", True)

		if origin.chb_convertExport.isChecked():
			outputName = os.path.join(os.path.dirname(os.path.dirname(outputName)), "meter", os.path.basename(outputName))
			if not os.path.exists(os.path.dirname(outputName)):
				os.makedirs(os.path.dirname(outputName))
			self.executeScript(origin, """
sHelper = point()
sHelper.name = ("SCALEOVERRIDE_%s")
for obj in selection do(
	obj.parent = sHelper
)
sVal = 0.01
sHelper.scale = [sVal, sVal, sVal]
""" % MaxPlus.INode.GetINodeByHandle(origin.curCam).GetName())

			self.selectCam(origin)
			MaxPlus.FileManager.ExportSelected(outputName + ".abc", True)

			if exportFBX:
				self.selectCam(origin)
				MaxPlus.FileManager.ExportSelected(outputName + ".fbx", True)

			self.executeScript(origin, """
for obj in selection do(
	if obj.parent != undefined and obj.parent.name == ("SCALEOVERRIDE_" + obj.name) do (
		sVal = 1
		sHelper = obj.parent
		sHelper.scale = [sVal, sVal, sVal]
		delete sHelper
	)
)
""")

		MaxPlus.SelectionManager_ClearNodeSelection(False)
コード例 #21
0
    def walk_material_hierarchy(cls, node):
        """Walks through the material hierarchy through their parameters

        :param node:
        :return:
        """
        for p in node.ParameterBlock.Parameters:
            # decide what to do by looking at the parameter type of the p param
            param_type_name = MaxPlus.FPTypeGetName(p.GetParamType())
            value = p.Value
            if param_type_name in ['MtlTab', 'TexmapTab']:
                # it contains multiple materials
                for i, v in enumerate(value):
                    yield (node, p, v, i)
                    try:
                        v.GetName()
                        for pp in cls.walk_material_hierarchy(v):
                            yield pp
                    except (RuntimeError, AttributeError):
                        pass
            else:
                try:
                    value.GetName()
                    yield (node, p, value, -1)
                    if isinstance(value, MaxPlus.MtlBase):
                        for pp in cls.walk_material_hierarchy(value):
                            yield pp
                except (RuntimeError, AttributeError):
                    pass
コード例 #22
0
def _create_login_menu():
    """
    Creates and displays a Shotgun user login menu.
    """

    _delete_login_menu()

    mb = MaxPlus.MenuBuilder(constants.SG_MENU_LABEL)
    login_action = MaxPlus.ActionFactory.Create(
        constants.SG_MENU_ITEMS_CATEGORY, "Log In to Shotgun...", _login_user)
    mb.AddItem(login_action)
    mb.AddSeparator()

    jump_to_website_action = MaxPlus.ActionFactory.Create(
        constants.SG_MENU_ITEMS_CATEGORY, "Learn about Shotgun...",
        _jump_to_website)
    mb.AddItem(jump_to_website_action)

    jump_to_signup_action = MaxPlus.ActionFactory.Create(
        constants.SG_MENU_ITEMS_CATEGORY, "Try Shotgun for Free...",
        _jump_to_signup)
    mb.AddItem(jump_to_signup_action)

    main_menu = MaxPlus.MenuManager.GetMainMenu()

    # Add menu item at the second to last position,
    # which should be before "Help"
    menu_index = main_menu.GetNumItems() - 1
    mb.Create(main_menu, menu_index)
コード例 #23
0
def pywolf_sync_active_layer_models():
	return
	if wolf_version == "":
		logger.log("PyWolf not available")
		return
			
	#first select nodes of active layer
	MaxPlus.SelectionManager.ClearNodeSelection()
	_layer = MaxPlus.LayerManager.GetCurrentLayer()
	_layer_name = _layer.GetName()
	if _layer_name == "_Problems_" or _layer_name == "_Boundaries_" or _layer_name == "_Inner_Layers_" or _layer_name == "_Middle_Layers_" or _layer_name == "_Outer_Layers_":
		logger.log("Could not add following Layers: _Problems_, _Boundaries_, _Inner_Layers_, _Middle_Layers_, _Outer_Layers_")
		return
	
	_selecting_nodes = MaxPlus.INodeTab()
	for _node in _layer.GetNodes():
		_selecting_nodes.Append(_node)
	if len(_selecting_nodes) != 0:
		#select
		MaxPlus.SelectionManager.SelectNodes(_selecting_nodes)
		#_collada_exp_path = tmp_dir + "\W" + get_unique_name() + ".DAE"
		#export the scene in the format of OpenCollada
		_max_sxript_cmd = "exp_classes = exporterPlugin.classes																\r\n\
		_idx = findItem exp_classes OpenCOLLADAExporter																			\r\n\
		if _idx != 0 do 																															\r\n\
		(																																					\r\n\
		   file_url = \"c:\\Wolf\\models.DAE\"																				   	\r\n\
		   exportFile (file_url) #noprompt selectedOnly:on using:exp_classes[_idx]								\r\n\
     )"
		MaxPlus.Core.EvalMAXScript(_max_sxript_cmd)
コード例 #24
0
def GetMaxMainWindow():
    if MAXVERSION() >= MAX2021:
        import qtmax
        return qtmax.GetQMaxMainWindow()
    else:
        import MaxPlus
        return MaxPlus.GetQMaxMainWindow()
コード例 #25
0
 def __init__(self, parent=None):
     base_type.__init__(self)
     ui_type.__init__(self)
     self.setupUi(self)
     MaxPlus.AttachQWidgetToMax(self)
     pb = self.pushButton
     pb.clicked.connect(buttonClicked)
コード例 #26
0
    def add_menu_item(self, menu_node, new_command):
        if self._NAME == 'maya': import maya.cmds as cmds
        elif self._NAME == 'max': import MaxPlus
        else:
            LOG.debug('CANT find software: {}'.format(self._NAME))
            return

        sub_menu = ''

        for keys, item in new_command.iteritems():

            if isinstance(item, dict) or isinstance(item, list):
                if self._NAME == 'maya':
                    sub_menu = cmds.menuItem(p=menu_node, l=keys, sm=True)
                elif self._NAME == 'max':
                    MaxPlus.MenuManager.UnregisterMenu(unicode(keys))
                    sub_menu = MaxPlus.MenuBuilder(keys)
                    self.add_sub_menu.append(sub_menu)
                elif self._NAME == 'nuke':
                    sub_menu = menu_node.addMenu(keys)

                if sub_menu and isinstance(item, list):
                    for it in item:
                        self.add_menu_item(sub_menu, it)
                elif sub_menu:
                    self.add_menu_item(sub_menu, item)

            else:
                if self._NAME == 'maya':
                    eval('cmds.{}'.format(item).format(menu_node))
                elif self._NAME == 'max':
                    import max_menu
                    eval('menu_node.{}'.format(item))
                elif self._NAME == 'nuke':
                    eval('menu_node.{}'.format(item))
コード例 #27
0
ファイル: zync_3dsmax.py プロジェクト: Shasthojoy/zync-3dsmax
    def _loadSpinnerDialog(self):
        ui_file_name = os.path.join(SubmitWindowController._get_self_dir(),
                                    SPINNER_DIALOG_FILE_NAME)
        SpinnerDialogType, BaseType = MaxPlus.LoadUiType(ui_file_name)

        class SpinnerDialog(SpinnerDialogType, BaseType):
            def __init__(self, parent=None):
                SpinnerDialogType.__init__(self, parent)
                BaseType.__init__(self, parent)
                self.setupUi(self)
                self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint
                                    | Qt.WindowTitleHint)

                spinner_filename = os.path.join(
                    SubmitWindowController._get_self_dir(),
                    SPINNER_GIF_FILE_NAME)
                self.spinner_movie = QMovie(spinner_filename)
                self.spinner_movie.setScaledSize(QSize(40, 40))
                self.spinner_label.setMovie(self.spinner_movie)

            def show(self):
                super(SpinnerDialog, self).show()
                self.spinner_movie.start()

        SubmitWindowController.spinner_dialog = SpinnerDialog(None)
コード例 #28
0
	def setFrameRange(self, origin, startFrame, endFrame):
		if startFrame == endFrame:
			QMessageBox.warning(self.core.messageParent, "Warning", "The startframe and the endframe cannot be the same in 3dsMax.")
			return

		MaxPlus.Animation.SetRange(MaxPlus.Interval(startFrame*MaxPlus.Animation.GetTicksPerFrame(), endFrame*MaxPlus.Animation.GetTicksPerFrame()))
		MaxPlus.Animation.SetTime(startFrame*MaxPlus.Animation.GetTicksPerFrame())
コード例 #29
0
def generate_mesh_in_3dsmax(meshatom):
    """
    @param mesh: atom mesh
    """

    meshcls = MaxPlus.ClassIds.TriMeshGeometry
    geom = MaxPlus.Factory.CreateGeomObject(meshcls)
    tri = MaxPlus.TriObject._CastFrom(geom)

    verts = meshatom.verts
    faces = meshatom.faces

    mesh = tri.GetMesh()
    mesh.SetNumVerts(len(verts))
    mesh.SetNumFaces(len(faces) / 3)

    for idx, v in enumerate(verts):
        mesh.SetVert(idx, MaxPlus.Point3(*v.pos()))

    for idx in range(0, len(faces), 3):
        face = mesh.GetFace(idx / 3)
        face.SetVerts(faces[idx + 0], faces[idx + 1], faces[idx + 2])

    mesh.InvalidateGeomCache()
    mesh.InvalidateTopologyCache()
    MaxPlus.Factory.CreateNode(tri)
コード例 #30
0
ファイル: initPlugin.py プロジェクト: rdsgautier/DccPlugin
def customMaxMenu(name):
    if not MaxPlus.MenuManager.MenuExists(name):
        mb = MaxPlus.MenuBuilder(name)
        mb.AddItem(action)
        menu = mb.Create(MaxPlus.MenuManager.GetMainMenu())
    else:
        print 'The menu ', name, ' already exists'