MEL How-To #83

Back · Previous · Next Maya

How do I devise a setup whereby when I select one object, Maya automatically selects another object?

The only method with which Maya communicates a change in selection is via a scriptJob. There is no attribute on an object to indicate whether it is part of the active selection list, and nothing in the DG becomes "dirty" when you simply click something with the mouse.

Now here's the kicker: The event doesn't tell you what was just selected (or unselected), only that the selection has changed. You'll have to figure out for yourself what's moved in or out of the queue.

Now, here's the real kicker: Whenever you perform a selection as a response to a SelectionChanged event, you add the selection to the undo queue. Attempting to undo the selection puts you back into the callback for the SelectionChanged event, which undoes your undo by restoring the selection just the way it was. Result: You can't undo.

So, what you have to do within the SelectionChanged event is to 'undo' the selection, modify the array of items to select if necessary, and 'redo' the selection. This tip from the Highend3D Maya Mailing List courtesy Roger Klado.

I also found that the "Click Drag Select" mode would trigger a SelectionChanged event which, upon obediently performing its undo, made the Click Drag ineffectual. So I had to wrap the works with a query to the Undo queue to assert it was triggered by a selection event and not a move event.

In the following example "ObjectB" will be selected whenever "ObjectA" is selected.

// Set up the scriptJob
scriptJob -event "SelectionChanged" reactToSelection;

// Callback for "SelectionChanged" scriptJob event.
global proc reactToSelection()
{
  string $whyAmIHere = `undoInfo -q -undoName`;

  // Wrapper to prevent unwanted Undo during 'Click Drag Select' mode.
  if ( `gmatch $whyAmIHere "select*"` )
  {
    string $select[] = `ls -sl`;

    // Undo the user selection.
    undo;

    int $hasObjectA = stringArrayCount( "ObjectA", $select );

    if ( $hasObjectA )
    {
      $select = stringArrayCatenate( { "ObjectB" }, $select );
    }
    else
    // Don't allow ObjectB to be selected alone.
    {
      $select = stringArrayRemove( { "ObjectB" }, $select );
    }

    // Redo with modified selection.
    select $select;
  }
}
There's bound to be some issues with this that I haven't foreseen. If it breaks, please
let me know.

Acknowledgements

Highend3D.com

Roger Klado, Man'O'War

09 February 2002