// 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.

// 
// 
// ALIAS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
// EVENT SHALL ALIAS BE LIABLE FOR ANY SPECIAL, INDIRECT OR

//  Alias Script File
//  MODIFY THIS AT YOUR OWN RISK
//
//  Creation Date:  November 20, 1996
//
//  Description:
//      This script contains common menu definition routines shared
//	between the graph editor and the dope sheet.
//
//		A call to the proc 'loadAnimMenuLibrary' will make sure that
//	all the other helper procs defined in here are loaded and available
//
//	Procs defined within this script:
//
//	defineEditMenu (string $editor, string $animEditor, string $parentMenu, string $buildMenuCommand)
//		Define the elements of the Edit subMenu
//
//	defineListMenu (string $editor, string $animEditor, string $parentMenu)
//		Define the elements of the Options subMenu
//
//	defineTangentsMenu (string $editor, string $animEditor, string $parentMenu)
//		Define the elements of the Tangents subMenu
//
//  Input Arguments:
//      None.
//
//  Return Value:
//      None.
//

global string $gEditorList[];
global string $gDefaultConnection[];

global proc performEulerFilter(string $selectionConnection) 
{
	string $objs[] = `findAnimCurves $selectionConnection`;
	int $nObjs = size($objs);
	int $i = 0;
	string $cmd = "filterCurve ";
	for ($i = 0; $i < $nObjs ; $i++) {
		$cmd += (" " + $objs[$i]);
	}

	if ($nObjs > 0) {
		evalEcho ($cmd);
	}
}

global proc performRotationInterpolation( string $mode, string $selectionConnection ) 
{
	// Query the curves which are selected in the graph editor viewport
	// and append the selected names to a rotationInterpolation command
	// string.
	//
	string $viewportSel[];
	if ( `isTrue SomethingSelected` != 0 ) {
		catch( $viewportSel = `keyframe -an keys -query -name` );
	}
	string $cmd = "rotationInterpolation -c " + $mode;
	int $i;
	int $viewportCount = size( $viewportSel );
	for ( $i = 0; $i < $viewportCount; $i++ ) {
	 	$cmd += (" " + $viewportSel[$i]);
	}

	// Query the curves which are selected in the graph editor outliner
	// and append the selected names to the command string.
	//
	string $outlinerSel[] = `selectionConnection -q -object $selectionConnection`;
	int $outlinerCount = size( $outlinerSel );
	for ( $i = 0; $i < $outlinerCount; $i++ ) {
	 	$cmd += (" " + $outlinerSel[$i]);
	}

	// If any curves were selected, execute the command string which we
	// built up.
	//
	if ( $viewportCount + $outlinerCount > 0 ) {
		evalEcho( $cmd );
	}
}

proc int
findEditorEntry (string $editor)
//
//	Procedure Name:
//		findEditorEntry
//
//	Description:
//		Helper method to find the index entry of a registered editor
//
//  Input Arguments:
//		string $editor			The name of the editor that is registered
//
//  Return Value:
//      int the index entry in $editorList (-1 if it is not registered)
//
{
	global string $gEditorList[];
	int $length = size ($gEditorList);
	for ($i = 0; $i < $length; $i++) {
		if ($gEditorList[$i] == $editor) {
			return ($i);
		}
	}
	return (-1);
}

global proc string
getDefaultConnection (string $editor)
//
//	Procedure Name:
//		getDefaultConnection
//
//	Description:
//		Helper method to find the name of the default selection connection
//	for a registered editor
//
//  Input Arguments:
//		string $editor			The name of the editor that is registered
//
//  Return Value:
//      string the name of the default selection connection, "animationList"
//	if the editor is not registered
//
{
	global string $gDefaultConnection[];

	int $entry = findEditorEntry ($editor);
	if ($entry == -1) {
		return ("animationList");
	}
	return ($gDefaultConnection[$entry]);
}

global proc
registerEditor (string $editor, string $defaultConnection)
//
//	Procedure Name:
//		registerEditor
//
//	Description:
//		Helper method to register the name of the default selection connection
//	for this editor
//
//  Input Arguments:
//		string $editor			The name of the editor that is being registered
//		string $defaultConnection	The name of the default selection connection
//
//  Return Value:
//      None.
//
{
	global string $gEditorList[];
	global string $gDefaultConnection[];

	int $entry = findEditorEntry ($editor);
	if ($entry == -1) {
		int $length = size ($gEditorList);
		$gEditorList[$length] = $editor;
		$gDefaultConnection[$length] = $defaultConnection;
	}
}

global proc
buildAnimEditMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand)
//
//	Procedure Name:
//		buildAnimEditMenu
//
//	Description:
//		This actually builds the edit subMenu if necessary
//
//  Input Arguments:
//		string $editor			The name of the editor that this submenu
//								is being attached to
//		string $animEditor		The name of the animation editor that this submenu
//								is being attached to
//		string $parentMenu		The name of the parent menu that this
//								submenu is being attached to
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//		string $buildMenuCommand
//								An optional command to be called when
//								this menu is built.  The command will
//								be called with $editor $parentMenu
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;
	if (`menu -query -numberOfItems $parentMenu` != 0) {
		return;
	}

	// Check for the bufferCurve option
	//
	int $performBase = 0;
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$performBase = 3;
	}

	// The dimWhen's below allow the Undo and Redo menu items to dim themselves
	// as approriate.  However the main undo menu items no longer do this
	// because Irix cannot handle roll over help on dimmed items, so this block
	// is commented out for now
	//
	menuItem -label "Undo"
		-annotation "Undo: Undo the last action"
		-command "undo"
		animUndoItem;
//	dimWhen -false "UndoAvailable" animUndoItem;
	menuItem -label "Redo"
		-annotation "Redo: Redo the last undone action"		
		-command "redo"
		animRedoItem;
