Home Technical Talk

Need help with a combining script.

polycounter lvl 12
Offline / Send Message
Hayden Zammit polycounter lvl 12
Hi everyone. I'm trying to sort out a script I need for combining and readying building assets for Unity for Maya.

My outliner looks like this:

tWB0Lc9.png

I have to click on storehouse_t0_LOD0 in this example and when I run the script it goes through and deletes history, freezes transformations and combines the msh_ groups that are there.

The problem that I'm having is that I use a lot of instanced geometry, and the script won't work once it hits anything that is instanced. It also won't merge instances.

I was hoping someone good with scripting could help me out with this.

Here's the script that I'm using:

// ---- EVEN EVEN More Better Combine
// // Looks through all nodes under current selection.
// Check if node name is the same as the strings we are looking for.
// Plug that name into the EVEN More Better Combine V2.3 to combine
//scriptEditorInfo -clearHistory;
{
//The strings we are looking for
string $targetMeshes[] = {"msh_roof","msh_building","msh_alpha","msh_sign"};
int $targetMeshesSize = size($targetMeshes);
//List of nodes as a full path
string $targetGroups[];
//List of nodes for selected object
//string $nodes[] = `ls -sl -dag`;
string $nodes[] = `ls -sl`;
//Stores child name of node to compare with $targetMeshes[]
string $nodeChildren[]={};
//Stores full path to node we are looking for
string $nodeChildrenFull[]={};
int $nodeChildrenSize;
int $nodeTokens;
int $k=0;
//K LOOP
do
{
//cyle through all nodes in the scene
for($node in $nodes)
{

//get child of current node
$nodeChildren =`listRelatives -c $node`;
//get full path name
$nodeChildrenFull = `listRelatives -f $node`;

$nodeChildrenSize = size($nodeChildren);



//cycle through targetMeshes array
$h=0;

//H LOOP
do
{

//if the child has the same name as the target mesh
if($nodeChildren[$h] == $targetMeshes[$k])
{


//add the full path of the desired node to the $targetGroups array
//$targetGroups is what the EVEN More Better Combine V2.3 looks at
$targetGroups[size($targetGroups)] = $nodeChildrenFull[$h];
}

$h++;
}
while ($h <= $nodeChildrenSize);


}

$k++;
}
while ($k <= $targetMeshesSize);

int $targetGroupSize = size($targetGroups);
int $m=0;
//print($targetGroups);
//print($targetGroups[0]);
//print($targetGroups[1]);
while($m <= $targetGroupSize)
{

if($targetGroups[$m] != ""){

// ---- EVEN More Better Combine V2.3
//
// Combines Polygons deletes history and keeps it within it's Group if it is in one.
// Also Keeps the name of the first Poly selected.
// Now it merges verts and Centers the pivot as requested. =D
// the initial Tolerance of the merge vert can be changed below or you can change it in the history after.
//
Change these values for the Merge Vert Tolorance
//
string $onOff = "on";
float $k = 0.001;
//
Change these values for the Merge Vert Tolorance
//

//edited line
string $sel[]={$targetGroups[$m]};
string $fpo = `firstParentOf $sel[0]`;
string $buffer[];
string $selBuffer[];
int $numTokens = `tokenize $fpo "|" $buffer`;
string $newPoly[] = `polyUnite -ch 0 -n $sel[0] $sel`;
int $j=0;
int $i=0;
if ($fpo != "")
{
while ($j<= $numTokens)
{
if (!`objExists $buffer[$j]`)
{
if($j != 0)
{
$j--;
}
//group -em -n $buffer[$j];
if (`objExists $buffer[$j]`)
{
parent $newPoly $buffer[$j];
}
break;
}
$j++;
}
}
int $selNumTokens = `tokenize $sel[0] "|" $selBuffer`;
$i = $selNumTokens -1;
$newPoly[0] = `rename $newPoly $selBuffer[$i]`;
if ($onOff == "on")
{
polyMergeVertex -d $k -am 1 -ch 0 $newPoly;
}
xform -cp $newPoly;
select -r $newPoly;
}
$m++;
}
}

