Maya Python – Select By Volume

posted in: Uncategorized | 1

I wrote up this quick script in response to a tech-artists.org forum post requested help on this selection-helper method. The below script should properly select all objects in a scene that are at least partially contained within the specified object’s bounding box volume.  This script is currently limited by the fact that the bounding box calculation performed by the xform command returns an axis-aligned box. To improve this, calculate the boundingbox with respect to the object’s local transformation – see http://tech-artists.org/forum/showthread.php?2860-maya-Object-Aligned-Bounding-Box. This will allow you to rotate your bounding volume object and still return visually expected results.

import maya.cmds as cmds

class BoundingBox():
''' Helper class for bounding box-related calculations. '''

    @classmethod
    def FromShape(cls, shapeObj):
    ''' Constructor method to create a bounding box from a shape. '''

        boundingBox = BoundingBox()
        bb = cmds.xform(shapeObj, q=True, bb=True)
        boundingBox.minX = bb[0]
        boundingBox.minY = bb[1]
        boundingBox.minZ = bb[2]
        boundingBox.maxX = bb[3]
        boundingBox.maxY = bb[4]
        boundingBox.maxZ = bb[5]
        return boundingBox

    def ContainsPoint(self, point):
    ''' Returns whether or not a point is contained in this bounding box. '''
        return (point[0] > self.minX and point[0] < self.maxX and point[1] > self.minY and point[1] < self.maxY and point[2] > self.minZ and point[2] < self.maxZ)

    def ContainsShape(self, shape):
    ''' Returns whether or not a shape is intersecting with this bounding box. '''
        shapeBB = BoundingBox.FromShape(shape)
        return (shapeBB.minX < self.maxX and shapeBB.maxX > self.minX) and (shapeBB.minY < self.maxY and shapeBB.maxY > self.minY) and(shapeBB.maxZ < self.maxZ and shapeBB.maxZ > self.minZ)

def SelectByVolume(volumeObj):
 ''' Selects all transforms in the scene that are within the specified argument's bounding box volume. '''

    # Create bounding box class from object
    boundingBox = BoundingBox.FromShape(volumeObj)

    # Get all scene objects asides from bounding box
    cmds.select(allDagObjects=True)
    sceneObjs = [obj for obj in cmds.ls(sl=True) if obj != volumeObj]

    # Compare against every object in our scene to determine what is in our volume
    newSelection = list()
    for obj in sceneObjs:
        objPos = cmds.xform(obj, q=True, rotatePivot=True, ws=True)

        # If the shape's bounding box intersects with the volume's bounding box
        if boundingBox.ContainsShape(obj):
            print "%s is contained."%obj
            newSelection.append(obj)

        # NOTE - Optional alternative means to determine objects within volume.
        # If the center of the object is contained
        #if boundingBox.ContainsPoint(objPos):
            # print "%s is contained."%obj
            # newSelection.append(obj)

    # Silly but compact list comprehension way of getting all our objects
    #newSelection = [obj for obj in [obj for obj in cmds.ls(sl=True) if obj != volumeObj] if boundingBox.ContainsPoint( cmds.xform(obj, q=True, rotatePivot=True, ws=True))]

    # Update selection
    if newSelection:
        cmds.select(newSelection)
    else:
        cmds.select(clear=True)

# Usage
yourVolumeObject = 'pCube1'
SelectByVolume(yourVolumeObject)

Unity Editor Script – Group Selected

posted in: Uncategorized | 0

This post offers an editor convenience class for Maya-like grouping of objects in the Unity scene hierarchy. It configures this script to run with the hotkey (Ctrl+G). Drop this into the editor. Your artists will love it. It currently does not take into account any parent groups that might be above your selected transforms. It will always try to group the selected to the an empty node at the world root.

 

using UnityEngine;
using UnityEditor;
using System.Collections;

public class GroupSelected : EditorWindow
{
    /// &lt;summary&gt;
    ///  Creates an empty node at the center of all selected nodes and parents all selected underneath it. 
    ///  Basically a nice re-creation of Maya grouping!
    /// &lt;/summary&gt;

    [MenuItem(&quot;GameObject/Group Selected %g&quot;, priority = 80)]
    static void Init()
    {
        Transform[] selected = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.TopLevel);

        GameObject emptyNode = new GameObject();
        Vector3 averagePosition = Vector3.zero;
        foreach(Transform node in selected)
        {
            averagePosition += node.position;
        }
        if (selected.Length &gt; 0)
        {
            averagePosition /= selected.Length;
        }
        emptyNode.transform.position = averagePosition;
        emptyNode.name = &quot;group&quot;;
        foreach (Transform node in selected)
        {
            node.parent = emptyNode.transform;
        }
   }
}