Form and Space

creating CG 3D since 2001

  • Connect @
  • Linked in
  • Vimeo
  • Twitter
Replace Add Randomize

MEL: Replace Add Randomize

Matthew | November 22, 2013

No Comments

Honorable Mention:

Updated May 1, 2014
This script now matches pivot location. In other words, if you move the pivot point of the source object and/or the pivot point of the target, this script will match source pivot point to target pivot point. This should make it even easier for the artist to craft complex scenes with the pivot points as their constant value. This is included with my Maya 2015 preferences.

Updated March 24, 2014.
Now you can download them as global mel scripts, and add them to your scripts folder in your preferences. Also, add it as a shelf button. This will be included in my Maya 2015 preferences.

Posted November 22, 2013

I’ve been adding more to the previous script I posted. This version has a simple GUI, and it will randomize the objects being replaced.

For example, imagine you create your tree and all it’s leaves based on the same leaf. Now you decide to create multiple variations of the same leaf, and want to place them into the tree. This script will preserve your hierarchy, give you options to duplicate or instantiate, and give you the option to state how of many objects you want to be placed randomly. Add this script to your shelf, and run it when you need it. This is a great compliment to the path constraint script. Also, this would be good for replacing proxy objects in a scene, where you now have a material and texture on your new object and want to swap out the placeholders.

Another example is with tank tread. Let us assume you used a proxy object for your tack tread, and now you’re happy with your new mesh and texture. Set the script to “replace”, Duplicates unchecked, and amount set to 1. Select your tank tread proxy objects, then the new tread mesh. Execute Script. Assuming the pivots points are manages well, then this will work.

Let us pretend the cubes are leaves on a tree.



We then select all the leaves. Then select all the new textured leaves with variation. Enter how you would like to replace the cubes. I used “replace” (delete the old leaves), “duplicates” is unchecked (so I get instances), and I enter the amount of new textured leaves, six (selected last).

Select all the cubes, then the replacements.

Select all the cubes, then the replacements.

Click “Execute Script”.


The final result.

Replace/Add Randomized Objects
- with UI
version 0.4
March 24, 2014
Author: Matthew L. Stoehr

- Duplicate and match object transformations of 
  all selected objects.
- Preserves inputs for duplicate objects.
- If there's a parent of the object to match, 
  parent the new duplicate.
- Toggle instantiate or Duplicate.
- Toggle hide, delete, or do nothing.
- Randomly select from the last selected to duplicate, 
  and define the amount.

How to use:
1. Select all objects to match.
2. Select object to duplicate last. (Last object selected is duplicated).
3. Run script.

Example usage:
Ideal for replacing a large amount of objects, 
such as leaves on a tree, cars in a parking lot, fence posts, etc.  
Also, good for swapping out proxy objects.

global proc mls_replaceAddRandomizedUI()
    string $mls_radioSelected; 
    int $mls_checked;
    int $mls_cnt;
    int $dev = false;
    if ($dev && `window -exists "mls_rarWindow"`)
        deleteUI -window "mls_rarWindow";
    if (!`window -exists "mls_rarWindow"`)
        window -title "Replace/Add Randomized"
               -iconName "RAR"
               -resizeToFitChildren true
               -width 100
        columnLayout -adjustableColumn true;
        radioCollection -parent "mls_rarWindow" "mls_rc";              
            radioButton -select -label "Replace" -cl "mls_rc" -ann "Replace the original objects." "Replace";
            radioButton -label "Hide" -cl "mls_rc" -ann "Hide the original objects." "Hide";
            radioButton -label "Add" -cl "mls_rc" -ann "Add to the original objects." "Add";
        $mls_radioSelected = `radioCollection -query -select "mls_rc"`;
        checkBox -label "Create duplicates" -ann "Defaults to instances." "mls_checkBox";   
        $mls_checked = `checkBox -q -value "mls_checkBox"`;
        text -label "How many are selected last.";
        intField -value 1 -ann ("Enter the amount of\nobjects selected last.\n"+
                                "From this amount objects will be randomly selected.") "mls_last";
        $mls_cnt = `intField -q -value "mls_last"`;
        //button -label "OK" -c ("mls_replaceAddObjectsUI");
        button -label "OK" -c ("mls_replaceAddRandomized()");
        button -label "Close" -command ("deleteUI -window RAR_window");
    showWindow "mls_rarWindow";
global proc mls_replaceAddRandomized()
    string $c[] = `ls -sl`;    
    int $s = size($c);
    //duplicate or instantiate
    int $di;
    //replace, hide, or add
    string $rha;
    //random object(s)
    int $ro;
    //random objects to select from
    string $selectFrom[];
    Query the UI (requires mls_replaceAddObjectsUI script) elements,
    did the user change the defaults?
    Like a polycube, the elements of the UI can be queried
    once they are created.    
    if(`radioButton -q -sl "Replace"`)
        $rha = "Replace";
    if(`radioButton -q -sl "Hide"`)
        $rha = "Hide";
    if(`radioButton -q -sl "Add"`)
        $rha = "Add";
    $di = `checkBox -q -value mls_checkBox`;
    $ro = `intField -q -value mls_last`;
    //stop the script if the user didn't select 2 or more
    if($s < 2) { error "Please select at least two objects."; } //collect the objects to be randomly duplicated for ($i = $ro; $i > 0; $i--)
        stringArrayInsertAtIndex(0, $selectFrom, $c[$s-$i]);
    //loop through all the objects, except the amount of random object(s)
    for ($i = 0; $i < $s - $ro; $i++)
         string $dObject[];
         int $randObject = rand(0,$ro); 
         //get parent
         string $thisParent = firstParentOf($c[$i]);
         //get matrix 
         float $m[] = `xform -q -ws -m $c[$i]`;
            $dObject = `duplicate -un $selectFrom[$randObject]`;
            $dObject = `instance $selectFrom[$randObject]`;
         //get pivot, use scale pivot to create vector easily
         vector $piv = `xform -q -os -sp $c[$i]`;
         //get pivot from duplicate
         vector $pivDup = `xform -q -os -sp $dObject[0]`;
         //add pivots, invert the duplicate pivot values
         float $pivX = ($piv.x) + -($pivDup.x);
         float $pivY = ($piv.y) + -($pivDup.y);
         float $pivZ = ($piv.z) + -($pivDup.z);
         vector $pivNew = <<$pivX, $pivY, $pivZ>>;
         //set matrix, matching all transform values
         xform -ws -m ($m[0]) ($m[1]) ($m[2]) ($m[3])
                      ($m[4]) ($m[5]) ($m[6]) ($m[7])
                      ($m[8]) ($m[9]) ($m[10]) ($m[11])
                      ($m[12]) ($m[13]) ($m[14]) ($m[15])
         //set pivot, reset to former values, if any
         xform -os -piv ($pivDup.x) ($pivDup.y) ($pivDup.z) $dObject[0];
         //set translation, relative move using pivot values
         xform -r -os -t ($pivNew.x) ($pivNew.y) ($pivNew.z) $dObject[0];
        //if there is a parent            
        if(`objExists $thisParent`)
            parent $dObject[0] $thisParent;
        switch($rha) {
        		case "Replace" :
        			delete $c[$i]; 
        		case "Hide" :
        			hide $c[$i]; 
        			// do nothing

Leave a Reply