Avguard Extensions - Version 2.08

Change notes:
v2.00	- replaceControllerInstances replaced with replaceInstances.
		- getMouseMode() and getMouseButtonStates() will go away soon. Use
		- mouse.mode and mouse.buttonStates instead.
v2.01	- added amin() and amax()
		- changed #SCALE to #NUSCALE for toolmode.commandmode to match value used for setToolBtnState method
		- added eulerToQuat() and quatToEuler()
		- redefined trackview.pickTrackDlg() with corrected version - handles paramblock picks correctly
		- moved local_euler_XYZ and euler_XYZ controller access out of this extension and into avg_ctrl.dlx
		- added toolmode.axisConstraints
		- added getToolbtnState()
		- added updateMTLInMedit()
		- added getMaterialID()
		- added WSMSupportsForce() and WSMSupportsCollision()
		- added WSMApplyFC() - work in progress, syntax may change
		- added ik.getIsTerminator(), ik.setIsTerminator(), ik.getBindPos(), ik.setBindPos(), ik.getBindOrient(), 
		  ik.setBindOrient()
		- added meshop.getEdgesUsingVert(), meshop.getFacesUsingVert(), meshop.getPolysUsingVert(), 
		  meshop.getVertsUsingEdge(), meshop.getFacesUsingEdge(), meshop.getPolysUsingEdge(), 
		  meshop.getVertsUsingFace(), meshop.getEdgesUsingFace(), meshop.getPolysUsingFace(),
		  meshop.getEdgesReverseEdge()
		- added getPointControllers(), getPointController()
		- addded meshop.attach(), meshop.getVertWeight(), meshop.setVertWeight(), meshop.getVertsByColor(),
		  meshop.weldVerts(), meshop.autoSmooth(), meshop.unifyNormals(), meshop.flipNormals(),
		  meshop.autoEdge()
		- added isStructDef(), isStruct(), isController()
		- fixed snapshotAsMesh() to always return the mesh in world coordinates. 
v2.02	- VAF (yet another fix) to snapshotAsMesh() to handle object offset transform correctly, got
		  rid of memory leak
		- fix to meshop.attach
		- added MultiListBox UI element
		- added meshop.deleteIsoMapVerts
		- added units structure variables and methods to get/set MAX units settings
		- fixed up all meshop methods to take as an argument a node, editable mesh baseobject, or triMesh
		- added meshop.getUIParam() and meshop.setUIParam()
		- added isSelectionFrozen(), freezeSelection(), thawSelection()
		- added getBitmapOpenFileName(), getBitmapSaveFileName()
		- added doesFileExist()
v2.03	- added meshop.setNumMaps(), meshop.getNumMaps(), meshop.setMapSupport(), meshop.getMapSupport(),
		  meshop.setNumMapVerts(), meshop.getNumMapVerts(), meshop.setNumMapFaces(), meshop.getNumMapFaces(),
		  meshop.setMapVert(), meshop.getMapVert(), meshop.setMapFace(), meshop.getMapFace(), 
		  meshop.makeMapPlanar(), meshop.getIsoMapVerts(), meshop.deleteMapVertSet(), meshop.freeMapVerts(),
		  meshop.freeMapFaces(), meshop.applyUVWMap(), meshop.buildMapFaces(), meshop.defaultMapFaces(),
		  meshop.setNumVDataChannels(), meshop.getNumVDataChannels(), meshop.setVDataChannelSupport(),
		  meshop.getVDataChannelSupport(), meshop.getFloatVDataValue(), meshop.setFloatVDataValue(),
		  meshop.freeVData(), meshop.resetVertWeights()
		- all map and vertex data channel indices are 1-based. This affects the channel parameter for
		  meshop.deleteIsoMapVerts, which used 0-based indices.
		- added getHashValue()
		- modified meshop methods that take a face/edge/vertex set to accept a bitarray, array, number, or
		  #all as the set specifier (for example, meshop.weldverts $ #all 0.01)
		- added bit.and(), bit.or(), bit.xor(), bit.not(), bit.shift(), bit.set(), bit.flip(), bit.get(), 
		  bit.intAsChar(), bit.charAsInt(), bit.intAsHex()
		- added meshop.getFaceArea()
v2.04	- fixes to meshop.setMapFace() and meshop.getMapFace()
		- fix to displayControlDialog
		- added rendPickupFrames
		- overriding mapPaths.add with version with update: option
v2.05	- added meshop.turnEdges()
v2.06	- qsort can now take any number of user-defined key arguments. These key arguments are passed to the 
		- comparison function. 
v2.07   - fixed cast in bit.shift method
v2.08   - fixed MultiListBox for when all items are deselected
v2.09   - fixed qsort so it can handle empty arrays without complaint.

