// Copyright (C) 1997-2004 Alias Systems Corp.
// 
// The information in this file is provided for the exclusive use of the
// licensees of Alias.  Such users have the right to use, modify,
// and incorporate this code into other products for purposes authorized
// by the Alias license agreement, without fee.
// 
// ALIAS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
// EVENT SHALL ALIAS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

//
//  Procedure Name:
//      performPolyAutoProj
//
//  Description:
//
//  Input Arguments:
//        $option : Whether to set the options to default values.
//  Return Value:
//        command string iff $option==2
//

//
// Initialize optionVars for polyAutoProj:
// 
proc setOptionVars (
	string		$prefix, 
	int			$forceFactorySettings,
	string		$vars[]
)
{
	string $varName;

	// Must match $vars
	int    $intValues[]= { 4, 1, 1, 2, 0, 1, 0 };

	for ( $i = size($vars) ; $i-- ; )
	{
		$varName = ($prefix + $vars[$i]);
		if ($forceFactorySettings || !`optionVar -exists $varName`)
			optionVar -intValue $varName $intValues[$i];
	}

	$varName = ($prefix + "eg");
	if ($forceFactorySettings || !`optionVar -exists $varName`)
		optionVar -floatValue $varName .2;

	// Also add the map name
	$varName = ($prefix + "uvSetName");
	if ($forceFactorySettings || !`optionVar -exists $varName`)
		optionVar -stringValue $varName "uvSet1";

	$varName = ($prefix + "polyGeomObject");
	if ($forceFactorySettings || !`optionVar -exists $varName`)
		optionVar -stringValue $varName "";
}

global proc performPolyAutoProjSetup(string $parent, int $forceFactorySettings)
{
	string $prefix = "polyAutoProj";
	string $intVars[] ={"p", "o", "sc", "l", "cm", "ibd", "pb"};
	string $varName;
	float  $presets[] = {.1, .2, .4, .8, 1.6, 3.2};
	int    $i;

	setOptionVars($prefix, $forceFactorySettings, $intVars);
	setParent $parent;
	
	$varName = ($prefix + $intVars[0]);
	optionMenuGrp -e -sl `optionVar -query $varName` $varName;

	$varName = ($prefix + $intVars[1]);
	radioButtonGrp -e -sl (`optionVar -query $varName`+1) $varName;

	$varName = ($prefix + $intVars[2]);
	radioButtonGrp -e -sl (`optionVar -query $varName`+1) $varName;

	$varName = ($prefix + $intVars[3]);
	optionMenuGrp -e -sl (`optionVar -query $varName`+1) $varName;

	$varName = ($prefix + "eg");
	float $fval = `optionVar -q $varName`;
	floatSliderGrp -e -v $fval $varName;

	// See if the value corresponds to one of the presets.
	$varName = ($prefix + "egPresets");
	optionMenuGrp -e -sl 1 $varName;
	for ($i = size($presets) ; $i-- ; )
	{
		if ($fval == $presets[$i])
		{
			optionMenuGrp -e -sl ($i+2) $varName;
			break;
		}
	}

	$varName = ($prefix + $intVars[4]);
	int $val = `optionVar -query $varName`;
	checkBoxGrp -e -value1 $val $varName;
	$varName = ($prefix + "uvSetName");
	textFieldGrp -e -en $val -tx `optionVar -q $varName` $varName; 

	string $blank = "";
	$varName = ($prefix + "polyGeomObject");
	textFieldGrp -e -en $val -tx $blank $varName; 

	$varName = ($prefix + $intVars[5]);
	checkBoxGrp -e -v1 `optionVar -query $varName` $varName;

	$varName = ($prefix + $intVars[6]);
	checkBoxGrp -e -v1 `optionVar -query $varName` $varName;
}

