Level One Magic
"Any sufficiently advanced technology is indistinguishable from magic." - Arthur C. Clarke
ajk_unityTools.mel
/*

    SCRIPT NAME:  ajk_unityTools
    CREATED BY:   Andy Kelts
    DATE EDITED:  04/05/2011
_______________________________________________________________________________

    Comments:     Tools for prepping and sending files to Unity Projects.
                  Includes utilities for automating shader creation, light 
                  creation, collision objects, scrolling UVs and ignoring 
                  nodes on export.

 */

global proc ajk_ignoreTag(int $tagValue)
{
    string $selected[] = `ls -sl -l`;
    for($each in $selected)
    {
        string $objType = `objectType $each`;
        if($objType == "transform" || $objType == "joint")
        {
            if($tagValue)
            {
                print("Tagging " + $objType + "\t" + $each + "\n");
                if(!`objExists ($each + ".ignoreInUnity")`)
                    addAttr -at "bool" -k 1 -longName "ignoreInUnity" $each;
                setAttr ($each + ".ignoreInUnity") $tagValue;
            }
            else if(`objExists ($each + ".ignoreInUnity")`)
                deleteAttr ($each + ".ignoreInUnity");
        }
        else
            print("skipping " + $each + "\t" + $objType + "\n");
    }
}

global proc ajk_collisionTag(int $mode)
{
    string $collisionModes[] = { 
                    "sphereCollider", 
                    "capsuleCollider", 
                    "boxCollider", 
                    "meshCollider" };
    if($mode == 0)
    {
        int $tagValue = `radioButtonGrp -q -sl ajk_radioCollision`;
        string $collisionMode = "";
        if($tagValue < 5)
            $collisionMode = $collisionModes[$tagValue - 1];

        if($collisionMode != "")
        {
            string $sel[] = `ls -sl -l`;
            for($each in $sel)
            {
                for($cm in $collisionModes)
                    if(`objExists ($each + "." + $cm)`)
                        deleteAttr ($each + "." + $cm);
                print("Adding collision tag " + $collisionMode + " to " + $each + "\n");
                addAttr -at "bool" -k 1 -longName $collisionMode $each;
                setAttr ($each + "." + $collisionMode) 1;
            }
            optionVar -iv ajk_collisionValue $tagValue;
        }
    }
    else
    {
        string $sel[] = `ls -sl -l`;
        for($each in $sel)
        {
            for($cm in $collisionModes)
                if(`objExists ($each + "." + $cm)`)
                    deleteAttr ($each + "." + $cm);
        }
    }
}

proc string[] findRoots()
{
  string $transforms[] = `ls -l -typ "transform"`;
  string $roots[] = {};
  for($trans in $transforms)
    $roots[size($roots)] = rootOf($trans);
  return stringArrayRemoveDuplicates($roots);
}
// ////////////////////////////////////////////////////////////////////////////
// Determine if a mesh and its children should be kept for copying
// ////////////////////////////////////////////////////////////////////////////
proc string[] addKeptMesh(string $mesh){
    string $keepers[];
      if(`objExists ($mesh + ".ignoreInUnity")`)
        if(`getAttr ($mesh + ".ignoreInUnity")` == true)
          return $keepers;
    $keepers[size($keepers)] = $mesh;
    string $children[] = `listRelatives -c -f $mesh`;
    if(size($children) > 0)
    for($child in $children)
        $keepers = stringArrayCatenate($keepers, addKeptMesh($child));
    return $keepers;
}

// ////////////////////////////////////////////////////////////////////////////
// Get a list of textures that are assigned to a particular mesh
// ////////////////////////////////////////////////////////////////////////////
proc string[] getTexturesOnMesh(string $mesh)
{
    if(`objectType $mesh` != "mesh")
        return {};
    string $textures[];
    string $shaderGroup[] = `listSets -type 1 -o $mesh`;
    if(size($shaderGroup) > 0)
    {
        for($sg in $shaderGroup)
        {
            string $materials[] = `listConnections -d off -s on ($sg + ".surfaceShader")`;
            string $fileNodes[];
            if(`objectType $materials[0]` == "surfaceShader")
                $fileNodes = `listConnections -d off -s on ($materials[0] + ".outColor")`;
            else
            {
                $fileNodes = `listConnections -d off -s on ($materials[0] + ".color")`;
                $fileNodes = stringArrayCatenate($fileNodes, `listConnections -d off -s on ($materials[0] + ".incandescence")`);
            }
            if(size($fileNodes) > 0)
            {
                for($file in $fileNodes)
                {
                    string $path = `getAttr ($fileNodes[0] + ".fileTextureName")`;
                    if($path != "")
                        $textures[size($textures)] = $path;
                }
            }
        }
    }
    return stringArrayRemoveDuplicates($textures);
}