//	dimWhen -false "RedoAvailable" animRedoItem;

	menuItem -divider true;

	string $selectionConnection = `editor -query -selectionConnection $editor`;
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$selectionConnection = $animEditor;
	}

	menuItem -label "Cut"
		-annotation "Cut: Select object or curve segment"
		-command ("performCutKeyArgList 1 {\"" + $performBase + "\", \"" + $selectionConnection + "\", \"1\"}") 
		-dragMenuCommand( "performCutKeyArgList 1 {\"" + ($performBase + 2) + "\", \"" + $selectionConnection + "\", \"1\"}")
		cutItem;
	menuItem -optionBox true 
		-label "Cut Option Box"
		-command ("performCutKeyArgList 1 {\"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"1\"}" ) 
		cutKeyDialogItem;
	menuItem -label "Copy"
		-annotation "Copy: Select object or curve segment"		
		-command ("performCopyKeyArgList 1 {\"" + $performBase + "\", \"" + $selectionConnection + "\", \"1\"}") 
		-dragMenuCommand( "performCopyKeyArgList 1 {\"" + ($performBase + 2) + "\", \"" + $selectionConnection + "\", \"1\"}")
		copyItem;
	menuItem -optionBox true 
		-label "Copy Option Box"
		-command ("performCopyKeyArgList 1 {\"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"1\"}" )
		copyKeyDialogItem;
	menuItem -label "Paste"
		-annotation "Paste: Select object or curve segment"
		-command ("performPasteKeyArgList 1 {\"" + $performBase + "\", \"" + $selectionConnection + "\", \"1\"}")
		-dragMenuCommand( "performPasteKeyArgList 1 {\"" + ($performBase + 2) + "\", \"" + $selectionConnection + "\", \"1\"}")
		pasteItem;
	menuItem -optionBox true 
		-label "Paste Option Box"
		-command ("performPasteKeyArgList 1 {\"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"1\"}")
		pasteKeyDialogItem;
	menuItem -label "Delete"
		-annotation "Delete: Select key(s)"
		-command ("performClearKeyArgList 1 {\"" + $performBase + "\", \"" + $selectionConnection + "\", \"0\", \"1\"}")
		-dragMenuCommand( "performClearKeyArgList 1 {\"" + ($performBase + 2) + "\", \"" + $selectionConnection + ", \"0\", \"1\"}")
		clearItem;
	menuItem -optionBox true 
		-label "Delete Option Box"
		-command ("performClearKeyArgList 1 {\"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"0\", \"1\"}")
		clearKeyDialogItem;
	menuItem -label "Scale"
		-annotation "Scale: Select keys"		
		-command ("performScaleKeyArgList 1 {\"" + $performBase + "\", \"" + $selectionConnection + "\", \"1\"}" )
		-dragMenuCommand( "performScaleKeyArgList 1 {\"" + ($performBase + 2) + "\", \"" + $selectionConnection + "\", \"1\"}")
		scaleItem;
	menuItem -optionBox true 
		-label "Scale Option Box"
		-command ("performScaleKeyArgList 1 {\"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"1\"}")
		scaleKeyDialogItem;

	menuItem -l "Transformation Tools" -sm true -to true -aob true transAnimItem;
	menuItem -label "Move Keys Tool"
		-annotation (getRunTimeCommandAnnotation("MoveTool"))
		-image "move_M.xpm"
		-command "MoveTool"
		-dragDoubleClickCommand "MoveToolOptions";

	menuItem -optionBox true
		-label "Move Keys Tool Option Box"
		-annotation (getRunTimeCommandAnnotation("MoveToolOptions"))
		-image "move_M.xpm" 
		-command "MoveToolOptions"
			;

	menuItem 
		-label "Scale Keys Tool" 
		-annotation (getRunTimeCommandAnnotation("ScaleTool"))
		-image "scale_M.xpm"
		-command "ScaleTool"
		-dragDoubleClickCommand "ScaleToolOptions"
		;
	menuItem -optionBox true
		-label "Scale Keys Tool Option Box"
		-annotation (getRunTimeCommandAnnotation("ScaleToolOptions"))
		-image "scale_M.xpm" 
		-command "ScaleToolOptions"
			;
	int $enableLattice = ($options != "noOptions");
	menuItem -label "Lattice Deform Keys Tool"
		-enable $enableLattice
		-image "latticeDeformKeySmall.xpm"
		-command "setToolTo latticeDeformKeySuperContext";

	menuItem -optionBox true
		-enable $enableLattice
		-label "Lattice Deform Keys Tool Option Box"
		-image "latticeDeformKeySmall.xpm"
		-command "setToolTo latticeDeformKeySuperContext";
	setParent -m ..;

	menuItem -divider true;

	menuItem -label "Snap"
		-annotation "Snap: Select object or key(s)"		
		-command ("performSnapKeyArgList 1 { \"" + $performBase + "\", \"" + $selectionConnection + "\", \"1\" }" )
		-dragMenuCommand( "performSnapKeyArgList 1 { \"" + ($performBase + 2) + "\", \"" + $selectionConnection + "\", \"1\" }" )
		snapItem;
	menuItem -optionBox true 
		-label "Snap Option Box"
		-command ("performSnapKeyArgList 1 { \"" + ($performBase + 1) + "\", \"" + $selectionConnection + "\", \"1\" }")
		snapKeyDialogItem;

	menuItem -label "Select Unsnapped"
		-annotation "Select Unsnapped: Select nothing or select a curve"
		-command ("performSnapKeyArgList 1 { \"6\", \"" + $selectionConnection + "\", \"1\" } " )
		-dragMenuCommand( "performSnapKeyArgList 1 { \"7\", \"" + $selectionConnection + "\", \"1\" } " )
		selectUnsnappedItem;

	if ($buildMenuCommand != "") {
		eval (($buildMenuCommand + " " + $animEditor + " " + $parentMenu));
	}
}

global proc
defineEditMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand)
//
//	Procedure Name:
//		defineEditMenu
//
//	Description:
//		This creates the submenu for edit functionality
//
//	Example:
//		Create a menu that this submenu is to be attached to
//	(make sure that the menu is defined to allow option boxes)
//
//		menuItem -label "Edit"
//			-allowOptionBoxes true
//			-subMenu true
//			editHierItem;
//			defineEditMenu $editor "editHierItem" "optionalBuildMenuCommand"; 
//		setParent -menu ..;
//
//  Input Arguments:
//		string $editor			The name of the editor that this submenu
//								is being attached to
//		string $parentMenu		The name of the parent menu that this
//								submenu is being attached to
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//		string $buildMenuCommand
//								An optional command to be called when
//								this menu is built.  The command will
//								be called with $editor $parentMenu
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;

	menu -edit
		-postMenuCommand ("buildAnimEditMenu " + $editor + " " + $animEditor + " " + $parentMenu + "\"" + $options + "\"" + " " + "\"" + $buildMenuCommand + "\"")
		$parentMenu;

	// This section will allow the undo item to display what is going to
	// be undone.  This is the fix for bug 55712.  However the main undo
	// menu items no longer show this, so this block is commented out for
	// now
	//
//mm	menu -edit
//mm		-postMenuCommand ("handleEditMenuCmd " + $parentMenu)
//mm		$parentMenu;

}

global proc
handleEditMenuCmd (string $parentMenu)
//
//  Procedure Name:
//      handleEditMenuCmd
//
//  Description:
//		This proc is a -postMenuCommand callback which sets the state of
//	menu items in the Edit menu.
//
//  Input Arguments:
//      None.
//
//  Return Value:
//      None.
//
{
	string $undoName;
	string $buffer[];
	
	setParent -menu $parentMenu;

	$undoName = `undoInfo -query -undoName`;
	tokenize ($undoName, $buffer);
	$undoName = ("Undo " + $buffer[0]);
	menuItem -edit -label $undoName animUndoItem;

	$undoName = `undoInfo -query -redoName`;
	tokenize ($undoName, $buffer);
	$undoName = ("Redo " + $buffer[0]);
	menuItem -edit -label $undoName animRedoItem;
}

global proc int
isAutoLoad (string $editor)
{
	// First, find out what is connected to this editor
	//
	string $mainListConnection = `editor -query -mainListConnection $editor`;

	// If it is NOT the active list, then check it off
	//
	string $defaultConnection = getDefaultConnection ($editor);
	if(( $mainListConnection != "activeList" ) 
	&& ( $mainListConnection != $defaultConnection )) 
	{
		return (0);
	}
	else if (`selectionConnection -query -lock $mainListConnection`) {
		return (0);
	}
	return (1);
}