global proc performPolyAutoProjCallback (string $parent, int $doIt)
{
	string $prefix = "polyAutoProj";
	string $intVars[] ={"p", "o", "sc", "l", "cm", "ibd", "pb"};
	string $varName;

	setParent $parent;
	
	$varName = ($prefix + $intVars[0]);
	optionVar -intValue $varName `optionMenuGrp -q -sl $varName`;

	$varName = ($prefix + $intVars[1]);
	optionVar -intValue $varName (`radioButtonGrp -q -sl $varName`-1);
	
	$varName = ($prefix + $intVars[2]);
	optionVar -intValue $varName (`radioButtonGrp -q -sl $varName`-1);
	
	$varName = ($prefix + $intVars[3]);
	optionVar -intValue $varName (`optionMenuGrp -q -sl $varName`-1);
	
	$varName = ($prefix + $intVars[4]);
	optionVar -intValue $varName `checkBoxGrp -q -v1 $varName`;

	$varName = ($prefix + $intVars[5]);
	optionVar -intValue $varName `checkBoxGrp -q -v1 $varName`;

	$varName = ($prefix + $intVars[6]);
	optionVar -intValue $varName `checkBoxGrp -q -v1 $varName`;

	$varName = ($prefix + "uvSetName");
	optionVar -stringValue $varName `textFieldGrp -q -tx $varName`; 

	$varName = ($prefix + "eg");
	optionVar -floatValue $varName `floatSliderGrp -q -v $varName`;

	$varName = ($prefix + "polyGeomObject");
	optionVar -stringValue $varName `textFieldGrp -q -tx $varName`; 


	if ($doIt) 
	{
		performPolyAutoProj 0;
		addToRecentCommandQueue "performPolyAutoProj 0" "PolyAutoProj";
	}
}

global proc polyAutoSpacingPresets()
{
	int $item = `optionMenuGrp -q -sl "polyAutoProjegPresets"`-2;
	float  $presets[] = {.1, .2, .4, .8, 1.6, 3.2};

	if ($item>=0 && $item<6)
		floatSliderGrp -e -v $presets[$item] "polyAutoProjeg";
}

proc polyAutoSetupLoadButtonTemplate() {
	if (!`uiTemplate -exists LoadButtonTemplate`) {
			uiTemplate LoadButtonTemplate;
		}

	int $kOffsetText = (`about -mac` ? 8 : 5);
	int $kSingleWidgetWidthIndex = 62;
	rowLayout
		-defineTemplate LoadButtonTemplate 
		-columnAlign2  "left" "center"
		-columnAttach2 "both" "both"
		-columnOffset2 $kOffsetText 0
		-columnWidth2  170 (3 * $kSingleWidgetWidthIndex);
}