// ////////////////////////////////////////////////////////////////////////////
// Get a list of textures that should be copied
// ////////////////////////////////////////////////////////////////////////////
proc string[] getTexturesToCopy()
{
    string $meshes[];
    string $textures[];
    for($node in findRoots())
        $meshes = stringArrayCatenate($meshes, addKeptMesh($node));
    for($mesh in $meshes)
        $textures = stringArrayCatenate($textures, getTexturesOnMesh($mesh));
    return stringArrayRemoveDuplicates($textures);
}

// ////////////////////////////////////////////////////////////////////////////
// create export folder browser 
// ////////////////////////////////////////////////////////////////////////////
global proc ajk_createFolderBrowser ()
{
    string $myDir = "";
    string $oldDir = `workspace -q -fn`;
    $myDir = `textFieldButtonGrp -q -tx ajk_outFileControl`;
    if($myDir == "")
        $myDir =    $oldDir;
    workspace -dir $myDir;
    fileBrowserDialog -m 4 -ds 1 -fc ajk_setExportPath -an "Choose output folder:"; 
    workspace -dir $oldDir;
}

// ////////////////////////////////////////////////////////////////////////////
// set export path from export folder browser
// ////////////////////////////////////////////////////////////////////////////
global proc ajk_setExportPath (string $folder, string $type) 

    textFieldButtonGrp -e -tx ($folder + "/") ajk_outFileControl;
}

proc copyTextureFiles(string $outputFolder)
{
    print("Copying file textures to " + $outputFolder + "\n");
    string $textures[] = getTexturesToCopy();
    if(size($textures) > 0)
    {
        for($textureFile in $textures)
        {
            if(`file -q -ex $textureFile`)
            {
                string $fileName = basename($textureFile, "");
                if(!`file -q -ex $outputFolder`)
                    sysFile -md $outputFolder;
                if(`file -q -ex ($outputFolder + "/" + $fileName)`)
                    system("attrib -r " + ($outputFolder + "/" + $fileName));
                if(`sysFile -cp ($outputFolder + "/" + $fileName) ($textureFile)`)
                    print($fileName + " copied to " + $outputFolder + "\n");
                else
                    warning("Could not copy texture file: " + $textureFile + "! An error occured during copy!");
            }
            else
                warning("Could not copy texture file: " + $textureFile + "! File does not exist!");
        }
    }
}

// ////////////////////////////////////////////////////////////////////////////
// Copy scene file to output folder
// ////////////////////////////////////////////////////////////////////////////

global proc ajk_copyFile()
{

    ajk_saveSettings();
    string $outFilePath = `textFieldButtonGrp -q -text ajk_outFileControl`;
    int $copyTextures = `checkBox -q -v ajk_checkBoxCopyTextures`;
    optionVar -sv ajk_outFilePath $outFilePath;
    optionVar -iv ajk_copyTextures $copyTextures;
    
    if(`file -q -ex $outFilePath` == 0)
    {
        if(`confirmDialog -t "No Folder" -ma "left" -button "Yes" -button "No" -m ("Folder does not exist:\n" + $outFilePath + "\nCreate?") -defaultButton "Yes" -cancelButton "No" -dismissString "No"` == "Yes")
        {
            print("Creating folder: " + $outFilePath + "\n");
            sysFile -md $outFilePath;
        }
        else
            error("Cannot copy files to non-existent folder: " + $outFilePath);
    }
    if( $copyTextures == 1)
        copyTextureFiles($outFilePath + "/Textures");
    string $sceneName = `file -q -sn`;
    print($outFilePath + "/" + basename($sceneName, "") + "\n");
    file -rename ($outFilePath + "/" + basename($sceneName, ""));
    file -force -prompt 0 -ea -type "mayaBinary" -ch 1 -chn 1 -exp 1 -con 1 -sh 1;
    file -rename $sceneName;
    print("File saved to folder: " + $outFilePath + "\n");
}

