/*
Author: Morgan J Heacock
	Date: 05/24/2005
	Date Last Revised: 05/24/2005
	Version: 1.0
	Description:	this is the sphere cube generation program, it was created to test out
			procedural coding as per the requirements of the class programing for
			the artist, morgan lost 34% of his available sanity coding this program.
					
	Known Bugs:	
			The resize procedure for adjusting sphere radius does not adjust spacing
			to compensate, I considered going through the code and adding naming
			convention to the spheres that would tell the resize procedure which relative
			position it holds and thus where its new position should be in relation to
			the spacing, but I ran out of patience and it was not required for the project
			nor do I perceive that it would be rewarded with extra credit.
			if you would like to see this added to the code then I would be pleased to do
			so if it supplied improvement to my grade.	
					
	Feature List:	
			* A list of five(5) value fields combined with sliders
			that will control five global variables.

			* A Create button that will use the five global variables
			and pass them to a procedure that generates a cube of arranged spheres
			this procedure returns the list of sphere names to string $selector[].

			* A Resize button which uses string $selector[] and float $sD in a procedure
			to set the diameter of all spheres to the new value selected by the UI elements

			* A Destroy button which uses string $selector[] in a procedure to delete
			all objects with their names stored in the array.
						
					
	Input Arguments: None
	Return Value: None
*/

int $sW;
int $sL;
int $sH;
float $sD;
float $sS;

string $selector[];

/* this is to check and see if the window exists already and to delete it incase it does
	very useful during the bug fix stage of programing becuse it gets rid of the added step
	of constantly deleting the code.
*/

	if( `window -ex cubeSUIwin` )
	{
		deleteUI cubeSUIwin;
	}

	window -t "Sphere Cube Creator"
				-mxb 0 
				-w 300 
				-h 300
				-s 1
				cubeSUIwin;
	
	columnLayout -parent "cubeSUIwin"
			-w 300
			-h 360
			-rs 10
			masterLayout;

		/* 
			I contemplated setting up loops for all of these UI element declarations
			but I decided to just hard code the information rather then handling
			the time consuming head ache of automating it
			maybe later.
		*/

		rowLayout -parent "masterLayout"
				-w 300
				-nc 3
				-cal 1 "center"
		
				swRow;
			text -parent "swRow"
				-w 100
				-al "center"
				-l "Width In Spheres"
				swTXT;
			intField -parent "swRow"
				-w 60
				-v $sW
				-cc "cubeSUIcc sw; $sW = `intField -q -v swField`;"
				swField;
			intSlider -parent "swRow"
				-w 100
				-v $sW
				-cc "cubeSUIcc sW; $sW = `intField -q -v swField`;"
				swScroll;				

		rowLayout -parent "masterLayout"
				-w 300
				-h 60
				-nc 3
				-cal 1 "center"
				slRow;
			text -parent "slRow"
				-w 100
				-al "center"
				-l "Length In Spheres"
				slTXT;
			intField -parent "slRow"
				-w 60
				-v $sL
				-cc "cubeSUIcc sl; $sL = `intField -q -v slField`;"
				slField;
			intSlider -parent "slRow"
				-w 100
				-v $sL
				-cc "cubeSUIcc sL; $sL = `intField -q -v slField`;"
				slScroll;

		rowLayout -parent "masterLayout"
				-w 300
				-h 60
				-nc 3
				-cal 1 "center"
				shRow;

			text -parent "shRow"
				-w 100
				-al "center"
				-l "Height In Spheres"
				shTXT;
			intField -parent "shRow"
				-w 60
				-v $sH
				-cc "cubeSUIcc sh; $sH = `intField -q -v shField`;"
				shField;
			intSlider -parent "shRow"
				-w 100
				-v $sH
				-cc "cubeSUIcc sH; $sH = `intField -q -v shField`;"
				shScroll;

		rowLayout -parent "masterLayout"
				-w 300
				-h 60
				-nc 3
				-cal 1 "center"
				sdRow;

			text -parent "sdRow"
				-w 100
				-al "center"
				-l "Sphere Diameter"
				sdTXT;
			floatField -parent "sdRow"
				-w 60
				-v $sD
				-cc "cubeSUIcc sd; $sD = `floatField -q -v sdField`;"
				sdField;
			floatSlider -parent "sdRow"
				-w 100
				-v $sD
				-cc "cubeSUIcc sD; $sD = `floatField -q -v sdField`;"
				sdScroll;

		rowLayout -parent "masterLayout"
				-w 300
				-h 60
				-nc 3
				-cal 1 "center"
				ssRow;

			text -parent "ssRow"
				-w 100
				-al "center"
				-l "Sphere Spacing"
				ssTXT;
			floatField -parent "ssRow"
				-w 60
				-v $sS
				-cc "cubeSUIcc ss; $sS = `floatField -q -v ssField`;"
				ssField;
			floatSlider -parent "ssRow"
				-w 100
				-v $sS
				-cc "cubeSUIcc ss; $sS = `floatField -q -v ssField`;"
				ssScroll;
		
		rowLayout -parent "masterLayout"
				-w 300
				-h 60
				-nc 3
				-cal 1 "center"
				-cw 1 100
				-cal 2 "center"
				-cw 2 100
				-cal 3 "center"
				-cw 3 100
				bRow;
			button -parent"bRow" 
				-l "CREATE"
				-h 80
				-w 100
				-al right
				-c "$selector = `sphereCube $sW $sL $sH $sD $sS` ; "
				cB;
			button -parent"bRow" 
				-l "RESIZE"
				-h 80
				-w 100
				-al right
				-c "rescaleCube $selector $sD;"
				rB;
			button -parent"bRow" 
				-l "DESTROY"
				-h 80
				-w 100
				-al right
				-c "destroyCube $selector;"
				dB;
	showWindow cubeSUIwin;				