proc polyAutoProjOptions (string $prefix, string $intVars[])
{
	polyAutoSetupLoadButtonTemplate();

	string $commandName = "performPolyAutoProj";
	string $callback = ($commandName + "Callback");
	string $setup = ($commandName + "Setup");
	string $varName;

	string $layout = getOptionBox();
	setParent $layout;
	setUITemplate -pushTemplate DefaultTemplate;
	waitCursor -state 1;
	
	string $parent = `columnLayout -adjustableColumn 1`;

	$numProj = ($prefix + $intVars[0]);

	optionMenuGrp -l "Planes" $numProj;
	menuItem -l "3";
	menuItem -l "4";
	menuItem -l "5";
	menuItem -l "6";
	menuItem -l "8";
	menuItem -l "12";
	setParent -m ..;

	$varName = ($prefix + $intVars[1]);
    radioButtonGrp -l "Optimize" -nrb 2
		-l1 "Less Distortion" 
		-l2 "Fewer Pieces" $varName;

	separator;

	$varName = ($prefix + $intVars[3]);
	$gapName = ($prefix + "eg");
	$menuName = ($prefix + "egPresets");
	string $grayCmd = 
		"{ int $tmp = `optionMenuGrp -q -sl "+$varName + "` == 3;" +
		"  floatSliderGrp -e -en $tmp "+$gapName+";" +
		"  optionMenuGrp -e -en $tmp "+$menuName+";}";

	optionMenuGrp -l "Layout" -cc $grayCmd $varName;
	menuItem -l "Overlap";
	menuItem -l "Along U";
	menuItem -l "Into Square";
	menuItem -l "Tile";
	setParent -m ..;

	$varName = ($prefix + $intVars[2]);
    radioButtonGrp -l "Scale Mode" -nrb 3
		-l1 "None"
	    -l2 "Uniform"
		-l3 "Stretch to Square" $varName;

	separator;

	$buttonCheckBox = ($prefix + "buttonCheckBox");
	$projButtonName = ($prefix + "loadProjButton");
	$textName = ($prefix + "polyGeomObject");
	$varName = ($prefix + $intVars[6]);
	string $grayCmd = 
		"{ int $tmp = `checkBoxGrp -q -v1 "+ $buttonCheckBox + "`;" +
		"  if ($tmp == 0) textFieldGrp -e -text \"\" "+$textName+";" +
		"  optionMenuGrp -e -en (!$tmp) "+$numProj+";" +
		"  textFieldGrp -e -en $tmp "+$textName+";" +
		"  checkBoxGrp -e -en $tmp "+$varName+";" +
		"  button -e -en $tmp "+$projButtonName+";}";
    checkBoxGrp -label1 "Load Projection" -cc $grayCmd $buttonCheckBox;
	textFieldGrp -label "Projection Object: " $textName;
	checkBoxGrp -l1 "Project Both Directions" $varName;

	checkBoxGrp -e -v1 0 $buttonCheckBox;

	string $getPolyGeomObject = 
		"{ string $totalSel[] = `ls -sl`; " +
		"  textFieldGrp -e -text $totalSel[0] "+$textName+";}";

	setUITemplate -pushTemplate LoadButtonTemplate;
	rowLayout -numberOfColumns 2;
		text -label "";
		button -align "center" -label "Load Selected" -command $getPolyGeomObject $projButtonName;
	setParent ..;
	setUITemplate -popTemplate;

	eval $grayCmd;

	separator;

	optionMenuGrp -l "Spacing Presets" -cc polyAutoSpacingPresets $menuName;
	menuItem -l " Custom";
	menuItem -l "1024 Map";
	menuItem -l " 512 Map";
	menuItem -l " 256 Map";
	menuItem -l " 128 Map";
	menuItem -l "  64 Map";
	menuItem -l "  32 Map";
	setParent -m ..;

	string $cmd = ("optionMenuGrp -e -sl 1 " + $menuName);
    floatSliderGrp -l "Percentage Space" -min 0 -max 5 -cc $cmd $gapName;

	separator;

	$varName = ($prefix + $intVars[5]);
	checkBoxGrp -l1 "Insert Before Deformers" $varName;

    $varName = ($prefix + $intVars[4]);
	$textName = ($prefix + "uvSetName");
	string $grayCmd = 
		"{ int $tmp = `checkBoxGrp -q -v1 "+$varName + "`;" +
		"  textFieldGrp -e -en $tmp "+$textName+";}";
    checkBoxGrp -label1 "Create New UV Set" -cc $grayCmd $varName;
	textFieldGrp -label "UV Set Name: " $textName;

	waitCursor -state 0;
	setUITemplate -popTemplate;

	string $applyBtn = getOptionBoxApplyBtn();
	button -edit -label "Project"
	       -command ($callback + " " + $parent + " " + 1) $applyBtn;
	string $saveBtn = getOptionBoxSaveBtn();
	button -edit 
		-command ($callback + " " + $parent + " " + 0 + "; hideOptionBox")
		$saveBtn;
	string $resetBtn = getOptionBoxResetBtn();
	button -edit 
		-command ($setup + " " + $parent + " " + 1) $resetBtn;

	setOptionBoxTitle("Polygon Automatic Mapping Options");

	setOptionBoxHelpTag( "AutomaticMapping" );

	eval (($setup + " " + $parent + " " + 0));

	showOptionBox();
}