global proc
toggleAutoLoad (string $editor, int $toggle)
//
//  Procedure Name:
//      toggleAutoLoad
//
//  Description:
//		This proc is a helper to toggle the auto load state
//		of the outliner.
//
//  Input Arguments:
//      None.
//
//  Return Value:
//      None.
//
{
	// First, find out what is connected to this editor
	//
	string $mainListConnection = `editor -query -mainListConnection $editor`;
	// If it is NOT the active list, then force it to use the active list
	//
	string $defaultConnection = getDefaultConnection ($editor);
	if (($mainListConnection != "activeList") && ($mainListConnection != $defaultConnection)) {
		editor -edit -unlockMainConnection $editor;
		editor -edit -mainListConnection $defaultConnection $editor;
	}
	else if ($toggle) {
		editor -edit -unlockMainConnection $editor;
	}
	else {
		editor -edit -lockMainConnection $editor;
	}

	// The best way to resolve the button name is to pass in the full
	// path to the button, however toggleAutoLoad is called from several
	// places (including some c++ code) and this makes it difficult.
	// So instead we will use a carefully constructed name for the
	// button
	//
	if (`iconTextCheckBox -exists ($editor + "loadToggleButton")`) {
		iconTextCheckBox -edit
			-value `isAutoLoad $editor`
			($editor + "loadToggleButton");
	}

	if (`iconTextButton -exists ($editor + "reloadButton")`) {
		iconTextButton -edit
			-enable (!`isAutoLoad $editor`)
			($editor + "reloadButton");
	}
}

global proc
doReload (string $editor)
//
//  Procedure Name:
//      doReload
//
//  Description:
//		This proc is a helper to have the outliner do a reload.
//
//  Input Arguments:
//      None.
//
//  Return Value:
//      None.
//
{
	// First, find out what is connected to this editor
	//
	string $mainListConnection = `editor -query -mainListConnection $editor`;
	// If it is NOT the active list, then force it to use the active list
	//
	string $defaultConnection = getDefaultConnection ($editor);
	if (($mainListConnection != "activeList") && ($mainListConnection != $defaultConnection)) {
//		editor -edit -unlockMainConnection $editor;
//		editor -edit -mainListConnection $defaultConnection $editor;
//		editor -edit -lockMainConnection $editor;
		editor -edit -forceMainConnection $defaultConnection $editor;
	}
	// Otherwise switch the lock on the list off and on
	//
	else if (`selectionConnection -query -lock $mainListConnection`) {
//		editor -edit -unlockMainConnection $editor;
//		editor -edit -mainListConnection $defaultConnection $editor;
//		editor -edit -lockMainConnection $editor;
		editor -edit -forceMainConnection $defaultConnection $editor;
	}
}

global proc
handleListMenuCmd (string $options, string $editor, string $animEditor, string $parentMenu, string $buildMenuCommand)
//
//  Procedure Name:
//      handleListMenuCmd
//
//  Description:
//		This proc is a -postMenuCommand callback which sets the state of
//	menu items in the List menu.
//
//  Input Arguments:
//		string $options			Options for this menu
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "noScroll otherOption")
//
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				useHier			Add a "Hierarchy Below" entry
//				useCharacters	Add support for characters
//
//  Return Value:
//      None.
//
{
	// Set the proper check state of the AutoLoad menu
	//
	setParent -menu $parentMenu;

	string $objects = "Objects";
	string $bookmarkType = "bookmarkAnimCurves";
	string $toggleLoadCmd = ("toggleAutoLoad " + $editor + " #1");
	int $autoLoad = 1;
	string $editorName = "Graph Editor";
	if (match ("useCharacters", $options) == "useCharacters") {
		$objects = "Characters";
		$bookmarkType = "bookmarkClips";
		$toggleLoadCmd += ("; optionVar -intValue traxAutoLoadSel #1");
		$editorName = "Trax Editor";
		if (`optionVar -exists traxAutoLoadSel`) {
			$autoLoad = `optionVar -q traxAutoLoadSel`;
		}
	}
	
	if (`menu -query -numberOfItems $parentMenu` == 0) {
		if (match ("useHier", $options) == "useHier") {
			menuItem -label "Hierarchy Below"
				-checkBox false
				-command ("setHierarchyBelow #1 " + $animEditor)
				hierItem;
		}
		menuItem -label ("Auto Load Selected " + $objects)
			-checkBox $autoLoad
			-annotation ("Auto Load Curves for selected objects into the "+$editorName)
			-command $toggleLoadCmd
			autoLoadItem;
		menuItem -label ("Load Selected " + $objects)
			-annotation ("Load Curves for selected objects into the "+$editorName)
			-command ("doReload " + $editor)
			reloadItem;
		menuItem -label ("Add Selected " + $objects)
			-annotation ("Add Curves for selected objects into the "+$editorName)
			-command ("addSelectedToEditorWithOptions \"" + $options + "\" " + $editor)
			addToListItem;

		string $menuItem = `menuItem -label "Bookmarks"
			-subMenu true -aob true
			bookMarkHierItem`;
		menuItem -edit
			-postMenuCommand ("buildBookmarkMenu -type " + $bookmarkType + " -editor " + $editor + " " + $menuItem)
			$menuItem;
			menuItem 
				-label ("Bookmark Current " + $objects)
				-annotation "Bookmark Current Objects: Select curves"
				-command ("createBookmark " + $editor + " " + $bookmarkType + " false") 
				bookAnimMarkObjectsItem;
				menuItem -optionBox true
					-label "Bookmark Current Objects Option Box"
					-command ("createBookmark " + $editor + " " + $bookmarkType + " true")
					bookAnimMarkObjectsDialog;
//			menuItem 
//				-label "Remove Current Bookmark"
//				-annotation "Remove Current Bookmark: Choose a Bookmark"
//				-command ("createBookmark " + $editor + " " + $bookmarkType + " false") 
//				removeCurrentBookmarkItem;
			menuItem 
				-label "Remove All Bookmarks"
				-annotation "Remove All Bookmarks"
				-command ("removeBookmark {} " + $bookmarkType) 
				removeAllBookmarksItem;
//		menuItem 
//			-label "Bookmark Current Curves..." 
//			-command ("createBookmark " + $editor + " " + $bookmarkType) 
//			bookAnimMarkCurvesItem;
			setParent -menu ..;

		if ($buildMenuCommand != "") {
			eval (($buildMenuCommand + " " + $editor + " " + $animEditor + " " + $parentMenu));
		}
	}

	if (match ("useHier", $options) == "useHier") {
		menuItem -edit
			-checkBox `dopeSheetEditor -query -hierarchyBelow $animEditor`
			hierItem;
	}

	// First, find out what is connected to this editor
	//
	string $mainListConnection = `editor -query -mainListConnection $editor`;
	if ($mainListConnection == "") {
		if (`modelEditor -exists $editor`) {
			$mainListConnection = "activeList";
		}
	}

	// If it is NOT the active list, then check it off
	//
	string $defaultConnection = getDefaultConnection ($editor);
	if(( $mainListConnection != "activeList") 
    && ( $mainListConnection != $defaultConnection )) 
	{
		menuItem -edit -checkBox off autoLoadItem;
		menuItem -edit -enable true reloadItem;
		menuItem -edit -enable true addToListItem;
	}
	else if (`selectionConnection -query -lock $mainListConnection`) {
		menuItem -edit -checkBox off autoLoadItem;
		menuItem -edit -enable true reloadItem;
		menuItem -edit -enable true addToListItem;
	}
	else {
		menuItem -edit -checkBox on autoLoadItem;
		menuItem -edit -enable false reloadItem;
		menuItem -edit -enable false addToListItem;
	}
}

