Search code examples
pythonviewportmaya

Maya – Select objects in viewport via Python


Can anyone help me? Is it possible to make a script with Python to automatically select every object in Maya's viewport?

Is it possible?


Solution

  • It's very possible though you have to use Maya's api to do it. You can use OpenMayaUI.MDrawTraversal to collect all objects within a camera's frustum.

    This may seem more long winded than using OpenMaya.MGlobal.selectFromScreen, but it gives you a few benefits:

    1. You can do it on any camera, despite it not being used as an active view.
    2. You can perform whatever you need to do all in memory without selecting and forcing a redraw.
    3. OpenMaya.MGlobal.selectFromScreen will be interface dependent, meaning that it's not possible to execute it on Maya batch jobs. This will work on either case.

    That being said, here's an example that will create a bunch of random boxes, create a camera looking at them, then select all boxes that are within the camera's view:

    import random
    
    import maya.cmds as cmds
    import maya.OpenMaya as OpenMaya
    import maya.OpenMayaUI as OpenMayaUI
    
    
    # Create a new camera.
    cam, cam_shape = cmds.camera()
    cmds.move(15, 10, 15, cam)
    cmds.rotate(-25, 45, 0, cam)
    cmds.setAttr("{}.focalLength".format(cam), 70)
    cmds.setAttr("{}.displayCameraFrustum".format(cam), True)
    
    # Create a bunch of boxes at random positions.
    val = 10
    for i in range(50):
        new_cube, _ = cmds.polyCube()
        cmds.move(random.uniform(-val, val), random.uniform(-val, val), random.uniform(-val, val), new_cube)
    
    # Add camera to MDagPath.
    mdag_path = OpenMaya.MDagPath()
    sel = OpenMaya.MSelectionList()
    sel.add(cam)
    sel.getDagPath(0, mdag_path)
    
    # Create frustum object with camera.
    draw_traversal = OpenMayaUI.MDrawTraversal()
    draw_traversal.setFrustum(mdag_path, cmds.getAttr("defaultResolution.width"), cmds.getAttr("defaultResolution.height"))  # Use render's resolution.
    draw_traversal.traverse()  # Traverse scene to get all objects in the camera's view.
    
    frustum_objs = []
    
    # Loop through objects within frustum.
    for i in range(draw_traversal.numberOfItems()):
        # It will return shapes at first, so we need to fetch its transform.
        shape_dag_path = OpenMaya.MDagPath()
        draw_traversal.itemPath(i, shape_dag_path)
        transform_dag_path = OpenMaya.MDagPath()
        OpenMaya.MDagPath.getAPathTo(shape_dag_path.transform(), transform_dag_path)
    
        # Get object's long name and make sure it's a valid transform.
        obj = transform_dag_path.fullPathName()
        if cmds.objExists(obj):
            frustum_objs.append(obj)
    
    
    # At this point we have a list of objects that we can filter by type and do whatever we want.
    # In this case just select them.
    cmds.select(frustum_objs)
    

    Hope that gives you a better direction.