proc string createCurrentShader ()
{
	global string $polyTextureColorShader;
	string $shader;
	string $shaderType="lambert";
	string $textureName="checker";
	if (`optionVar -q polyCreateShaderWithMapping` == 0) 
		return "";
	string $shader=`evalEcho "sets -n texturedFacets -em -r true -nss true"`;
	if ($shader != "") {
		evalEcho ("partition -e -addSet renderPartition " + $shader);
		string $shad[];
		if ($polyTextureColorShader != "")
			$shad=`ls -showType $polyTextureColorShader`;
		if ($polyTextureColorShader == "" || size($shad) == 0) {
			string $texture[]=`ls -showType defaultPolygonTexture`;
			if (size($texture) == 0)
				$texture[0]=`evalEcho ("shadingNode -asTexture " 
						+ $textureName + " -n defaultPolygonTexture")`;
			$polyTextureColorShader=`evalEcho ("shadingNode -asShader " 
						+ $shaderType + " -n defaultPolygonShader")`;
			evalEcho ("connectAttr " + $texture[0] + ".outColor " 
					+ $polyTextureColorShader + ".color");
			// creating a node selects it: we don't want that...
			select -d $texture[0] $polyTextureColorShader;
		}
		$shad=`ls -showType $polyTextureColorShader`;
		if ($polyTextureColorShader != "" && size($shad) != 0)
			evalEcho("connectAttr -f " + $polyTextureColorShader + ".outColor "
					 + $shader + ".surfaceShader");
		else warning "Could not create the default polygons shader";
	} else warning "Could not create a new set to hold the faces.";
	return $shader;
}

global proc string[] rearrangeSelection(string $totalSelected[])
{
	string $beforeDot[];
	string $resultantSelection[];

	for( $i = 0; $i < size($totalSelected); $i++ )
	{
		string $buffer[];
		tokenize($totalSelected[$i], ".", $buffer);

		int $index = -1;
		for( $j = 0; $j < size($beforeDot); $j++ )
		{
			if($beforeDot[$j] == $buffer[0])
			{
				$index = $j;
				break;
			}
		}

		if($index == -1)
		{
			$beforeDot[size($beforeDot)] = $buffer[0];
			$resultantSelection[size($resultantSelection)] = $totalSelected[$i];
		}
		else
		{
			$resultantSelection[$index] = $resultantSelection[$index] + " " + ($totalSelected[$i]);
		}
	}

	return $resultantSelection;
}