global proc
defineListMenu (string $options, string $editor, string $animEditor,
				string $parentMenu, string $buildMenuCommand)
//
//	Procedure Name:
//		defineListMenu
//
//	Description:
//		This creates the submenu for list functionality
//
//	Example:
//		Create a menu that this submenu is to be attached to
//	(make sure that the menu is defined to allow option boxes)
//
//		menuItem -label "List"
//			-allowOptionBoxes true
//			-subMenu true
//			optionsHierItem;
//			defineListMenu $editor $animEditor "optionsHierItem"; 
//			{further menu items could be defined here}
//		setParent -m ..;
//
//  Input Arguments:
//		string $editor			The name of the editor that this submenu
//								is being attached to
//		string $parentMenu		The name of the parent menu that this
//								submenu is being attached to
//		string $options			Options for this menu
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "noScroll otherOption")
//
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				useHier			Add a "Hierarchy Below" entry
//				useCharacters	Add support for characters
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;
	menu -edit
		-postMenuCommand ("handleListMenuCmd " + $options + " " + $editor + " " + $animEditor + " " + $parentMenu + "\"" + $buildMenuCommand + "\"")
		$parentMenu;
}

global proc
doKeyTangent (string $commandOptions, string $selectionConnection, string $options)
//
//  Procedure Name:
//      doKeyTangent
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		keyTangent command, depending upon whether or not keys are active.
//
//  Input Arguments:
//		string $commandOptions			Options to be passed to the keyTangent
//										command
//		string $selectionConnection		The name of the selection connection
//										that contains potential objects to
//										perform the keyTangent command upon
//		string $options					Options for this proc
//										Option words are specified within the
//										the string, with each option seperated
//										by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions				A nice "do nothing" string to pass
//				bufferCurve				Issue commands to (possibly) create buffer curves
//
//  Return Value:
//      None.
//
{
	// Build up the command string
	//
	string $command = ("keyTangent " + $commandOptions);

	string $realConnection = $selectionConnection;

	// Check for the bufferCurve option
	//
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$realConnection = `editor -query -mainListConnection $selectionConnection`;
		// Check to see if we need to create buffer curves
		//
		if (`animCurveEditor -query -showBufferCurves $selectionConnection` == "on") {
			$command = "bufferCurve -animation \"keys\" -overwrite false; " + $command;
		}
	}

	// Check to see if any keys are selected
	//
	int $keys = 0;
	if (!`isTrue SomethingSelected`
	||	catch ($keys = `keyframe -animation keys -query -keyframeCount`)) {
		$keys = 0;
	}
	if ($keys == 0) {
		// No keys, so use the selection connection
		//
		$command = ($command + " -animation objects " + $realConnection);
	}
	// Now issue the command
	//
	evalEcho ($command);
}

global proc
doKeyEdit (string $commandOptions, string $selectionConnection, string $options)
//
//  Procedure Name:
//      doKeyEdit
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		keyframe command, depending upon whether or not keys are active.
//
//  Input Arguments:
//		string $commandOptions			Options to be passed to the keyTangent
//										command
//		string $selectionConnection		The name of the selection connection
//										that contains potential objects to
//										perform the keyTangent command upon
//		string $options				Options for this proc
//										Option words are specified within the
//										the string, with each option seperated
//										by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions				A nice "do nothing" string to pass
//				bufferCurve				Issue commands to (possibly) create buffer curves
//				addInbetween			Create options to add an inbetween at the current time
//				removeInbetween			Create options to remove an inbetween at the current time
//
//  Return Value:
//      None.
//
{
	// Build up the command string
	//
	string $command = ("keyframe " + $commandOptions);

	int $checkKeys = true;
	// Check for the inbetweens
	//
	if (match ("addInbetween", $options) == "addInbetween") {
		$command = $command + " -time \"" + `currentTime -query` + ":\" " +
			"-relative -timeChange 1 -option over";
		$checkKeys = false;
	}
	else if (match ("removeInbetween", $options) == "removeInbetween") {
		$command = $command + " -time \"" + `currentTime -query` + ":\" " +
			"-relative -timeChange -1 -option over";
		$checkKeys = false;
	}

	string $realConnection = $selectionConnection;

	// Check for the bufferCurve option
	//
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$realConnection = `editor -query -mainListConnection $selectionConnection`;
		// Check to see if we need to create buffer curves
		//
		if (`animCurveEditor -query -showBufferCurves $selectionConnection` == "on") {
			$command = "bufferCurve -animation \"keys\" -overwrite false; " + $command;
		}
	}

	// Check to see if any keys are selected
	//
	int $keys = 0;
	if ($checkKeys && (!`isTrue SomethingSelected`
	||	catch ($keys = `keyframe -animation keys -query -keyframeCount`))) {
		$keys = 0;
	}
	if ($keys == 0) {
		// No keys, so use the selection connection
		//
		$command = ($command + " -animation objects " + $realConnection);
	}
	// Now issue the command
	//
	evalEcho ($command);
}


global proc
int looksLikeAttr(string $nodeAttr)
//
//  Procedure Name:
//      looksLikeAttr
//
//  Description:
//      A convenience method to test if nodeAttr represents an attribute
//  written in the node.Attr format.
{
	int $result = 0;
	string $tokens[];
	tokenize($nodeAttr,".",$tokens);
	if(size($tokens) > 1) 
	{
		$result = 1;
	}
	return $result;
}


proc string getAnimAttr(string $selectedItem)
//
//  Procedure Name:
//      getAnimAttr
//
//  Description:
//		This is a helper proc to get proper attribute from animCurve node
//
{
	if(looksLikeAttr($selectedItem))
		return $selectedItem;

	string $attr = $selectedItem;
	string $connectedNodes[] = `listConnections -source false $selectedItem`;

	if (size($connectedNodes) > 0) {
		string $objectType = `objectType $connectedNodes[0]`;

		switch ($objectType){

			// Simple Anim
			case "transform":
				$connectedNodes = `listConnections -source false -plugs true $selectedItem`;
				$attr = $connectedNodes[0];
				break;

				// Simple and Muted
			case "mute":
				$connectedNodes = `listConnections -source false -type transform -plugs true $connectedNodes[0]`;
				$attr = $connectedNodes[0];
				break;

				// The attribute belongs to a character
			case "character":
				string $characterNode = $connectedNodes[0];
				$connectedNodes = `listConnections -source false -plugs true $selectedItem`;
				int $mindex = `character -q -memberIndex $connectedNodes[0]`;
				string $sattr = $characterNode + ".dnSetMembers[" + $mindex + "]";
				$connectedNodes = `listConnections -destination false -plugs true $sattr`;
				$attr = $connectedNodes[0];
				break;

				// The attribute belongs to a character and instanced to a clip
			case "clipLibrary":
				// Get character node
				$connectedNodes = `listConnections -destination false -type character $connectedNodes[0]`;
				string $characterNode =  $connectedNodes[0];

				// Get character member index
				$connectedNodes = `listConnections -source false -plugs true $selectedItem`;
				string $strs[];
				tokenize($connectedNodes[0], ".", $strs);
				int $ssize = size($strs[2]);
				// clipEval index
				string $cindex = substring($strs[2], 10, $ssize-1);
				string $sattr = $characterNode + ".dnSetMembers[" + $cindex + "]";

				$connectedNodes = `listConnections -destination false -plugs true $sattr`;
				$attr = $connectedNodes[0];

				break;
			default:
				$connectedNodes = `listConnections -source false -plugs true $selectedItem`;
				$attr = $connectedNodes[0];
		}
	}

	return $attr;
}