/* 	this is where I adjust both slider and field values to match when they activate, I did this in a procedure to save on code space.
	however the variables used in this procedure are not the same as the ones called outside of it, this caused much frustration
	later on and required that I add more code to the field and slider change command flags
*/
proc cubeSUIcc(string $control)
{
	switch ($control) {
	case "sw":
		$sW = `intField -q -v swField`;
		intSlider -e -v $sW swScroll;
		break;
	case "sW":
		$sW = `intSlider -q -v swScroll`;
		intField -e -v $sW swField;
		break;
	case "sl":
		$sL = `intField -q -v slField`;
		intSlider -e -v $sL slScroll;
		break;
	case "sL":
		$sL = `intSlider -q -v slScroll`;
		intField -e -v $sL slField;
		break;
	case "sh":
		$sH = `intField -q -v shField`;
		intSlider -e -v $sH shScroll;
		break;
	case "sH":
		$sH = `intSlider -q -v shScroll`;
		intField -e -v $sH shField;
		break;
	case "sd":
		$sD = `floatField -q -v sdField`;
		floatSlider -e -v $sD sdScroll;
		break;
	case "sD":
		$sD = `floatSlider -q -v sdScroll`;
		floatField -e -v $sD sdField;
		break;
	case "ss":
		$sS = `floatField -q -v ssField`;
		floatSlider -e -v $sS ssScroll;
		break;
	case "sS":
		$sS = `floatSlider -q -v ssScroll`;
		floatField -e -v $sS ssField;
		break;
	}
}



/* the code after this is non UI elements, it is the heart and soul of this program and
should not be messed with unless you know what your doing. */

/* first up is the ValueCheck procedure, this is used to do multiple logic operators as well as print commands
for those logic operators */

proc int ValueCheck( int $sW, int $sL, int $sH, float $sD, float $sS){

	/* by default this value is set to true, it then checks if it is false */
	int $carrBool = 1;

	if($sW == 0)
		{
			print "Cannot Accept Zero as Input for 'Spheres Wide'\n";
			$carrBool = 0;
		}
	if($sL == 0)
		{
			print "Cannot Accept Zero as Input for 'Spheres Long'\n";
			$carrBool = 0;
		}
	if($sH == 0)
		{
			print "Cannot Accept Zero as Input for 'Spheres High'\n";
			$carrBool = 0;
		}
	if($sD == 0)
		{
			print "Cannot Accept Zero as Input for 'Sphere Diameter'\n";
			$carrBool = 0;
		}
	if($sS == 0)
		{
			print "Cannot Accept Zero as Input for 'Sphere Spacing'\n";
			$carrBool = 0;
		}

		return $carrBool;

		/* 	here it returns the value to the waiting if statement that will
			use it to decide to continue the procedure.
		*/

}

/* this resizes the spheres in the cube, at the moment it 
does not account for what the new positions should be */