// ////////////////////////////////////////////////////////////////////////////
// Save export settings to a script node in the file
// ////////////////////////////////////////////////////////////////////////////
global proc ajk_saveSettings()
{
  if(`objExists "unityExportScriptNode"` == 0)
    scriptNode -n "unityExportScriptNode" -st 0;
  int $animValue = `checkBox -q -v ajk_checkBoxAnimationOnly`;
  string $command = "if(`exists FBXExportAnimationOnly`){ FBXExportAnimationOnly " + $animValue + ";}";
  if(`objExists "unityExportScriptNode"`)
    scriptNode -e -bs $command "unityExportScriptNode";
  print("Export settings saved to file: " + `file -q -sn` + ".\n");
}

// ////////////////////////////////////////////////////////////////////////////
// main proc, UI
// ////////////////////////////////////////////////////////////////////////////
global proc ajk_unityTools()
{
    if(`window -ex window_unityTools`)
        deleteUI -window window_unityTools;
    
    string $outFilePath = `workspace -q -fn`;
    int $copyTextures = 0;
    int $collisionValue = 1;
    int $animationOnly = 0;
    if(`optionVar -ex ajk_outFilePath`)
      $outFilePath = `optionVar -q ajk_outFilePath`;
    if(`optionVar -ex ajk_copyTextures`)
      $copyTextures = `optionVar -q ajk_copyTextures`;
    if(`optionVar -ex ajk_collisionValue`)
      $collisionValue = `optionVar -q ajk_collisionValue`;
    if(`optionVar -ex ajk_animationOnly`)
      $animationOnly = `optionVar -q ajk_animationOnly`;

    window -title "Unity Tools" -tlb 1 window_unityTools;
        columnLayout -cal "center" -rowSpacing 5 -columnWidth 400 -adj true;
            frameLayout -l "Tag for Unity" -borderStyle "etchedIn" -cll 0 -cl 0 -w 400 -mw 10;
                rowColumnLayout -nc 2 -cw 1 150 -cw 2 150;
                    button -label "Ignore Selected" -c "ajk_ignoreTag(1)" -bgc 0.5 1.0 0.5;
                    button -label "Un-Ignore Selected" -c "ajk_ignoreTag(0)" -bgc 1.0 0.5 0.5;
                    radioButtonGrp -nrb 4 -la4 "Sphere" "Capsule" "Box" "Mesh" -sl $collisionValue -vr ajk_radioCollision;
                    text -l "";
                    button -label "Collision Tag Selected" -c "ajk_collisionTag(0)" -bgc 0.5 1.0 0.5;
                    button -label "Un-Collision Tag Selected" -c "ajk_collisionTag(1)" -bgc 1.0 0.5 0.5;
                setParent..;
            setParent..;
            frameLayout -l "Send to Unity" -borderStyle "etchedIn" -cll 0 -cl 0 -w 400 -mw 10;
                columnLayout -cal "left" -cat "both" 0 -rowSpacing 5 -columnWidth 360;
                    textFieldButtonGrp -text $outFilePath -label "Output Folder" -cal 1 "left" -buttonLabel "Browse" -buttonCommand ajk_createFolderBrowser -cw 1 75 -cw 2 240 -cw 3 90 ajk_outFileControl;
                    checkBox -label "Copy textures to ./Output/Textures/ Folder" -v $copyTextures ajk_checkBoxCopyTextures;
                    checkBox -label "Animation Only" -v $animationOnly ajk_checkBoxAnimationOnly;
                    button -label "Export" -align "center" -c ajk_copyFile -bgc 0.5 1.0 0.5;
                setParent ..;
            setParent ..;
        setParent..;
    setParent..;
    showWindow window_unityTools;
    window -e -width 400 -height 280 window_unityTools;
}

Back to Main

© 2003-2013 Andrew Kelts