global proc
int isChannelFromClip(string $channel)
{
	int $result = 0;
	string $buffer[];
	tokenize($channel,".",$buffer);
	if (nodeType($buffer[0]) == "clipLibrary") {
		$result = 1;
	}
	return $result;
}


global proc
doMuteChannel (string $selectionConnection, string $flag)
//
//  Procedure Name:
//     doMuteChannel 
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		mute command, depending upon whether or not channels are selected

{
	string $command;
	int $result = 0;    

	string $membersArray[] = `keyframe -query -sl -name`;

	if (size($membersArray) == 0)
	{
		$membersArray = expandSelectionConnectionAsArray($selectionConnection);
	}

	if ($flag == "-true") {
		for ($m in $membersArray)
		{	
			// don't mute mute
			if (match("mute", $m) == ""){

				$mm = getAnimAttr($m);
				if ($mm != "") {
					$mm = $m;
				}

				string $muted[] = `mute  $mm`;
				for ($mute in $muted) {
					//if we get a mute channel set the first and last keys to be on
					$result = 1;
					// set the begin and end keys.
					int   $lastkey = `keyframe -q -kc $m` - 1;
					float $start[] = `keyframe -index 0 -q -tc $m`;
					float $end[] = `keyframe -index $lastkey -q -tc $m`;
					$command = "cutKey -index \"0:" + $lastkey + "\" "+ $muted[0];
					eval($command);
					float $playstart = `playbackOptions -q -min`;
					float $playend   = `playbackOptions -q -max`;

					setKeyframe -t  $playstart -v 1 $mute ;
					setKeyframe -t  $playend -v 1 $mute ;

				}

			}
		}
	}
	else 
	{

		for ($m in $membersArray)
		{

			if (match("mute", $m) == ""){
				//get the mute channel
				string $chan = getAnimAttr($m);
				string $chans[] = `listConnections -type mute $chan`;

				for ($c in $chans) {
					if ($c != "")
					{
						// get the keys of the mute channel
						int $keys = `keyframe -q -kc $chan`;
						//remove all the keys
						$command = "cutKey -index \"0:" + $keys + "\" "+ $c;
						eval($command);

						$m = getAnimAttr($m);
						mute -disable $m;
						$result = 1; 
					}
				}
			}
		}
	}   

	if ($result == 0)
	{
		string $errMsg;
		if ($flag == "-true") {
			$errMsg = ("No channel has been found that can be muted.");
		}
		else {
			$errMsg = ("No channel has been found that can be unmuted.");
		}
		error($errMsg);
	}
}

global proc
doMuteRegion(string $channel, string $flag, float $start, float $end)
//
//  Procedure Name:
//     doMuteRegion
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		mute command, depending upon which keys are selected

{

	int $value;
	int $result = 0;

	if ($flag == "-true") 
		$value = 1;
	else
		$value = 0;

	string $chan = getAnimAttr($channel);
	if ($chan == "") {
		$chan = $channel;
	}
	

	// skip mute channels. Don't want to mute mute channels
	if (match("mute", $chan) == "")
	{
		// create a mute channel or get it if it exits.
		string $muted[] = `mute $chan`;    

		for ($mute in $muted) {
			//test to see if this mute channel has keys

			float $mkeys[] = `keyframe -q -tc $mute`;

			float $endvalue[] = `keyframe -absolute -time ($end -1) -q -eval ($mute + ".mute")`;

			// We don't have any values keyed yet
			if (size($mkeys)!= 0) {
				string $range = "\"" + $start + ":" + $end + "\"";
				string $cmd = ("cutKey -t "+ $range +" -option keys " + $mute + ".mute");
				eval($cmd);
			}

			int $inverse = (1 - $value );
			float $playstart = `playbackOptions -q -min`;
			float $playend   = `playbackOptions -q -max`;

			int  $nbkeys = `keyframe -q -kc ($mute + ".mute")`;
			if ($nbkeys == 0) {
				// set the begin and end keys.
				setKeyframe -t $playstart -v 0 $mute;
				setKeyframe -t $playend -v 0 $mute;
			}

			// Move just abit along the curve (in case there is a key right on the
			// spot and get the reading
			float $keyvalue[] = `keyframe -absolute -time ($start +.001) -q -eval ($mute + ".mute")`;

			// Since the number is float it could be edited away from
			// 0 and 1 value.  Let it round to the neareast value.  This
			// matches up with stipple drawing in the graph editor and 
			// other places.
			if ($endvalue[0] > 0.5){
				$endvalue[0] = 1.0; 
			}
			else {
				$endvalue[0] = 0.0;
			}
			if ($keyvalue[0] > 0.5){
				$keyvalue[0] = 1.0; 
			}
			else {
				$keyvalue[0] = 0.0;
			}

			// Check if we need to add a new starting key.
			if ($keyvalue[0] != $value) {
				setKeyframe -t $start -v $value $mute;
				if ($endvalue[0] != $value) {
					// We want to mute the selected ticks but not the
					// effect the key at the end value. So move it back almost
					// a full key. This is currently composented for in the 
					// drawing routine.
					setKeyframe -t $end -v $inverse $mute;
				}
			}
			// Check if we need to an ending key
			else if ($keyvalue[0] != $endvalue[0] ) {
				setKeyframe -t $end -v $inverse $mute;
			}

		}
	}
}

global proc
doMuteKey (string $flag)
//
//  Procedure Name:
//      doMuteKey
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		mute command, depending upon which keys are selected