Replies

  • Bartalon
    Options
    Offline / Send Message
    Bartalon polycounter lvl 12
    Hey there. I have a custom Mesh Combine script that checks for instances and converts them (which will also prevent other instances from disappearing if you have more), perhaps my bit of code can be of some help. Unfortunately I don't have the time right now to go through the rest of your code, but hopefully this can be of some use in the meantime.
    //  Check for and convert instances
            string $select[] = `ls -sl`;
            for ($i=0; $i<`size $select`; ++$i) {
                string $realName[];
                int $last;
            // In case the same name exists in different places, remove hierarchy from the name
            // so it can keep the original name for the rest of the operation
                tokenize($select[$i], "|", $realName);
                $last = `size $realName`-1; // this saves the actual name of the object excluding all the hierarchy names
                string $shape[] = `listRelatives -f -s $select[$i]`;
                if ($shape[0] != "") { // checks if object is a group
                    string $relatives[] = `listRelatives -ap $shape[0]`;
                    if (`size $relatives` > 1 ) { // instances will have multiple shape relatives
                        select $select[$i];
                        ConvertInstanceToObject; //this may kick out some warnings, but no errors
                        rename $realName[$last]; //this keeps the object named the same so future operations don't break from a "no object matches name" error
                    }
                }
            }
    
  • Hayden Zammit
    Options
    Offline / Send Message
    Hayden Zammit polycounter lvl 12
    Thanks Bartalon, I had to select all the groups contents and then run your script, and it worked awesome. I'll just have to go through and run that script before I run the main script.

    Do you have anything similar to your script that merges and cleans up references, or is that a whole different thing? I have no idea with scripting.

    Thanks again.
  • Bartalon
    Options
    Offline / Send Message
    Bartalon polycounter lvl 12
    Hey, good to know it worked. I wrote a small script which includes that bit of code so this time around it should do what I think it is that you want it to do... It will merge everything underneath the LOD groups into a mesh, retain the name, and keep it parented under the main "storehouse" group. Any spare instances will be left behind.

    You'll want to have "storehouse" selected when you run the script.

    Here's a before and after simulation:

    BEFORE
    ScriptBefore.PNG

    AFTER
    ScriptAfter.PNG

    The naming conventions don't matter as long as you maintain a three-group hierarchy (main asset name, the group with whatever "t0" means, and the LOD group.

    I tried to comment everything so you can see what's going on. It looks like a jumbled mess here but it's easier to read inside the Script Editor :)
    {
        //select your highest hierarchy of an asset and run script
        //in the example provided in your image, you would select "storehouse"
    
        //for your main asset group such as "storehouse"
        string $select[] = `ls -sl`;
        //for groups such as _t0, _t1, etc.
        string $subGroup[];
        //for groups such as _t0_LOD0, _t0_LOD1, etc.
        string $lod[];
        //this will contain all the msh_ objects to be merged
        string $children[];
        //makes sure you have a selection    
        if ($select[0] == "") { error "Nothing selected!"; }
        //lists all the _t0, _t1, _t2, etc. groups
        $subGroup = `listRelatives -c $select[0]`;
    
        //this loop will go through all the _t* groups
        for($s=0; $s<`size $subGroup`; ++$s) {
            //finds all _LOD groups
            $lod = `listRelatives -c $subGroup[$s]`;
    
            //this loop will go through all the LOD groups and merge the contents of each
            for($l=0; $l<`size $lod`; ++$l) {
                //now we get the msh_ nodes
                $children = `listRelatives -c -f $lod[$l]`;
                select -hi $children;
                // this stores all hierarchy
                string $allObjects[] = `ls -sl`;
    
                //this loop will go through and check for instancing (tweaked to work for groups)
                for($i=0; $i<`size $allObjects`; ++$i) {
                    string $realName[];
                    int $last;
                    // In case the same name exists in different places, remove hierarchy from the name
                    // so it can keep the original name for the rest of the operation
                    tokenize($allObjects[$i], "|", $realName);
                    // this saves the actual name of the object excluding all the hierarchy names
                    $last = `size $realName`-1;
                    string $shape[] = `listRelatives -f -s $allObjects[$i]`;
                    // checks if object is a group
                    if ($shape[0] != "") {
                        string $relatives[] = `listRelatives -ap $shape[0]`;
                         // instances will have multiple shape relatives
                        if (`size $relatives` > 1 ) {
                            select $allObjects[$i];
                            //this may kick out some warnings, but no errors
                            ConvertInstanceToObject;
                            //this keeps the object named the same so future operations don't break from a "no object matches name" error                        
                            rename $realName[$last];
                        }
                    }
                }
                //now we can merge ALL the things
                select -hi $lod[$l];
                polyUnite -ch 1 -mergeUVSets 1;
                DeleteHistory;
                CenterPivot;
                //keeps it parented to main group
                select -tgl $select[0];
                Parent;
                //keeps it named according to the LOD group it was under
                rename $lod[$l];
            }        
        }   
    }
    
    Do you have anything similar to your script that merges and cleans up references, or is that a whole different thing? I have no idea with scripting.
    I don't really work with references so I've never written anything to deal with them. Sorry!
  • Hayden Zammit
    Options
    Offline / Send Message
    Hayden Zammit polycounter lvl 12
    This seems so close to what I need. Is there a way I can incorporate that first script that gets rid of the instances into a part of this second script so that it works all in one?

    The real issue I'm having is that its combining and giving me the wrong groups.

    Like, if you see the hierarchy in that image I supplied, I need the exact same hiearchy, except I need it to go through and take msh building, msh alpha, msh roof groups, etc. and combine them, rename the resulting mesh and keep it where its group was before.

    I hope that makes sense.

    Thanks for the help so far. The instancing one is awesome so far.
  • Bartalon
    Options
    Offline / Send Message
    Bartalon polycounter lvl 12
    No big deal, just nested one more loop and it gets the job done. I also added a check to prevent some errors and ensure things get renamed properly. Also it has the part from before where it converts instances. You might get some warnings/errors but neither should interfere with the operation. Try this one out for size (sorry for the poor coding)
    {
        //select your highest hierarchy of an asset and run script
        //in the example provided in your image, you would select "storehouse"
    
        //for your main asset group such as "storehouse"
        string $select[] = `ls -sl`;
        //for groups such as _t0, _t1, etc.
        string $subGroup[];
        //for groups such as _t0_LOD0, _t0_LOD1, etc.
        string $lod[];
        //this will contain all the msh_ objects to be merged
        string $children[];
        //makes sure you have a selection    
        if ($select[0] == "") { error "Nothing selected!"; }
        //lists all the _t0, _t1, _t2, etc. groups
        $subGroup = `listRelatives -c -f $select[0]`;
    
        //this loop will go through all the _t* groups
        for($s=0; $s<`size $subGroup`; ++$s) {
            //finds all _LOD groups
            $lod = `listRelatives -c -f $subGroup[$s]`;
    
            //this loop will go through all the LOD groups and merge the contents of each
            for($l=0; $l<`size $lod`; ++$l) {
                //now we get the msh_ nodes
                $children = `listRelatives -c -f $lod[$l]`;
                select -hi $children;
                // this stores all hierarchy
                string $allObjects[] = `ls -sl`;
    
                //this loop will go through and check for instancing (tweaked to work for groups)
                for($i=0; $i<`size $allObjects`; ++$i) {
                    string $realName[];
                    int $last;
                    // In case the same name exists in different places, remove hierarchy from the name
                    // so it can keep the original name for the rest of the operation
                    tokenize($allObjects[$i], "|", $realName);
                    // this saves the actual name of the object excluding all the hierarchy names
                    $last = `size $realName`-1;
                    string $shape[] = `listRelatives -f -s $allObjects[$i]`;
                    // checks if object is a group
                    if ($shape[0] != "") {
                        string $relatives[] = `listRelatives -ap $shape[0]`;
                         // instances will have multiple shape relatives
                        if (`size $relatives` > 1 ) {
                            select $allObjects[$i];
                            //this may kick out some warnings, but no errors
                            ConvertInstanceToObject;
                            //this keeps the object named the same so future operations don't break from a "no object matches name" error                        
                            rename $realName[$last];
                        }
                    }
                }
                                
                //now we can merge ALL the things
                //this loop will go through each msh_group and combine that instead
                for($c=0; $c<`size $children`; ++$c) {
                    string $shortName[];
                    //removing hierarchy from name
                    tokenize($children[$c], "|", $shortName);
                    select -hi $children[$c];
                    //need to make sure there is more than 1 object or it'll error out
                    if (size(`ls -s -sl`) > 1) {
                        polyUnite -ch 1 -mergeUVSets 1;
                        DeleteHistory;
                        CenterPivot;
                        //keeps it parented to main group
                        select -tgl $lod[$l];
                        Parent;
                        //keeps it named according to the LOD group it was under
                        rename $shortName[`size $shortName`-1];
                    }
                    else {
                        select $children[$c];
                        Ungroup;
                        rename $shortName[`size $shortName`-1];
                    }
                }
            }        
        }
    }
    
  • Hayden Zammit
    Options
    Offline / Send Message
    Hayden Zammit polycounter lvl 12
    Thanks heaps Bartalon. This works great sets it all up ready for me to export. Has a bit of trouble with the references I use, but I think I can tweak my workflow to make it work.

    Thanks a lot.
Sign In or Register to comment.