Methods:

  avguardHelp()
      A quick summary of the methods and variables defined by this extension.

  getSegLengths <splineShape> <spline_index> [cum:<boolean>] [byVertex:<boolean>] [numArcSteps:<integer>]
	Returns array of segment lengths or vertex distances by spline fraction and length, and total spline length.
	Double precision calculations, very accurate. If cum:true, results are cumulative, otherwise they are
    relative. If byVertex:true results are per vertex, otherwise per segment. 
    Defaults: cum:false byVertex:false numArcSteps:100

  subdivideSegment <splineShape> <spline_index> <seg_index> <divisions>
	Divides the segment into the specified number of divisions. Double precision calculations, very accurate. 

  interpCurve3D <splineShape> <spline_index> <param_float> [pathParam:<boolean>]
	Returns a <point3> coordinate on the indexed curve. If pathParam:false, param is the fraction of the 
	spline length, otherwise it is a segment-based (path) fraction. Default is pathParam:false

  tangentCurve3D <splineShape> <spline_index> <param_float> [pathParam:<boolean>]
	Returns a <point3> tangent on the indexed curve. If pathParam:false, param is the fraction of the 
	spline length, otherwise it is a segment-based (path) fraction. Default is pathParam:false

  setMaterialID <splineShape> <spline_index> <seg_index> <matID>
	Sets the material ID of the specified spline segment.

  getMaterialID <splineShape> <spline_index> <seg_index>
	Gets the material ID of the specified spline segment.

  getNodeTM <node>
	Returns the node's world space transformation matrix.

  getTransformAxis <node> <index> 
	Returns the transform axis of the indexed axis system of the node as a <matrix3> value. Normally a node just
	has 1 transform axis. In some cases (like being in the Local Reference Coordinate System, in object SO mode,
	and having multiple SO selected), multiple transform axes exist. If index > the number of transform axis, 
	the transform for the first transform axis is returned.
	The transform returned by this method can be used in an "in coordsys" context and an "about" context to 
	move, rotate, or scale an object about the current MAX UI Reference Coordinate System and Center.
	For example:

	fn axisRotate obj rotation =  
	(	local axis
		local objA = if classof obj == objectSet or classof obj == array then obj else #(obj)
		if getCoordCenter() != #local then
		(	axis = getTransformAxis objA[1] 0
			for obj1 in objA do in coordsys axis about axis rotate obj1 rotation
		)
		else
		(	for obj1 in objA do
			(	axis = getTransformAxis obj1 0
				in coordsys axis about axis rotate obj1 rotation
			)
		)
	)

  invalidateTM <node> 
	Invalidates the node's transformation matrix cache.

  invalidateTreeTM <node> 
	Invalidates the node's transformation matrix cach and notify the node's subtree that the 
	transformation matrix has changed.
	The following MAXScript function can be used to force an update of an object whose transform
	is partially controlled by a scripted controller (such as a script controller on the position
	track):

	mapped fn TMInvalidate obj =
	(	at time (currenttime-1) obj.transform
		nodeInvalRect obj
		invalidateTreeTM obj
		redrawViews()
	)

  invalidateWS <node> 
	Invalidates the node's world space cache.

  getNodeByName <string> exact:<boolean> 
	Returns first <node> with the specified name. String case is insensitive unless exact:true. 
	Default is exact:false

  snapshotAsMesh <node>
	Returns world state of node as a <mesh> value.

  getInheritanceFlags <node> 
  setInheritanceFlags <node> (#all | #none | <bitarray>) keepPos:<boolean>
	Get and set the inheritance flags for the specified node as an <bitarray>. If a bit is on, the 
	corresponding inheritance is turned on. The order of the bits is:
	#{POS_X,POS_Y,POS_Z,ROT_X,ROT_Y,ROT_Z,SCALE_X,SCALE_Y,SCALE_Z}
	If keepPos:false is specified, the node may move when an inheritance is turned on or off.

  getTransformLockFlags <node>
  setTransformLockFlags <node> (#all | #none | <bitarray>)
	Get and set the transform lock flags for the specified node as an <bitarray>. If a bit is on, the 
	corresponding transform lock is turned on. The order of the bits is:
	#{POS_X,POS_Y,POS_Z,ROT_X,ROT_Y,ROT_Z,SCALE_X,SCALE_Y,SCALE_Z}

  isSelectionFrozen()
	Returns true if the node selection is frozen, false if not frozen

  freezeSelection()
	Freezes the node selection

  thawSelection()
	Thaws the node selection.

  getPropertyController <value> <string_or_name>
  setPropertyController <value> <string_or_name> <controller>
	Get and set the controller assigned to the named property of the value. If no controller has been
	assigned to the property, a value of undefined is returned.

  replaceInstances <old_MAXWrapper> <new_MAXWrapper>
	Replaces all instances of the old MAXWrapper with the new MAXWrapper. Old and new MAXWrapper must
	have the same superclass.
	Minimal error checking, use with extreme caution.

  getMouseMode()
	Returns the mouse mode as an integer value. Results are: 0 - Idle; 1 - Point; 2 - Move
	Note: deprecated method - use mouse.mode instead

  getMouseButtonStates()
	Returns the state of the mouse buttons as a 3 element bitArray. The order of the bits is:
	#(Left, Middle, Right)
	Note: right mouse button state not always correct. If you right click to bring up a right-click
	menu and then click in the viewport to dismiss the menu, the right mouse button is still reported as down.
	Note: deprecated method - use mouse.buttonStates instead

  getMTLMEditFlags ( <material> | <texture> ) 
  setMTLMEditFlags ( <material> | <texture> ) <bitarray>
	Get and set the MEdit options for the specified material or texture as a <bitarray>. If a bit is on, 
	the corresponding option is turned on. The order of the bits is:
	#{MTL_BEING_EDITED,BACKGROUND,BACKLIGHT,VIDEO_COLOR_CHECK}
	The first bit is set if the rollout for the specified material or texture is currently displayed
	in the active MEdit slot. The state of this bit is ignored in setMTLMEditFlags().

  getMTLMeditObjType ( <material> | <texture> )
  setMTLMeditObjType ( <material> | <texture> ) <integer>
	Get and set the MEdit sample object type for the specified material or texture. The valid values 
	are: 1 - sphere; 2 - cylinder; 3 - cube; 4 - custom

  getMTLMeditTiling ( <material> | <texture> )
  setMTLMeditTiling ( <material> | <texture> ) <integer>
	Get and set the MEdit tiling type for the specified material or texture. The valid values 
	are: 1 - 1x1; 2 - 2x2; 3 - 3x3; 4 - 4x4

  updateMTLInMedit ( <material> | <texture> )
	Performs a set of MAX notifications that forces an update of the material or texture throughout
	MAX, including the MEdit and material browser.

  insertItem <value> <array> <integer>
	Inserts the value at the specified index in the array, growing the array if necessary

  qsort <array> <function> [start:<integer>] [end:<integer>] [user-defined key args passed to function]
	Sorts the array using the specified function for element-by-element comparison. The comparison
	function must take 2 values as arguments, and return a number < 0 if the first value is less than the
	second value, 0 if the values are equivalent, and a number > 0 if the first value is greater than the
	second value. The entire array is sorted unless a start or end value is specified.
	For example, the following script generates 10 random positions, and then sorts the positions based on
	their distance from [0,0,0]:
		positions=for i=1 to 10 collect (random [0,0,0] [100,100,0])
		qsort positions (fn distFrom0 v1 v2 = (length v1)-(length v2))
	All key arguments are now passed to the comparison function. This allows you to do things like an indexed 
	sort:
		fn compareFN v1 v2 valArray: =
		(	local v1i = valArray[v1]
			local v2i = valArray[v2]
			(length v1i)-(length v2)
		)
		positions=for i=1 to 10 collect (random [0,0,0] [100,100,0])
		indexArray = for i = 1 to positions.count collect i
		qsort indexArray compareFN valArray:positions
		for i = 1 to positions.count do print positions[indexArray[i]]


  amin ( <array> | {value} ) 
	Returns minimum value of items in the array or of the argument values. If the array size is zero or
	no arguments are specified, the value undefined is returned. Examples:
		myMin1 = amin #(5,1,4,2,8)
		myMin2 = amin 5 1 4 2 8

  amax ( <array> | {value} )
	Returns maximum value of items in the array or of the argument values. If the array size is zero or
	no arguments are specified, the value undefined is returned.

  getXYZControllers <controller>
	Returns an array of the X, Y, and Z sub-controllers of the specified controller

  displayControlDialog <controller> <string>
	Displays the modal controller dialog, if any. The string will be in the dialog title bar. If the 
	controller is a keyframe controller, the key info dialog will be displayed for the selected keys. If
	no keys are selected, no dialog will be displayed.

  getBitmapOpenFileName caption:<title> filename:<seed_filename_string>
  getBitmapSaveFileName caption:<title> filename:<seed_filename_string>
	Displays the bitmap file selection dialog. Both functions return a fully-specified file path name or undefined 
	if the user cancels out. If an existing file name is selected using the getBitmapSaveFileName() function, a File 
	Exists/Confirm Overwrite dialog will be displayed. Note: The getBitmapOpenFileName() function does not require 
	that an existing file name be selected - i.e., a file name is returned if the user types a file name that does not
	exist. If necessary, you should check the file name that is returned to ensure the file exists.

  doesFileExist <filename_string>
	Returns true if the file exists, false otherwise

  getToolbtnState <name>
	Returns whether the specified tool button is on or off as a <boolean> value. Valid name values are:
		#select
		#move
		#rotate
		#uscale		-- returns true if any of the scale button states is on
		#nuscale	-- returns true if any of the scale button states is on
		#squash		-- returns true if any of the scale button states is on

  WSMApplyFC <WSM_node_array> <pos_point3_array> <vel_point3_array> <force_point3_array> interval:<interval> stepsize:<time> 
	Applies force-field (Particles & Dynamics + Displace) and deflector (Particles Only) type Space Warps to 
	the position, velocity, and force array values. The position values are in MAX units, the velocity values 
	are in MAX units/tick, the force values are in Max units/tick^2 (mass assumed to be == 1). The position, 
	velocity, and force arrays must be the same size. The effects of the space warps are evaluated over the 
	specified interval, with a default interval of (interval currenttime (currenttime+1f)), using the specified 
	stepsize, with a default of 1 frame. The effect of the force-field space warps are first evaluated in the 
	order specified, followed by the deflector space warps in the order specified. The values in the position, 
	velocity, and force arrays are replaced with the results of the evaluation of the effects of the space 
	warps. The supplied force values are applied prior to the space warps being applied. Normally you 
	want to set the force array to contain values of [0,0,0] prior to calling this method. Only if you are 
	calculating an additional force in your script would you set the force array to other values. The position 
	and velocity arrays would normally contain the results of the last call to this method. Any force-field 
	space warp, including 3rd party plugins, should work correctly. Only the deflector space warps that ship 
	with MAX are supported. The Path Follow space warp is not suppported as it requires a particle system.

	Example usage (assuming an appropriately placed Gravity and Deflector space warp):
		posArray=#([10,0,0],[10,10,0])
		velArray=#([0,0,0],[0,0,0])
		for i = 0 to 20 do
		(	forceArray=#([0,0,0],[0,0,0])
			point pos:posArray[1] 
			point pos:posArray[2] 
			at time i WSMApplyFC #($gravity01,$deflector01) posArray velArray forceArray
		)
		point pos:posArray[1] 
		point pos:posArray[2] 

	Note: Thinking about adding a 'collided' named parameter that takes a bitArray value, and have the method
	set the corresponding bit if a collision has occurred. Also a 'stopAtCollision' named parameter that, if 
	set to true, would stop evaluating the interval when a collision is detected. The current return value 
	for this method is always 'ok', but would be changed to the time at which the first collision occurred or
	undefined if no collision occurred. Also, possibly allow the <pos_point3_array> to be an array of point3
	controllers and set keys for the controllers at each timestep. Probably would need to also specify an 
	offset transform, since the position values need to be in world space.

  WSMSupportsForce <node>
	Returns true if the specified node can be used as a force-field type space warp for WSMApplyFC.

  WSMSupportsCollision <node>
	Returns true if the specified node can be used as a deflector type space warp for WSMApplyFC.

  quatToEuler <quat> order:<eulertype_integer>
  eulerToQuat <eulerAngle> order:<eulertype_integer>
	Convert between quat and euler angle values. The optional order parameter specifies the order of 
	application of the angles. If not specified, XYZ ordering is used. Its value can be any of the following:
		1 - XYZ
		2 - XZY
		3 - YZX
		4 - YXZ
		5 - ZXY
		6 - ZYX
		7 - XYX
		8 - YZY
		9 - ZXZ

  meshop.getEdgesUsingVert <mesh> {<vert_index_integer> | <vert_index_array> | <vertex_bitarray> | #all}
     Returns a bitarray of size=(#edges in mesh) with bits set for all edges that use the specified vertices.

  meshop.getFacesUsingVert <mesh> {<vert_index_integer> | <vert_index_array> | <vertex_bitarray> | #all}
     Returns a bitarray of size=(#faces in mesh) with bits set for all faces that use the specified vertices.

  meshop.getPolysUsingVert <mesh> {<vert_index_integer> | <vert_index_array> | <vertex_bitarray> | #all} \
                           ignoreVisEdges:<boolean> threshhold:<angle_float>
     Returns a bitarray of size=(#faces in mesh) with bits set for all faces that are in 'polygons' containing 
	 the specified vertices. The definition of a polygon is all faces sharing invisible edges with edge angles 
	 below the threshhold angle. The default threshhold angle is 45 degrees. If ignoreVisEdges is set to true, 
	 the edge visibility is ignored but the threshhold is still relevant.

  meshop.getVertsUsingEdge <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all}
     Returns a bitarray of size=(#vertices in mesh) with bits set for all vertices that are used by the 
	 specified edges.

  meshop.getFacesUsingEdge <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all}
     Returns a bitarray of size=(#faces in mesh) with bits set for all faces that use the specified edges.

  meshop.getPolysUsingEdge <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all} \
                           ignoreVisEdges:<boolean> threshhold:<angle_float>
     Returns a bitarray of size=(#faces in mesh) with bits set for all faces that are in 'polygons' containing 
	 the specified edges. The definition of a polygon is all faces sharing invisible edges with edge angles 
	 below the threshhold angle. The default threshhold angle is 45 degrees. If ignoreVisEdges is set to 
	 true, the edge visibility is ignored but the threshhold is still relevant.

  meshop.getVertsUsingFace <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all}
     Returns a bitarray of size=(#vertices in mesh) with bits set for all vertices that are used by the 
	 specified faces.

  meshop.getEdgesUsingFace <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all}
     Returns a bitarray of size=(#edges in mesh) with bits set for all edges that are used by the specified 
	 faces.

  meshop.getPolysUsingFace <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all} \
                           ignoreVisEdges:<boolean> threshhold:<angle_float>
     Returns a bitarray of size=(#faces in mesh) with bits set for all faces that are in 'polygons' containing 
	 the specified faces. The definition of a polygon is all faces sharing invisible edges with edge angles 
	 below the threshhold angle. The default threshhold angle is 45 degrees. If ignoreVisEdges is set to 
	 true, the edge visibility is ignored but the threshhold is still relevant.

  meshop.getEdgesReverseEdge <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all}
	Returns a bitarray of size=(#edges in mesh) with bits set for all additional edges that use the same 
	vertices as the specified edges. These are edges on the adjacent faces.

	Example usage of the above:

		Plane length:100 width:100 isSelected:on
		convertTo $ TriMeshGeometry
		max modify mode
		subobjectLevel = 1
		select $.verts[13]
		-- get edges that use vertex 13
		edges = meshop.getEdgesUsingVert $ (getVertSelection $)
		-- select the vertices used by those edges
		$.selectedVerts = meshop.getVertsUsingEdge $ edges
		update $
		-- not what we wanted, really want all vertices "surrounding" vertex 13
		faces = meshop.getPolysUsingVert $ 13
		$.selectedVerts = meshop.getVertsUsingFace $ faces
		update $
		-- or ...
		faces = meshop.getFacesUsingVert $ #(13)
		edges = meshop.getEdgesUsingFace $ faces
		-- turn off all visible edges
		for e in edges do edges[e]=not (getEdgeVis $ (1+(e-1)/3) (1+mod (e-1) 3))
		-- get the edges on the adjacent faces that are the "reverse" of these edges
		-- "OR" that bitarray with the initial edges bitarray
		edges = (meshop.getEdgesReverseEdge $ edges) + edges
		-- get the faces that use the edges, and "OR" that bitarray with the initial
		-- face bitarray
		faces = (meshop.getFacesUsingEdge $ edges) + faces
		$.selectedVerts = meshop.getVertsUsingFace $ faces
		update $

  meshop.attach (<target_editable_mesh_node> | <target_mesh>) (<source_node> | <source_mesh>) \
				targetNode:<target_node> sourceNode:<source_node> \
				attachMat:(#neither | #MatToID | #IDToMat) condenseMat:<boolean> \
				deleteSourceNode:<boolean = true>
	Attaches the source mesh to the target mesh. If the target or source is specified as a mesh rather
	than a node, the mesh is attached using the local coordinate system of the mesh, and no material 
	correction is performed. To get around this, if the target or source is a mesh, the corresponding 
	targetNode or sourceNode named parameter is checked to see if a node is specified and, if it is, the
	transform and material for than node is used. If the source or target is specified as a node, the
	corresponding targetNode or sourceNode named parameter is not checked. The attachMat and condenseMat 
	options correspond to the attach options in editable mesh. condenseMat is applicable only if 
	attachMat:#IDToMat is specified. If deleteSourceNode:false is not specified, and the source was specified 
	as a node, or as a mesh and a sourceNode was specified, the source node is deleted after the attach.
    Defaults: attachMat:#neither condenseMat:true deleteSourceNode:true
	Examples:
		meshop.attach $.baseobject $sphere02 targetNode:$
		meshop.attach $box01 $box02 attachMat:#IDToMat condenseMat:true deleteSourceNode:false

  meshop.getVertWeight <mesh> <vert_index_integer>
	Returns the weight assigned to the specified vertex as a <float>

  meshop.setVertWeight <mesh> {<vert_index_integer> | <vert_index_array> | <vertex_bitarray> | #all} <weight_float>
	Sets the weight for the specified vertices.

  meshop.resetVertWeights <Mesh mesh>
	Resets all the vertex weights to 1.

  meshop.getVertsByColor <mesh> <color> <red_range_float> <green_range_float> <blue_range_float>
	Returns the vertices whose vertex color is within the color range as a <bitarray>. The range values should
	be in the range of 0 to 255.

  meshop.weldVerts <mesh> {<vert_index_integer> | <vert_index_array> | <vertex_bitarray> | #all} <distance_float>
	Welds the specified vertices that are within the specified distance. The distance is in the local coordinate
	system of the mesh. A value of true is returned if vertices were welded, false otherwise.

  meshop.autoSmooth <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all} <threshold_angle_float>
	Smooths the specified faces based on the threshold angle.

  meshop.unifyNormals <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all}
	Unifies the normals of the specified faces.

  meshop.flipNormals <mesh> {<face_index_integer> | <face_index_array> | <face_bitarray> | #all}
	Flips the normal of the specified faces.

  meshop.autoEdge <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all} \
				  <threshold_angle_float> type:{#SetClear | #Set | #Clear}
	Sets/clears the edge visibility for the specified edges based on the threshold angle. Note: for an edge 
	to be autoEdged, both it and the "reverse" edge on the face sharing the edge vertices must be specified 
	in the edge specification.

  meshop.turnEdges <mesh> {<edge_index_integer> | <edge_index_array> | <edge_bitarray> | #all}
	Turns the specified edges. Only works on edges that have a face on both sides. These two faces are considered 
	as a quad, where this edge is the diagonal, and remapped so that the diagonal flows the other way, between 
	the vertices that were opposite this edge on each face. Note: The edges are turned in increasing numerical 
	order if the edges to turn are specified via an array or bitArray. Since the edges can be renumbered when an
	edge is turned, incorrect edges may be turned if 

  meshop.getFaceArea <Mesh mesh> {<face_index_integer> | <face_index_array> | <face_bitarray>}
	Returns the area of the specified faces as a <float>

  meshop.setNumMaps <Mesh mesh> <Integer count> [keep:FALSE]
	Sets the number of map channels available. The number of map channels can be set from 2 to 100.
	Map channels 1 and 2 are the Vertex Color and default Texture Map channels. If keep is false or
	not specified, the old mapping information is discarded. If true, the old mapping information 
	is retained after the resize.

  meshop.getNumMaps <Mesh mesh>
	Returns the number of map channels available as an <integer>.

  meshop.setMapSupport <Mesh mesh> <Integer mapChannel> <Boolean support>
	Sets whether the specified mapping channel is supported or not. If support is true, and the
	channel support state is currently false, a new map face array of the same size as the number of 
	faces in the mesh is allocated, but no map vertex array is allocated. If support is false, and
	the channel support state is currently true, existing map channel face and vertex arrays are 
	deallocated. If support and the current channel support state are both the same, no action is 
	performed. SetNumMaps() is automatically called if the specified map channel is not available.
	mapChannel index values are 1-based, with Map channels 1 and 2 being the Vertex Color and default 
	Texture Map channels.

  meshop.getMapSupport <Mesh mesh> <Integer mapChannel>
	Returns whether the specified map channel is supported. This signifies that a map face array
	is present, but not necessarily a map vertex array.

  meshop.setNumMapVerts <Mesh mesh> <Integer mapChannel> <Integer count> [keep:FALSE]
	Sets the number of vertices for the map channel, initializing the map vertex array. If keep is 
	false or not specified, the old map vertex information is discarded. If true, the old map vertex 
	information is retained after the resize.

  meshop.getNumMapVerts <Mesh mesh> <Integer mapChannel>
	Returns the number of vertices for the map channel as an <integer>.

  meshop.setNumMapFaces <Mesh mesh> <Integer mapChannel> <Integer count> [keep:FALSE] [keepCount:0]
	Sets the number of faces for the map channel. If keep is false or not specified, the old map face
	information is discarded. If true, the old map face information from the number of faces specified 
	by keepCount is retained after the resize. Dangerous to use with map channels 1 and 2, so miminum 
	mapChannel value is 3.

  meshop.getNumMapFaces <Mesh mesh> <Integer mapChannel>
	Returns the number of faces for the map channel as an <integer>.

  meshop.setMapVert <Mesh mesh> <Integer mapChannel> <Integer index> <Point3 xyz>
	Sets the coordinates of the specified map vertex.

  meshop.getMapVert <Mesh mesh> <Integer mapChannel> <Integer index>
	Returns the coordinates of the specified map vertex as a <point3>.

  meshop.setMapFace <Mesh mesh> <Integer mapChannel> <Integer index> <Point3 face>
	Sets the map vertices for the specified map face.

  meshop.getMapFace <Mesh mesh> <Integer mapChannel> <Integer index>
	Returns the vertices of the specified map face as a <point3>.

  meshop.makeMapPlanar <Mesh mesh> <Integer mapChannel>
	Applies a simple planar mapping to the specified channel. This is done by copying the mesh 
	topology and vertex locations into the map, resizing the face and vertex arrays if necessary.

  meshop.getIsoMapVerts <Mesh mesh> <Integer mapChannel>
	Returns a <bitarray> with a bit set for each isolated map vertex (unrefereced by any map face) 
	for the specified channel.

  meshop.deleteMapVertSet <Mesh mesh> <Integer mapChannel> {<BitArray set> | <Integer index> | <integer array>}
	Deletes the specified map vertices. Returns a <bitarray> with a bit set for each map face that 
	used one of the deleted map vertices. Normally, you should delete or modify the map faces using 
	the map vertices before deleting the map vertices, as after the vertex deletion you can't tell 
	which vertex on a face was a vertex that was deleted.

  meshop.freeMapVerts <Mesh mesh> <Integer mapChannel>
	Deallocates the map vertex array and sets the number of map vertices to 0.

  meshop.freeMapFaces <Mesh mesh> <Integer mapChannel>
	Deallocates the map face array and sets the number of map faces to 0.

  meshop.applyUVWMap <TriMesh mesh> {<#planar | #cylindrical | #spherical | #ball | #box>} \
					 <float utile> <float vtile> <float wtile> \
					 <boolean uflip> <boolean vflip> <boolean wflip> \
					 <boolean cap> <Matrix3 tm> [channel:1]
	Applies the specified mapping type to the mapping channel. utile/vtile/wtile - Number of tiles 
	in the U/V/W directions. uflip/vflip/wflip - U/V/W are mirrored if true. cap - used with 
	#cylindrical. If true, then any face normal that is pointing more vertically than horizontally 
	will be mapped using planar coordinates. tm - defines the mapping space. As each point is mapped, 
	it is multiplied by this matrix, and then it is mapped. channel - the mapping channel the mapping
	is applied to, defaults to channel 1.

  meshop.buildMapFaces <Mesh mesh> <Integer mapChannel> <Boolean keep>
	Sets the number of map faces to the number of mesh faces, retaining existing mapping data if keep 
	is true. Deletes any map vertices that are not used by the map faces.

  meshop.defaultMapFaces  <Mesh mesh> <Integer mapChannel> <Integer count>
	Sets the number of map faces to the number of mesh faces, and the number of map vertices to the 
	number of mesh vertices. The map face vertices are set to the same vertex index as the corresponding
	mesh face vertices (i.e., there will be a 1-to-1 correspondence between map faces/vertices and the
	mesh faces/vertices). The map vertex UVW coordinates are set to the normalized (0 to 1) position of
	the corresponding mesh vertex in the mesh's bounding box.

  meshop.setNumVDataChannels <Mesh mesh> <Integer count> [keep:false]
	Sets the number of vertex data channels available. The number of vertex data channels can be set from 
	2 to 100. Vertex data channels 1 and 2 are the Vertex Soft Selection and Vertex Weight channels. If 
	keep is false or not specified, the old channel data is discarded. If true, the old channel data 
	is retained after the resize.

  meshop.getNumVDataChannels <Mesh mesh>
	Returns the number of vertex data channels available as an <integer>.

  meshop.setVDataChannelSupport <Mesh mesh> <Integer vdChannel> <Boolean support>
	Sets whether the specified vertex data channel is supported or not. If support is true, and the
	channel support state is currently false, a new vertex data array of the same size as the number of 
	vertices in the mesh is allocated. If support is false, and the channel support state is currently 
	true, the existing vertex data channel array is deallocated. If support and the current channel support 
	state are both the same, no action is performed. setNumVDataChannels() is automatically called if the 
	specified vertex data channel is not available. vdChannel index values are 1-based, with channels 1 and 
	2 being the Vertex Soft Selection and Vertex Weight channels.

  meshop.getVDataChannelSupport <Mesh mesh> <Integer vdChannel>
	Returns whether the specified vertex data channel is supported.

  meshop.getFloatVDataValue <Mesh mesh> <Integer vdChannel> <Integer vertex_index>
	Returns the floating point data value associated with vertex vertex_index in vertex data channel 
	vdChannel as a <float>.

  meshop.setFloatVDataValue <Mesh mesh> <Integer vdChannel> <Integer vertex_index> <Float value>
	Sets the floating point data value associated with vertex vertex_index in vertex data channel 
	vdChannel.

  meshop.freeVData <Mesh mesh> <Integer vdChannel>
	Deallocates the existing vertex data channel array and turns off the vertex data channel support state.

  meshop.getUIParam <mesh> <param_name>
  meshop.getUIParam <node> [ <modifier_or_index> ] <param_name>
  meshop.setUIParam <mesh> <param_name> { <float> | <boolean> }
  meshop.setUIParam <node> [ <modifier_or_index> ] <param_name> { <number> | <boolean> }
	Get/set a user-interface value. The optional <modifier_or_index> identifies the Edit Mesh modifier on the 
	given scene object to set the parameter value for. These methods are UI-dependent, and require that the 
	specified editable mesh or Edit Mesh modifier be currently displayed in the Modify panel. The valid
	param_name values, their meaning, and parameter value type are:
		#SelByVert		Selection - By Vertex (boolean)
		#IgBack			Selection - Ignore Backfacing (boolean)
		#IgnoreVis		Selection - Ignore Visibile Edges (boolean)
		#PolyThresh		Selection - Planar Threshold (number)
		#SoftSel		Soft Selection - Use Soft Selection (boolean)
		#SSUseEDist		Soft Selection - Edge Distance (boolean)
		#SSEDist		Soft Selection - Edge Distance (number) [note: if value hasn't been changed, returns a value of 0]
		#SSBack			Soft Selection - Ignore Backfacing (boolean) [note: this is the inverse of the UI element]
		#Falloff		Soft Selection - Falloff (number)
		#Pinch			Soft Selection - Pinch (number)
		#Bubble			Soft Selection - Bubble (number)
		#WeldDist		Weld - Distance (number)
		#WeldBoxSize	Weld - Box Size in Pixels (number)
		#ExtrudeType	Extrude/Chamfer (boolean) [note: true - Group; false - Local]

  getPointControllers {<editable_mesh_node> | <editable_spline_node>} 
	Returns an array of controllers assigned to the vertices in the mesh or spline. If no controller has been 
	assigned to a vertex, the array element value will be undefined. For editable splines, each knot consists 
	of 3 vertices: the in vector, the knot, and the out vector. The array of controllers returned is a "snapshot" 
	of the current controllers. If controllers are assigned or changed for a vertex, this change is not reflected 
	in the array. If a vertex is added/deleted, the array is not resized to reflect the change in number of 
	vertices.

  getPointController <editable_mesh_node> <vertex_index_integer> 
	Returns the controller currently assigned to the vertex, undefined if no controller assigned.

  getPointController <editable_spline_node> <spline_index_integer> <vertex_index_integer> 
	Returns the controller for specified vertex in the specified spline, undefined if no controller assigned. 
	Each spline knot consists of 3 vertices: the in vector, the knot, and the out vector.

  isStructDef <value>
	Returns true if the value is a structure definition

  isStruct <value>
	Returns true if the value is a structure instance

  isController <value>
	Returns true if the value is a controller

  getHashValue <value> <Integer oldHaskValue>
	If the value is one of the supported value types, returns an integer hash value that is a factor of the 
	value and oldHaskValue. If the value type is not supported, returns a value of undefined. The supported
	value types are:
		Float 
		Integer 
		String 
		BitArray 
		Point3
		Ray
		Quat
		AngAxis
		EulerAngles
		Matrix3
		Point2
		Color
		Arrays containing any of the above value types

  bit.and <integer1> <integer2>
	Returns the <integer> result of AND-ing the bits in integer1 and integer2

  bit.or <integer1> <integer2>
	Returns the <integer> result of OR-ing the bits in integer1 and integer2

  bit.xor <integer1> <integer2>
	Returns the <integer> result of XOR-ing the bits in integer1 and integer2

  bit.not <integer1>
	Returns the <integer> result of flipping the bits in integer1

  bit.shift <integer1> <integer2>
	Returns the <integer> result of shifting the bits in integer1 by integer2 places. If integer2 is
	positive, the bits are shifted to the left, if negative, to the right. The highest order bit is 
	not carried when shifting to the left (unsigned shift operation).

  bit.set <integer1> <integer2> <boolean>
	Returns an <integer> result where bit integer2 of integer1 is set to the specified boolean value. 
	Bit 1 is the lowest order (least significant) bit.

  bit.flip <integer1> <integer2>
	Returns an <integer> result where bit integer2 of integer1 is flipped. Bit 1 is the lowest order 
	(least significant) bit.

  bit.get <integer1> <integer2>
	Returns the <boolean> state of the integer2 bit of integer1. Bit 1 is the lowest order 
	(least significant) bit.

  bit.intAsChar <integer>
	Returns a <string> result of length 1 containing the character corresponding to the integer
	value. Only the lowest order 8-bits (16-bits for localized versions of MAX) of the integer are
	used.

  bit.charAsInt <string>
	Returns the <integer> value corresponding to the first character of the string.

  bit.intAsHex <integer>
	Returns a <string> value containing the hex representation of the integer.

  mapPaths.add <string> [ update:<boolean> ]
	Adds the path string to the list the biitmap path directories. If update:false, the 3dsmax.ini
	file is not updated to include the added path. NOTE: this method overrides the existing mapPaths.add
	method.

Global Variables:

  listener 
	read only system global - listener edit window <WindowStream> value

  avguard_dlx_ver 
	read only system global - the version number of this plugin as <string> value

NOTE: The following globals should not be used if the Render Scene dialog is open.
      These globals do not update the dialog if it is open, and closing the dialog
      or rendering from the dialog will cause the displayed settings to be stored and
      used.

  rendTimeType -- integer
	Get/set the type of time range to be rendered. One of the following values:
		1 - A single frame.
		2 - The active time segment.
		3 - The user specified range.
		4 - The user specified frame pickup string (for example "1,3,5-12").

  rendStart -- time
	Get/set the renderer's start time setting.

  rendEnd -- time
	Get/set the renderer's end time setting.

  rendNThFrame -- integer
	Get/set the renderer's 'n-th' frame setting. Minimum value = 1

  rendShowVFB -- boolean
	Get/set the state of the renderer's show virtual frame buffer flag. TRUE = on; FALSE = off

  rendSaveFile -- boolean
	Get/set the state of the renderer's save file flag. TRUE = on; FALSE = off

  rendUseDevice -- boolean
	Get/set the state of the renderer's use device flag. TRUE = on; FALSE = off

  rendUseNet -- boolean
	Get/set the state of the renderer's use net flag. TRUE = on; FALSE = off

  rendFieldRender -- boolean
	Get/set the renderer's field render flag. TRUE = on; FALSE = off

  rendColorCheck -- boolean
	Get/set the renderer's color check flag. TRUE = on; FALSE = off

  rendSuperBlack -- boolean
	Get/set the renderer's super black flag. TRUE = on; FALSE = off

  rendHidden -- boolean
	Get/set the renderer's render hidden objects flag. TRUE = on; FALSE = off

  rendForce2Side -- boolean
	Get/set the renderer's force two-sided flag. TRUE = on; FALSE = off

  rendAtmosphere -- boolean
	Get/set the renderer's uses atmospheric effects flag. TRUE = on; FALSE = off

  rendDitherTrue -- boolean
	Get/set the renderer's dither true color flag. TRUE = on; FALSE = off

  rendDither256 -- boolean
	Get/set the renderer's dither 256 color flag. TRUE = on; FALSE = off

  rendMultiThread -- boolean
	Get/set the renderer's multi-threaded flag. TRUE = on; FALSE = off

  rendNThSerial -- boolean
	Get/set the output file sequencing nth serial numbering setting. TRUE = on; FALSE = off

  rendVidCorrectMethod -- integer
	Get/set the video color check method. One of the following values:
		1 is FLAG
		2 is SCALE_LUMA
		3 is SCALE_SAT

  rendFieldOrder -- integer
	Get/set the rendering field order. One of the following values:
		1 is Even
		2 is Odd

  rendNTSC_PAL -- integer
	Get/set the video color check NTSC or PAL setting. One of the following values:
		1 is NTSC
		2 is PAL

  rendSuperBlackThresh -- integer
	Get/set the super black threshold setting. Range 0 to 255.

  rendFileNumberBase -- integer
	Get/set the File Number Base in the 'Common Parameters' rollup of the Render Scene dialog.

  rendPickupFrames -- string
	Get/set the Frames string in the 'Common Parameters' rollup of the Render Scene dialog.

WAVSound structure variables and methods:

  WAVsound.filename
	Get/set Sound track filename as <string>. There currently is not a way to perform
	a Remove Sound via MAXScript

  WAVsound.start 
	Get/set Sound track range start time as <time>.

  WAVsound.end 
	A read only variable to get the Sound track range end time as a <time> value.

  WAVsound.mute 
	Get/set whether Sound track is active as <boolean>.

  WAVsound.isPlaying 
	A read only variable that returns whether the Sound track is currently playing 
	as a <boolean> value.

  WAVsound.scrub <interval>
	Plays back the specified time interval of the Sound track.

timeConfiguration structure variable:

  timeConfiguration.playbackSpeed
	Get/set viewport playback speed as an indexed <integer>. The valid values for the
	integer are: 1 - 1/4x, 2 - 1/2x, 3 - 1x, 4 - 2x, 5 - 4x.

ik structure methods:

  ik.getPinNode <node> 
	Gets the node the specified node is bound to in the IK panel as a <node> value, undefined if none.

  ik.setPinNode <node> (<node> | undefined)
	Sets the node the specified node is bound to in the IK panel. If undefined is specified,
	the node is unbound. Returns true if the bind was successful, false otherwise.

  ik.getPrecedence <node>
	Gets the precedence of the node as specified in the IK panel as an <integer> value

  ik.setPrecedence <node> <number> 
	Sets the precedence of the node as specified in the IK panel. Returns true if the assignment was successful, false otherwise.

  ik.getIsTerminator <node> 
  ik.setIsTerminator <node> <boolean>
	Get/set whether the node is a terminator.

  ik.getBindPos <node> 
  ik.setBindPos <node> <boolean>
	Get/set whether Bind Position is turned on for the node.

  ik.getBindOrient <node> 
  ik.setBindOrient <node> <boolean>
	Get/set whether Bind Orientation is turned on for the node.

toolmode structure variable:

  toolmode.commandmode
	Get/set the MAX command mode. The return value when getting the command mode is a <name> value if the
	command mode is a recognized command mode, otherwise the return value is an integer value. The recognized
	command modes are:
		#SELECT
		#MOVE
		#ROTATE
		#NUSCALE
		#USCALE
		#SQUASH
		#VIEWPORT
		#HIERARCHY
		#CREATE
		#MODIFY
		#MOTION
		#ANIMATION
		#CAMERA
		#NULL
		#DISPLAY
		#SPOTLIGHT
		#PICK

	When setting the MAX command mode, only the following command modes are valid:
		#SELECT
		#MOVE
		#ROTATE
		#NUSCALE
		#USCALE
		#SQUASH

  toolmode.axisConstraints
	Get/set the MAX axis constraints. The axis constraints values are:
		#X
		#Y
		#Z
		#XY
		#YZ
		#ZX

mouse structure variables:

  mouse.mode
	A read only variable to get the mouse mode as an <integer> value. 
	Return values are: 0 - Idle; 1 - Point; 2 - Move

  mouse.buttonStates
	A read only variable to get the state of the mouse buttons as a 3 element <bitArray>.
	The order of the bits is: #{Left, Middle, Right}
	Note: right mouse button state not always correct. If you right click to bring up a right-click
	menu and then click in the viewport to dismiss the menu, the right mouse button is still reported as down.

  mouse.pos
	A read only variable to get the mouse position in the currently active viewport as a <point2> value. 
	The coordinates are in pixel values. If the currently active viewport is a 2D view (Track View, 
	Schematic View, Listener, etc.), the coordinates are in the first non-2D viewport.

sysInfo structure variables:

  sysInfo.DesktopSize
	A read only variable to get the desktop size in pixels as a <point2> value. 

  sysInfo.DesktopBPP
	A read only variable to get the desktop color depth in bits per pixel as an <integer> value.

units structure variables and methods:

  units.DisplayType
	Get/set the current unit display type as a <name>. Valid unit display types are:
		#Generic
		#Metric
		#US
		#custom

  units.MetricType
	Get/set the current metric unit display type as a <name>. Valid metric unit display types are:
		#Millimeters
		#Centimeters
		#Meters
		#Kilometers

  units.USType
	Get/set the current US standard unit display type as a <name>. Valid US standard unit display types are:
		#Frac_In
		#Dec_In
		#Frac_Ft
		#Dec_Ft
		#Ft_Frac_In
		#Ft_Dec_In

  units.USFrac
	Get/set the current US fraction display type as a <name>. Valid US fraction display types are:
		#Frac_1_1
		#Frac_1_2
		#Frac_1_4
		#Frac_1_8
		#Frac_1_10
		#Frac_1_16
		#Frac_1_32
		#Frac_1_64
		#Frac_1_100

  units.CustomName
	Get/set the current custom unit name as a <string>

  units.CustomValue
	Get/set the current custom unit value as a <float>

  units.CustomUnit
	Get/set the current custom unit type as a <name>. Valid custom unit display types are:

  units.SystemScale
	Get/set the current system unit scale value as a <float>. This is the value shown in Preference Settings,
	General tab, System Unit Scale group.

  units.SystemType
	Get/set the current system unit scale type as a <name>. This is the unit shown in Preference Settings,
	General tab, System Unit Scale group. Valid system unit scale types are:
		#Inches
		#Feet
		#Miles
		#Millimeters
		#Centimeters
		#Meters
		#Kilometers

  units.formatValue <float>
	Returns a <string> value representing the <float> in the current unit scale. This method can cause 
	a string overflow, especially when the units are set to miles or kilometers. If an overflow occurs a
	run-time error is thrown.

  units.decodeValue <string>
	Parses <string> using the current unit settings and returns a <float>. A run-time error is thrown if 
	an error occurs in the parsing of the string.
	

Rollout UI elements:

  MultiListBox
	A MultiListBox item is used to place a list box in the rollout. This is a variant of the ListBox
	in which multiple items in the list can be selected. The syntax is: 

	MultiListBox <name> [ <caption> ] [ items:<array_of_strings> ] \ 
						[ selection:{<bitarray> | <number_array> | <number>} ] \
						[ height:<number> ] 

	The default alignment of MultiListBox items is #left. 

	Example 
		rollout test "test"
		(	MultiListBox mlb "MultiListBox" items:#("A","B","C") selection:#(1,3)
			on mlb selected val do format "selected: % - %\n" val mlb.selection[val]
			on mlb doubleclicked val do format "doubleclicked: % - %\n" val mlb.selection[val]
			on mlb selectionEnd do format "selectionEnd: %\n" mlb.selection
		)
		rof=newrolloutfloater "tester" 200 300
		addrollout test rof
		test.mlb.items
		test.mlb.selection=1
		test.mlb.selection=#(1,3)
		test.mlb.selection=#{}

	Parameters 
		items: 
			The array of text strings that are the items in the list. 
		selection: 
			A BitArray signifying the currently selected items in the list. The default selection value is #{}. 
		height: 
			The overall height of the MultiListBox in number of item lines. Defaults to 10 lines. To have a 
			MultiListBox display exactly N items, set height to N. 

	Properties 
		<listbox>.items                 Array of Strings
			The item string array. 
		<listbox>.selection             BitArray 
			The currently selected items. When setting the selection via a script, the selection can be specified
			as a BitArray, Array of numbers, or a number.

	Events 
		on <listbox> selected <arg> do <expr> 
			Called when the user selects or deselects an item in the list. The <arg> argument contains the index 
			of the item that was selected or deselected. Since multiple items can be selected or deselected at once, 
			this handler is called for each item in the list, starting from the top of the list, whose selection 
			has changed. 
		on <listbox> doubleClicked <arg> do <expr> 
			Called when the user double-clicks on an item in the list. Note that the on selected handler is always 
			called on single clicks and on the first click of a double-click. The <arg> argument contains the number 
			of the item double-clicked. 
		on <listbox> selectionEnd do <expr> 
			Called when the user selects or deselects an item in the list, but after all the calls to the on 
			selected handler have been made. 

	Notes
		There isn't a way to deselect all the items in the list by clicking in the list somewhere. To
		clear the list selection you will need a "Clear Selection" button that sets selection=#{}.