{
    string $curves[] = `keyframe -query -sl -name`;
    string $c;
    int $value;
    int $result = 0;
    
    if ($flag == "-true") 
        $value = 1;
    else
        $value = 0;
    
    for( $c in $curves ) {
        // skip mute channels. Don't want to mute mute channels
        if (match("mute", $c) == ""){
            
			string $chan = getAnimAttr($c);
            // create a mute channel or get it if it exits.
            string $muted[] = `mute $chan`;    
            
            //test to see if this mute channel has keys
            float $mkeys[] = `keyframe -q -tc $muted[0]`;
            int   $lastkey = `keyframe -q -kc $c` - 1;
            
            if (size($mkeys) == 0)
            {
                int $inverse = (1 - $value );
                
                // set the begin and end keys.             
                float $start[] = `keyframe -index 0 -q -tc $c`;
                float $end[] = `keyframe -index $lastkey -q -tc $c`;
                setKeyframe -t $start[0] -v 0 $muted[0] ;
                setKeyframe -t $end[0] -v 0 $muted[0] ;                        
            }
            
            // get the time of the keys
            int $keys[] = `keyframe -sl -q -iv $c`;
            int $index, $i;
			int $lastkey = `keyframe -q -kc $c`;
            for ($i = 0; $i < size($keys); ++$i ){
                // set the key and mark it dirty to get let the 
                // graph editor pick up it.
				$index = $keys[$i];
				float $t[] = `keyframe -index $index -q $c`;
                setKeyframe -t ($t[0] - 0.0001) -v $value $muted[0] ;
				$result = 1; 
				
				// if the next is not selected 
				if ($value == 1)
				{
					if ( ($i < (size($keys) - 1) && $keys[$i + 1] != ($index + 1) )
						|| ( $i == (size($keys) - 1) &&  $index != $lastkey) ) 
					{
						float $tt[] = `keyframe -index ($index + 1) -q $c`;
						// test to see if the key is already off.
						float $va[] = `keyframe -t $tt[0] -q -eval $muted[0]`;
						if ($va[0] > 0.0)
							setKeyframe -t $tt[0] -v 0 $muted[0] ;
					}	
				}
			}
        }
    }
    
    if ($result == 0)
    {
    	string $errMsg;
    	if (size($curves) == 0) {
			$errMsg = ("No object selected to set mute keys on.");
    	}
    	else {
			$errMsg = ("Unable to set mute keys on selected object(s).");
    	}
		error($errMsg);    
    }
}




global proc
doSetInfinity (string $commandOptions, string $selectionConnection, string $options)
//
//  Procedure Name:
//      doSetInfinity
//
//  Description:
//		This is a helper proc which will issue the proper form of the
//		setInfinity command, depending upon whether or not keys are active.
//
//  Input Arguments:
//		string $commandOptions			Options to be passed to the setInfinity
//										command
//		string $selectionConnection		The name of the selection connection
//										that contains potential objects to
//										perform the setInfinity command upon
//		string $options					Options for this proc
//										Option words are specified within the
//										the string, with each option seperated
//										by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions				A nice "do nothing" string to pass
//				bufferCurve				Issue commands to (possibly) create buffer curves
//
//  Return Value:
//      None.
//
{
	// Build up the command string
	//
	string $command = ("setInfinity " + $commandOptions);

	string $realConnection = $selectionConnection;

	// Check for the bufferCurve option
	//
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$realConnection = `editor -query -mainListConnection $selectionConnection`;
		// Check to see if we need to create buffer curves
		//
		if (`animCurveEditor -query -showBufferCurves $selectionConnection` == "on") {
			$command = "bufferCurve -animation \"keys\" -overwrite false; " + $command;
		}
	}

	// Check to see if any keys are selected
	//
	int $keys = 0;
	if (!`isTrue SomethingSelected`
	||	catch ($keys = `keyframe -animation keys -query -keyframeCount`)) {
		$keys = 0;
	}
	if ($keys == 0) {
		// No keys, so use the selection connection
		//
		$command = ($command + " " + $realConnection);
	}
	// Now issue the command
	//
	evalEcho ($command);
}

global proc
buildTangentsMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand) 
//
//  Procedure Name:
//      buildGraphEdTangentsMenu
//
//  Description:
//		Creates the menu entries that control
//		tangent settings in the graph editor.
//
//  Input Arguments:
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;
	if (`menu -query -numberOfItems $parentMenu` != 0) {
		return;
	}

	string $selectionConnection = `editor -query -selectionConnection $editor`;

	// Check for the bufferCurve option
	//
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$selectionConnection = $animEditor;
	}

	menuItem -label "Spline"
		-annotation "Spline Tangents: Select key(s)"
		-command ("doKeyTangent \"-e -itt spline -ott spline\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Linear"
		-annotation "Linear Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -itt linear -ott linear\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Clamped"
		-annotation "Clamped Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -itt clamped -ott clamped\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Stepped"
		-annotation "Stepped Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -ott step\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Stepped Next"
		-annotation "Stepped Next Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -ott stepnext\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Flat"
		-annotation "Flat Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -itt flat -ott flat\" " + $selectionConnection + " " + "\"" + $options + "\"");