global proc string performPolyAutoProj (int $option)
{
	string $prefix = "polyAutoProj";
	string $intVars[] ={"p", "o", "sc", "l", "cm", "ibd", "pb"};
	string $cmd="";

	switch ($option) 
	{
		case 0:
		string $varName;
		int $ival;
		setOptionVars($prefix, false, $intVars);
		$cmd = "polyAutoProjection";
		for ( $i = size($intVars) ; $i-- > 1; )
		{
			$varName = ($prefix + $intVars[$i]);
			$ival = `optionVar -query $varName`;
			$cmd = $cmd + " -" + $intVars[$i] + " " + $ival;
		}

		$varName = ($prefix + $intVars[0]);
		$ival = `optionVar -query $varName`;
		int $numVal[] = {3, 4, 5, 6, 8, 12};
		$cmd = $cmd + " -" + $intVars[0] + " " + $numVal[$ival-1];

		$varName = ($prefix + $intVars[4]);
		int $createNewUVSet = `optionVar -query $varName`;
		if ($createNewUVSet)
		{
			$varName = ($prefix + "uvSetName");
			string $sval = `optionVar -query $varName`;
			if ($sval != "")
				$cmd = $cmd + " -uvSetName " + $sval;
		}

		$varName = ($prefix + "eg");
		float $fval = `optionVar -query $varName`;
		$cmd = $cmd + " -ps " + $fval;

		// Set world space to true for Auto Projection
		$cmd = $cmd + " -ws 1";


		string $totalSelected[] = `ls -sl`;
		string $selectList[] = `filterExpand -ex false -sm 34`;

		if(size($selectList) == 0)
		{
			string $expSel[] = polyCheckSelection ("polyAutoProjection", "f");
			$totalSelected = `filterExpand -ex false -sm 34`;
		}

		string $resultantSelection[] = rearrangeSelection($totalSelected);		

		string $resultingProjObject[];
		string $oldCmd = $cmd;

		int $i;
		for( $i = 0; $i < size($resultantSelection); $i++ )
		{
			$cmd = $oldCmd;
			$cmd = $cmd + " " + $resultantSelection[$i];
			string $resultingProjObjectArray[];
			$resultingProjObjectArray = `evalEcho $cmd`;
			
			$resultingProjObject[size($resultingProjObject)] = $resultingProjObjectArray[0];
		}

		string $totalSel[] = `ls -sl`;
        
        // Set current UV set
        if($createNewUVSet) {
        	string $filteredSel[];
        	$filteredSel=`filterExpand -ex false -sm 34 $totalSel`;
        	string $setCurrent = "polyUVSet -luv";
        	int $i;
        	for($i = 0; $i < size($filteredSel); $i++) {
        		$setCurrent += (" " + $filteredSel[$i]);
        	}
        	evalEcho $setCurrent;
        }
        
        string $shader=`createCurrentShader`;
		// Update shader's set.
		if( $shader != "") {
			string $filteredSel[];
	        	$filteredSel=`filterExpand -ex false -sm 34 $totalSel`;
			$cmd=("sets -e -fe " + $shader);
			int $i;
			for($i=0; $i < size($filteredSel); $i++)
				$cmd=($cmd + " " + $filteredSel[$i]);
			evalEcho $cmd;
		}
		
		// Set selection
		evalEcho `select -r $totalSel`;

		// Get the object for projection if it exists.
		$varName = ($prefix + "polyGeomObject");
		string $geomObject = `optionVar -query $varName`;
		
		// If the user did not want a polyGeomObject then $geomObject
		// will equal "".
		// If they did, $geomObject is the actual object. We need to
		// get the shape, and then connect the $shape to the
		// projection's polyGeomObject attribute.  This is done using
		// connectAttr -f $shape.outMesh
		// $resultingProjObject.polyGeomObject

		if ($geomObject != "") {
			string $allRelatives[] = `listRelatives -s $geomObject`;
			string $geomObjectShape = $allRelatives[0];

			string $attrOutMesh = $geomObjectShape + ".outMesh";

			for($i = 0; $i < size($resultantSelection); $i ++)
			{
				string $attrPolyGeomObject = $resultingProjObject[$i] + ".polyGeomObject";
				connectAttr -f $attrOutMesh $attrPolyGeomObject;
			}
		}

		// Now force the optionVar for polyGeomObject back to null so
		// it doesn't try to apply the same projection object if we
		// want to do another autoProjection.
		//
		$varName = ($prefix + "polyGeomObject");
		optionVar -stringValue $varName "";

		// Now we want to center the manip. Get the bounding box for
		// the object and then re-position the pivot location of the
		// manip for the Auto Projection.
		//
		// exactWorldBoundingBox returns 6 floats: xmin, ymin, zmin,
		// xmax, ymax, zmax.
		//

		float $boundingBox[] = `exactWorldBoundingBox $totalSelected`;
		float $manipX = ($boundingBox[0] + $boundingBox[3])/2.0;
		float $manipY = ($boundingBox[1] + $boundingBox[4])/2.0;
		float $manipZ = ($boundingBox[2] + $boundingBox[5])/2.0;
	
		// Now we want to set the scale for the projection as well.
		// The scaleX, scaleY and scaleZ attributes will all be set to
		// the same value. This is the max(x,y,z) where x,y,z = the
		// length of the x,y,z components of the bounding box.
		//

		float $xDist = abs($boundingBox[3] - $boundingBox[0]);
		float $yDist = abs($boundingBox[4] - $boundingBox[1]);
		float $zDist = abs($boundingBox[5] - $boundingBox[2]);

		float $scale = max(max($xDist, $yDist), $zDist);    

		for($i = 0; $i < size($resultantSelection); $i ++)
		{
			setAttr ($resultingProjObject[$i] + ".pivotX") $manipX;
			setAttr ($resultingProjObject[$i] + ".pivotY") $manipY;
			setAttr ($resultingProjObject[$i] + ".pivotZ") $manipZ;

			setAttr ($resultingProjObject[$i] + ".translateX") $manipX;
			setAttr ($resultingProjObject[$i] + ".translateY") $manipY;
			setAttr ($resultingProjObject[$i] + ".translateZ") $manipZ;

			setAttr ($resultingProjObject[$i] + ".scaleX") $scale;
			setAttr ($resultingProjObject[$i] + ".scaleY") $scale;
			setAttr ($resultingProjObject[$i] + ".scaleZ") $scale;

		// Show manip
			evalEcho `select -add $resultingProjObject[$i]`;
			setToolTo ShowManips;
		}

		break;

		case 1:
			polyAutoProjOptions($prefix, $intVars);
			break;
		case 2:
			$cmd="performPolyAutoProj 0";
			break;
	}
	return $cmd;
}