proc rescaleCube(string $names[], float $dia)
{

	for($sphere in $names)
	{
		if($sphere == "")
		{
		
		}
		else
		{
		sphere -e -r $dia $sphere;
		}
	}
}

/* this destroys all spheres in the cube */

proc destroyCube(string $names[])
{
	for($sphere in $names)
	{
		if($sphere == "")
		{
		
		}
		else
		{
		delete $sphere;
		}	
	}
}

/* I got sick of having this extra redundant code
 cluttering all of my other procedures so I built one to isolate the math of position calculation*/

proc float posCalc(float $pos, float $sphDia, float $sphSpace,int $sphDim, int $count)
{
	float $size = (($sphDia * 2)* $sphDim) + ($sphSpace * ($sphDim - 1));
	if($count == 0)
		$pos = 0 - ($size / 2);  
	$pos = $pos + $sphDia;
	return $pos;
}

/* here is where I call a function to do one 'dimension' of the sphere grid arbitrarily I chose X
   as the place to start */

proc string[] sphereLine( float $offsetY, float $offsetZ, int $sphLong, float $sphDia, float $sphSpace)
{
	string $name[];
	int $count;
	for($count = 0; $count < $sphLong; $count++)
	{
  		string $parse[];

// here is where we call posCalc and feed the data from it into $posX.
// We call this procedure for every sphere. The math increments its position
// based on what its calculated max dimensions are and what $count step we have reached.

	float $posX = posCalc($posX, $sphDia, $sphSpace, $sphLong, $count);

	string $parse[] = `sphere -p $posX $offsetY $offsetZ -r $sphDia`;
	$name[$count] = $parse[0];
	$posX = $posX + $sphDia + $sphSpace;

	};

	return $name;
}

/* here is where I call a function to do two 'dimensions' of the sphere grid its exactly the same
	as the sphereLine procedure except it calls 'sphereLine' instead of 'sphere'and runs in the Y axis*/

proc string[] sphereWall( float $offsetZ, int $sphLong, int $sphHigh, float $sphDia, float $sphSpace){
	string $name[];
	int $count;
	for($count = 0; $count < $sphHigh; $count++)
	{ 
	string $parse[];
	float $posY = posCalc($posY, $sphDia, $sphSpace, $sphHigh, $count);
	
	$parse = sphereLine( $posY, $offsetZ, $sphLong, $sphDia, $sphSpace);
	int $pcount;
	int $tcount;
	for($pcount = 0; $pcount < $sphLong * $sphHigh; $pcount++)
		{	
			$name[$tcount]= $parse[$pcount];
			$tcount ++;
		}

	$posY = $posY + $sphDia + $sphSpace;

	};

	return $name;

}

/* here is the last one, I originaly called it sphereGrid but
	changed the name to reflect the prior naming conventions it completes the code with its
	own for-loop it calls sphereWall in this loop which intern calls sphereLine.
	This makes a cube grid very effectively, it also calls the ValueCheck procedure  */

proc string[] sphereCube( int $sphWide, int $sphLong, int $sphHigh, float $sphDia, float $sphSpace)
{
	/*
		Here is where I do a check for if any of the values are zero.
		it passes a procedure that returns 0 if it finds anything out of place
	*/
	string $name[];
	if(ValueCheck($sphWide, $sphLong, $sphHigh, $sphDia, $sphSpace))
	{
		
	for($count = 0; $count < $sphLong; $count++)
		{
			string $parse[];

			float $posZ = posCalc($posZ, $sphDia, $sphSpace, $sphWide, $count);
	
			$parse = sphereWall( $posZ, $sphHigh, $sphWide, $sphDia, $sphSpace);

			int $pcount;
			int $tcount;
			for($pcount = 0; $pcount < $sphLong * $sphHigh * $sphWide; $pcount++)
			{	
				$name[$tcount]= $parse[$pcount];
				$tcount ++;
			}
			$posZ = $posZ + $sphDia + $sphSpace;

		};

	

	}
	/*
	// this is to check if my mechanism for returning the names of the created spheres worked
	// I left it in to check and see if it has selected all of spheres during the UI phase of
	// development in case I change the code of the other procedures and need to bug fix them.
		for( $text in $name)
	{
		print( $text + "\n");
	}
	*/
	return $name;

}

    Source: geocities.com/nighzmarquls/Code

               ( geocities.com/nighzmarquls)