//	menuItem -label "Fast" -c "keyTangent -e -itt fast -ott fast" fastItem;
//	menuItem -label "Slow" -c "keyTangent -e -itt slow -ott slow" slowItem;
	menuItem -label "Fixed"
		-annotation "Fixed Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -itt fixed -ott fixed\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Plateau"
		-annotation "Plateau Tangents: Select key(s)"		
		-command ("doKeyTangent \"-e -itt plateau -ott plateau\" " + $selectionConnection + " " + "\"" + $options + "\"");

	menuItem -divider true;

	menuItem -label "In Tangent" -subMenu true -to true inTanHierItem;
		menuItem -label "Spline"
			-annotation "Spline In Tangents: Select key(s)"			
			-command ("doKeyTangent \"-e -itt spline\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Linear"
			-annotation "Linear In Tangents: Select key(s)"						
			-command ("doKeyTangent \"-e -itt linear\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Clamped"
			-annotation "Clamped In Tangents: Select key(s)"			
			-command ("doKeyTangent \"-e -itt clamped\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Flat"
			-annotation "Flat In Tangents: Select key(s)"						
			-command ("doKeyTangent \"-e -itt flat\" " + $selectionConnection + " " + "\"" + $options + "\"");
			
//
//	The next two are commented out for now - don't work properly
//	yet, as the pre/post tangents are not being modified
//
//		menuItem -label "Fast" -c "keyTangent -e -itt fast";
//		menuItem -label "Slow" -c "keyTangent -e -itt slow";
		menuItem -label "Fixed"
			-annotation "Fixed In Tangents: Select key(s)"
			-command ("doKeyTangent \"-e -itt fixed\" " + $selectionConnection + " " + "\"" + $options + "\"");

		menuItem -label "Plateau"
			-annotation "Plateau In Tangents: Select key(s)"						
			-command ("doKeyTangent \"-e -itt plateau\" " + $selectionConnection + " " + "\"" + $options + "\"");
			
	setParent -m ..;

	menuItem -label "Out Tangent" -subMenu true -to true outTanHierItem;
		menuItem -label "Spline"
			-annotation "Spline Out Tangents: Select key(s)"
			-command ("doKeyTangent \"-e -ott spline\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Linear"
			-annotation "Linear Out Tangents: Select key(s)"						
			-command ("doKeyTangent \"-e -ott linear\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Clamped"
			-annotation "Clamped Out Tangents: Select key(s)"
			-command ("doKeyTangent \"-e -ott clamped\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Flat"
			-annotation "Flat Out Tangents: Select key(s)"			
			-command ("doKeyTangent \"-e -ott flat\" " + $selectionConnection + " " + "\"" + $options + "\"");
//
//	The next two are commented out for now - don't work properly
//	yet, as the pre/post tangents are not being modified
//
//		menuItem -label "Fast" -c "keyTangent -e -ott fast";
//		menuItem -label "Slow" -c "keyTangent -e -ott slow";
		menuItem -label "Fixed"
			-annotation "Fixed Tangents: Select key(s)"			
			-command ("doKeyTangent \"-e -ott fixed\" " + $selectionConnection + " " + "\"" + $options + "\"");

		menuItem -label "Plateau"
			-annotation "Plateau Out Tangents: Select key(s)"			
			-command ("doKeyTangent \"-e -ott plateau\" " + $selectionConnection + " " + "\"" + $options + "\"");
	setParent -m ..;

	if ($buildMenuCommand != "") {
		eval (($buildMenuCommand + " " + $editor + " " + $animEditor + " " + $parentMenu));
	}
}

global proc
defineTangentsMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand)
//
//	Procedure Name:
//		defineTangentsMenu
//
//	Description:
//		This creates the submenu for tangent setting functionality
//
//	Example:
//		Create a menu that this submenu is to be attached to
//
//		menuItem -label "Tangents"
//			-allowOptionBoxes false
//			-subMenu true
//			tangentsHierItem;
//			defineTangentsMenu $editor $animEditor "tangentsHierItem"; 
//			{further menu items could be defined here}
//		setParent -m ..;
//
//  Input Arguments:
//		string $editor			The name of the editor that this submenu
//								is being attached to
//		string $parentMenu		The name of the parent menu that this
//								submenu is being attached to
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//
//  Return Value:
//      None.
//
{

	setParent -menu $parentMenu;
	menu -edit
		-postMenuCommand ("buildTangentsMenu " + $editor + " " + $animEditor + " " + $parentMenu + "\"" + $options + "\"" + " " + "\"" + $buildMenuCommand + "\"")
		$parentMenu;

}

global proc doNormalizeCurvesMenuItemAction (int $normalize, string $animEditor)
{
	normalizeCurves($animEditor);
}

global proc
buildCurvesMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand) 
//
//  Procedure Name:
//      buildCurvesMenu
//
//  Description:
//		Creates the menu entries that control
//		curve editing within an animation editor.
//
//  Input Arguments:
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//				useSmoothness	Add a "Curve Smoothness" entry
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;
	if (`menu -query -numberOfItems $parentMenu` != 0) {
		// Update radio button checks for curve smoothness
		//
		if (match ("useSmoothness", $options) == "useSmoothness") {
			string $curveSmoothness = `animCurveEditor -query -smoothness $animEditor`;
			menuItem -edit
				-radioButton ($curveSmoothness == "coarse")
				coarseCurveItem;
			menuItem -edit
				-radioButton ($curveSmoothness == "rough")
				roughCurveItem;
			menuItem -edit
				-radioButton ($curveSmoothness == "medium")
				mediumCurveItem;
			menuItem -edit
				-radioButton ($curveSmoothness == "fine")
				fineCurveItem;
		}

		return;
	}

	string $selectionConnection = `editor -query -selectionConnection $editor`;
	string $realSelectionConnection = $selectionConnection;

	// Check for the bufferCurve option
	//
	int $performBase = 0;
	if (match ("bufferCurve", $options) == "bufferCurve") {
		$selectionConnection = $animEditor;
		$performBase = 3;
	}

	menuItem -label "Pre Infinity" -subMenu true -to true preInfinityHierItem;
		menuItem -label "Cycle"
			-annotation "Cycle: Select curve to cycle before its first key"
			-command ("doSetInfinity \"-pri cycle\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Cycle with Offset"
			-annotation "Cycle with offset: Select curve to cycle with offset before its first key"
			-command ("doSetInfinity \"-pri cycleRelative\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Oscillate"
			-annotation "Oscillate: Select curve to make it oscillate before its first key"
			-command ("doSetInfinity \"-pri oscillate\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Linear"
			-annotation "Linear: Select curve to make it linear before its first key"
			-command ("doSetInfinity \"-pri linear\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Constant"
			-annotation "Constant: Select curve to make it constant before its first key"			
			-command ("doSetInfinity \"-pri constant\" " + $selectionConnection + " " + "\"" + $options + "\"");
	setParent -m ..; 

	menuItem -label "Post Infinity" -subMenu true -to true postInfinityHierItem;
		menuItem -label "Cycle"
			-annotation "Cycle: Select curve to cycle before its last key"
			-command ("doSetInfinity \"-poi cycle\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Cycle with Offset"
			-annotation "Cycle with offset: Select curve to cycle with offset before its last key"
			-command ("doSetInfinity \"-poi cycleRelative\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Oscillate"
			-annotation "Oscillate: Select curve to make it oscillate before its last key"
			-command ("doSetInfinity \"-poi oscillate\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Linear"
			-annotation "Linear: Select curve to make it linear before its last key"			
			-command ("doSetInfinity \"-poi linear\" " + $selectionConnection + " " + "\"" + $options + "\"");
		menuItem -label "Constant"
			-annotation "Constant: Select curve to make it constant before its last key"			
			-command ("doSetInfinity \"-poi constant\" " + $selectionConnection + " " + "\"" + $options + "\"");
	setParent -m ..; 

	menuItem -divider true;

	if (match ("useSmoothness", $options) == "useSmoothness") {
		menuItem -label "Curve Smoothness" -subMenu true -tearOff true curveSmoothHierItem;
			//	Create a collection to keep the rb's in proper
			//	sync (IE: only one on at any one time. )
			//
			radioMenuItemCollection;
			menuItem -label "Coarse"
				-radioButton true
				-annotation "Coarse: Draw all curves at the coarsest resolution"
				-command ("animCurveEditor -edit -smoothness coarse " + $animEditor) coarseCurveItem;
			menuItem -label "Rough"
				-radioButton false
				-annotation "Rough: Draw all curves at the rough resolution"
				-command ("animCurveEditor -edit -smoothness rough " + $animEditor) roughCurveItem;
			menuItem -label "Medium"
				-radioButton false
				-annotation "Medium: Draw all curves at medium resolution"
				-command ("animCurveEditor -edit -smoothness medium " + $animEditor) mediumCurveItem;
			menuItem -label "Fine"
				-radioButton false
				-annotation "Fine: Draw all curves at the highest resolution"
				-command ("animCurveEditor -edit -smoothness fine " + $animEditor) fineCurveItem;
		setParent -m ..;
	}

	menuItem -label "Bake Channel"
		-annotation "Bake Channel: Select a curve"
		-c ("performBakeResults " + $performBase + " " + $selectionConnection) 
		-dragMenuCommand( "performBakeResults " + ($performBase + 2) + " \"" + 
						  $selectionConnection + "\"")
		bakeResultsItem;
		menuItem -optionBox true 
		-label "Bake Channel Option Box"
		-c ("performBakeResults " + ($performBase + 1) + " " + $selectionConnection) bakeResultsOptionsItem;

	menuItem -label "Mute Channel"
		-annotation "Mute Channel: Select a channel"
        -command ("doMuteChannel "+ $realSelectionConnection + " -true")
		muteChannelItem;
	menuItem -label "Unmute Channel"
		-annotation "Unmute Channel: Select a channel"
        -command ("doMuteChannel "+ $realSelectionConnection + " -false")
        unmuteChannelItem;
        
	if (match ("dopeSheet", $selectionConnection) == "") {
		menuItem -label "Normalize Curves"
			-annotation "Normalize curves in the Graph Editor"
			-command ("normalizeCurves " + $animEditor)
			normalizeCurvesMenuItem;

		menuItem -label "Denormalize Curves"
			-annotation "Denormalize curves in the Graph Editor"
			-command ("denormalizeCurves " + $animEditor + " true")
			denormalizeCurvesMenuItem;
	}

	menuItem -divider true;

	menuItem -label "Change Rotation Interp" -subMenu true -tearOff true rotationInterpolationHierItem;
		//
		//	These are not radio buttons because we cannot show the type
		//	of the current selection: there could be many curves currently
		//	selected.
		//
		menuItem -label "Independent Euler"
			-annotation "Independent Euler: Select a rotation curve"
				-c ("performRotationInterpolation none " + $realSelectionConnection);
		menuItem -label "Synchronized Euler"
			-annotation "Synchronized Euler: Select a rotation curve"
				-c ("performRotationInterpolation euler " + $realSelectionConnection);
		menuItem -label "Synchronized Quaternion"
			-annotation "Synchronized Quaternion: Select a rotation curve"
				-c ("performRotationInterpolation quaternion " + $realSelectionConnection);
	setParent -m ..;
	
	menuItem -label "Simplify Curve"
		-annotation "Simplify Curve: Select a curve"
		-c ("performSimplify " + $performBase + " " + $selectionConnection) 
		-dragMenuCommand( "performSimplify " + ($performBase + 2) + " \"" + 
						  $selectionConnection + "\"")
		simplifyItem;
	menuItem -optionBox true 
		-label "Simplify Curve Option Box"
		-c ("performSimplify " + ($performBase + 1) + " " + $selectionConnection) 
		simplifyOptionsItem;

	menuItem -label "Euler Filter"
		-annotation "Euler Filter: Select a curve"		
		-c ("performEulerFilter " + $realSelectionConnection)
		eulerFilterItem;

	menuItem -label "Resample Curve"
		-annotation "Resample Curve: Select a curve"				
		-c ("performResample " + $performBase + " " + $selectionConnection)
		-dragMenuCommand( "performResample " + ($performBase + 2) + " \"" +
						   $selectionConnection + "\"")
		resampleItem;
	menuItem -optionBox true
		-label "Resample Curve Option Box"
		-c ("performResample " + ($performBase + 1) + " " + $selectionConnection)
		resampleOptionsItem;

	menuItem -label "Spreadsheet..."
		-annotation "Open the Animation Spreadsheet."
		-command ("OpenAnimSpreadsheet " + $realSelectionConnection)
		spreadSheetItem;

	// Check for the bufferCurve option
	//
	if (match ("bufferCurve", $options) == "bufferCurve") {
		menuItem -label "Buffer Curve Snapshot"
			-annotation "Buffer Curve Shapshot: Select a curve"
			-command "bufferCurve -animation \"keys\" -overwrite true"
			bufferSnapItem;
		menuItem -label "Swap Buffer Curve"
			-annotation "Swap Buffer Curve: Select a curve"			
			-command "bufferCurve -animation \"keys\" -swap"
			bufferSwapItem;
	}

	menuItem -divider true;

	menuItem -label "Non-weighted Tangents"
		-annotation "Non-weighted Tangents: Select key(s)"
		-command ("doKeyTangent \"-edit -weightedTangents false\" " + $selectionConnection + " " + "\"" + $options + "\"");
	menuItem -label "Weighted Tangents"
		-annotation "Weighted Tangents: Select key(s)"		
		-command ("doKeyTangent \"-edit -weightedTangents true\" " + $selectionConnection + " " + "\"" + $options + "\"");

	if ($buildMenuCommand != "") {
		eval (($buildMenuCommand + " " + $editor + " " + $animEditor + " " + $parentMenu));
	}
}

global proc
defineCurvesMenu (string $editor, string $animEditor, string $parentMenu, string $options, string $buildMenuCommand)
//
//	Procedure Name:
//		defineCurvesMenu
//
//	Description:
//		This creates the submenu for curve editing functionality
//
//	Example:
//		Create a menu that this submenu is to be attached to
//
//		menuItem -label "Curves"
//			-allowOptionBoxes false
//			-subMenu true
//			curvesHierItem;
//			defineCurvesMenu $editor $animEditor "curvesHierItem"; 
//			{further menu items could be defined here}
//		setParent -m ..;
//
//  Input Arguments:
//		string $editor			The name of the editor that this submenu
//								is being attached to
//		string $parentMenu		The name of the parent menu that this
//								submenu is being attached to
//		string $options			Options for this proc
//								Option words are specified within the
//								the string, with each option seperated
//								by a space (e.g. "bufferCurve otherOption")
//			Current options:
//				noOptions		A nice "do nothing" string to pass
//				bufferCurve		Issue commands to (possibly) create buffer curves
//
//  Return Value:
//      None.
//
{
	setParent -menu $parentMenu;
	menu -edit
		-postMenuCommand ("buildCurvesMenu " + $editor + " " + $animEditor + " " + $parentMenu + "\"" + $options + "\"" + " " + "\"" + $buildMenuCommand + "\"")
		$parentMenu;
}

global proc string[]
findAnimCurves (string $selectionConnection)
//
//	Procedure Name:
//		findAnimCurves
//
//	Description:
//		This is a helper proc which will find a list of animCurves
//	that are connected to the objects within the specified selection
//	connection
//
//  Input Arguments:
//		string $selectionConnection
//								The name of the selection connection
//
//  Return Value:
//      string[] a list of animCurves
//
{
	string $animCurves[];
	int $numCurves = 0;

	// Make sure we have a valid selection connection
	//
	if ($selectionConnection == "") {
		return ($animCurves);
	}
	if (!`selectionConnection -query -exists $selectionConnection`) {
		return ($animCurves);
	}

	// Get the list of objects within the selection connection
	//
	string $objectList[] = `selectionConnection -query -object $selectionConnection`;
	if (size ($objectList) == 0) {
		return ($animCurves);
	}

	// Find all the animCurves within the object list
	//
	for ($object in $objectList) {
		if (`isAnimCurve $object` != 1) {
			continue;
		}
		$animCurves[$numCurves] = $object;
		$numCurves++;
	}

	// Now find everything that is connected to the objects in the
	// object list, and see if they are animCurves
	//
	string $connectList[];
	if (!catch ($connectList = `listConnections -skipConversionNodes true -source true -destination false $objectList`)) {
		for ($connection in $connectList) {
			if (`isAnimCurve $connection` != 1) {
				continue;
			}
			$animCurves[$numCurves] = $connection;
			$numCurves++;
		}
	}

	return ($animCurves);
}

global proc
OpenAnimSpreadsheet (string $selectionConnection)
//
//	Procedure Name:
//		OpenAnimSpreadsheet
//
//	Description:
//		This is a helper proc to open the attribute editor for
//		a selected curve (or the first curve if more than one
//		is selected)
//
//  Input Arguments:
//      None.
//
//  Return Value:
//      None.
//
{
	string $animCurves[];

	if (`isTrue SomethingSelected` != 0) {
		catch ($animCurves = `keyframe -an keys -query -name`);
	}
	if (size ($animCurves) == 0) {
		$animCurves = `findAnimCurves $selectionConnection`;
	}

	if (size ($animCurves) > 0) {
		showEditor $animCurves[0];
	}
	else {
		warning ("No keys selected. Please select the animation curve for which you want to view the spreadsheet.");
	}
}

global proc
loadAnimMenuLibrary ()
{
}
