--========================================================================--
--FB_quickLoopRing.ms   --version 1.1--
	--UV portion: 
	--	For Max 2010+ (I think, I no longer have max 2010 to test with but I don't think I've used anything that requires a newer version)
	--	For Max 2009 - UV's fallback to ONLY geometry loops
	--Skin portion: Max 2010+... (I think, I'm actually not sure, but it should work from several versions ago)
	--		update, it seems max 2009 doesn't register skinvert selections as a subobject selection, so the callback is never called :(
------------------------------------------
--Description:
	--enables shift+click selection of faceloop, edgering, edgeloop, and vertloops in the skin modifier and vertloops in the skin modifier
--------------------------------------------------------------------------------------------------
--How To Use:
	--simply select a subobject in the UV modifier and select a neighboring subobject while holding 'Shift' and it'll try and select the loop/ring for you
	--this script is activated each time you select a subobject, where it checks if you're pressing shift and then checks your modifier type to see if it needs to loop or ring anything
--------------------------------------------------------------------------------------------------
--Notes:
	--this script works with editable mesh and editable poly, editable mesh will show the hidden edges of your object, if you wish to keep those hidden, convert to editable poly
	--since this script runs all the time, there's a chance whatever your setup is could have strange behavior with it
--========================================================================--
--Installation:
	--drop this .ms file into ProgramFiles/3dsMaxXXXX/scripts/Startup/
	--then start 3ds max
	--FB_quickLoopRing will automatically start whenever you start 3ds max
--Uninstallation:
	-- to remove, delete FB_quickLoopRing.ms from the ...scripts/Startup/ folder and restart max
--========================================================================--
--email me with any questions or concerns at Chris@FunkyBunnies3d.com
--========================================================================--
--Change Log--
--========================================================================--
--version 1.1
--		added fix for moving/scaling/rotating 1 uv component at a time - since the reselection callback is called for some reason i had to put in a redo so it'll undo whatever changes this script makes.

Global FB_quickLoopRingStart = timeStamp()
Global FB_quickLoopRingWorking = False

Fn FB_quickLoopRing ev nodeHandles=
(
	--checks to see:::
	--::IF 
	--		pressing Shift
	--		and it's been at least 500 milliseconds since the last time this ran [to avoid accidentally running more than once]
	--::BUT NOT
	--		pressing Alt
	--		pressing Ctrl
	--		flagged as "FB_quickLoopRingWorking"
	if (keyboard.shiftPressed And Not keyboard.controlPressed And Not keyboard.altPressed And ((timeStamp())-FB_quickLoopRingStart > 500) And Not FB_quickLoopRingWorking) then 
	(
		FB_quickLoopRingWorking = true
		try
		(
			undo on
			(
				nodes = (GetAnimByHandle (nodeHandles[1]))
				
				if (classOf nodes[1] ==SubAnim) then
					 nodes = selection[1]
				--print ("event: " + ev as string)
				--print ("on: " + nodes[1] as string)
				currModifierType = Classof (modPanel.getcurrentobject())
					
				if (currModifierType  == unwrap_UVW) then
				(
					--initialize the UV modifier, the subobjectmode to determine whether to do face,edge,vert loop/ring
					--and check if the mouse is within the UV editor window, initialize to false (this flags whether or not to do a Geometry loop vs. a UV loop)
					unwrapMod = nodes.modifiers[#unwrap_UVW]
					CurrSubobjmode = unwrapMod.getTVSubObjectMode()
					isMouseInUVeditor = false
					
					--check if mouse is within UV editor window
						local uvX =  unwrapMod.GetWindowX();
						local uvY =  unwrapMod.GetWindowY();
						local uvH =  unwrapMod.GetWindowH();
						local uvW = unwrapMod.GetWindowW();
						local mousePos = mouse.screenpos
						if (uvX >0 and uvY>0 and uvH>0 and uvW>0) And mousePos[1]>uvX And mousePos[1]<(uvX+uvW) And mousePos[2]>uvY And mousePos[2]<(uvY+uvH) do
							isMouseInUVeditor = true
					--end check if within UV editor window					
					
					--if in face mode...
					if (CurrSubobjmode == 3) then
					(
						--define a struct for the new subobject selections so we can reselect them easily
						Struct SubObjSelectionPair ( subobjSel2,subobjSel3, NodeSel)
						FinalSelectionPairs = #()
						newSelectionPairs = #()
						initSelectionPairs = #()
						
					--Store New selection
						for selectedNode in (selection as array) do
						(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
							testnewEdge = (selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array
							testnewFace = (selectedNode.modifiers[#unwrap_UVW].getSelectedFacesByNode selectedNode) as array
							
							if (testnewFace).count > 1 then
							(
								--umm try and convert this to geometry verts later and see if they line up, otherwise halt operation because too many verts are selected - maybe marquee?
								if (selectedNode.modifiers[#unwrap_UVW].getSelectedPolygonsByNode selectedNode as Array).count > 1 then
									Throw "More than 1 Face selected"
							)
							append newSelectionPairs (SubObjSelectionPair SubObjSel3:testnewFace SubObjSel2:testnewEdge NodeSel:selectedNode)
						)
						with redraw off
						(
					--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
							max undo
					--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
							
						--Store old selections
							for iterate = 1 to newSelectionPairs.count do
							(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
								selectedNode = newSelectionPairs[iterate].NodeSel
								append initSelectionPairs (SubObjSelectionPair SubObjSel3:((selectedNode.modifiers[#unwrap_UVW].getSelectedFacesByNode selectedNode) as array) SubObjSel2:((selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array) NodeSel:selectedNode)
							)
							
							--finally do the main part now that selections have been stored
							for iterate = 1 to NewSelectionPairs.count do
							(
								selectedNode = newSelectionPairs[iterate].NodeSel
								unwrapMod = selectedNode.modifiers[#unwrap_UVW]
								
								newFace = newSelectionPairs[iterate].subObjSel3
								_Faces = initSelectionPairs[iterate].subObjSel3
								_edges =  newSelectionPairs[iterate].subObjSel2
								_newFaces2Add = #()
								
								_addVerts = #()
								newEdges = #()		
								localEdges = #()
								
							
									--SKIP THIS ITERATION IF THE NEW SELECTION IS WITHIN THE PREVIOUS SELECTION OR IF THERE'S NOTHING SELECTED AT ALL
									if (Newface.count == 0) then
									(
										CurrObjectSubobjs = SubObjSelectionPair subobjSel3:_faces subobjSel2:_edges NodeSel:selectedNode
											append FinalSelectionPairs CurrObjectSubobjs
											continue
									)
									else if (for i = 1 to newFace.count where (findItem _faces newFace[i])>0 collect i).count > 0 then
									(
										print "FB_Quickloopring aborted: Shift+selection overlaps previous selection"
										--if selection count is OVER 1, then it was already caught by a test, but if the selection is only 1 subobject, we have to REDO since we previously undid
											if newFace.count==1 then actionMan.executeAction 0 "40016"  -- Edit: Redo Scene Operation
										throw "Shift+selection overlaps previous selection"
									)
									
									
									unwrapMod.faceToEdgeSelect()
									_faceEdges = (unwrapMod.getSelectedEdgesByNode SelectedNode ) as array
										unwrapMod.selectFacesByNode (newFace as bitarray) selectedNode

									unwrapMod.faceToEdgeSelect() 
									unwrapMod.setTVSubObjectMode 2
									--if the mouse was not within the uv editor, then sync to geometry and assume the user was trying to select a geometry loop rather than uv loop
									if Not isMouseInUVeditor then
										unwrapMod.syncTVSelection()
									
									localEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
									unwrapMod.setTVSubObjectMode 3
									
									
									
									foundSharedEdge = False
									for singleEdge in localEdges do
									(
										sharedEdgeID = (findItem _faceEdges singleEdge)
										--if shared edge arrayID found, store the actual Edge number
										if sharedEdgeID > 0 then
										(
											unwrapMod.selectEdgesByNode (#{singleEdge}) SelectedNode
											--print (singleEdge as string + " selected")
											foundSharedEdge = true
											
											--set to edge mode real quick so that we can use the correct context of UVedgeRing
											unwrapMod.setTVSubObjectMode 2
											if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then
												unwrapMod.uvRing 0
											else
												unwrapMod.geomEdgeRingSelection() 
											
											--print ((unwrapMod.getSelectedEdges()) as array)
											--switch back to face mode and convert the edge selection to face selection
											unwrapMod.setTVSubObjectMode 3
											unwrapMod.EdgeToFaceSelect()
											_newFaces2add = (unwrapMod.getSelectedFacesByNode SelectedNode ) as array
											exit
										)
											
									)
									
										
								--now store proper selections [original edges, and modified faces] into the array 
								CurrObjectSubobjs = SubObjSelectionPair subobjSel3:(join _newFaces2add _faces) subobjSel2:_edges NodeSel:selectedNode
								append FinalSelectionPairs CurrObjectSubobjs
							)
						
						)	
						
						for CurrentSubObjPair in FinalSelectionPairs do
						(
							unwrapMod.SelectFacesByNode (CurrentSubObjPair.subobjSel3 as BitArray) CurrentSubObjPair.NodeSel
							unwrapMod.SelectEdgesByNode (CurrentSubObjPair.subobjSel2 as BitArray) CurrentSubObjPair.NodeSel
						)
						
						FB_quickLoopRingStart = timeStamp()							
					
					)
					else if (CurrSubobjMode == 2) then
					(
						--define a struct for the new subobject selections so we can reselect them easily
						Struct SubObjSelectionPair ( subobjSel2, NodeSel)
						FinalSelectionPairs = #()
						newSelectionPairs = #()
						initSelectionPairs = #()
						
					--Store New selection
						for selectedNode in (selection as array) do
						(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
							testnewEdge = (selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array
							if (testnewedge).count > 2 then
								Throw "More than 1 edge selected"
							--otherwise...
							append newSelectionPairs (SubObjSelectionPair subobjSel2:testnewEdge NodeSel:selectedNode)
							
						)
				--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
						max undo
				--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
						
					--Store old selections
						for iterate = 1 to newSelectionPairs.count do
						(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
							selectedNode = newSelectionPairs[iterate].NodeSel
							append initSelectionPairs (SubObjSelectionPair subobjSel2:((selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array) NodeSel:selectedNode)
						)
						
						
						--now finally start the real loop
						for iterate = 1 to NewSelectionPairs.count do
						(
							newEdge = newSelectionPairs[iterate].subobjSel2
							selectedNode = newSelectionPairs[iterate].NodeSel
							unwrapMod = selectedNode.modifiers[#unwrap_UVW]
							_oldEdges = initSelectionPairs[iterate].subobjSel2
							_addEdges = #()
							foundEdgeMatch = false
							_loopEdges = #()
							_ringEdges = #()
							if (newEdge.count == 0) then
							(
								append FinalSelectionPairs (SubObjSelectionPair subobjSel2:_oldEdges NodeSel:selectedNode)
								continue
							)
							-- Otherwise DO A THROW IF THE SELECTION OVERLAPS WITH PREVIOUS SELECTION AT ALL
							else	if (for i = 1 to newEdge.count where (findItem _oldEdges newEdge[i])>0 collect i).count > 0 then
							(
								print "FB_Quickloopring aborted: Shift+selection overlaps previous selection"
								--if selection count is OVER 1, then it was already caught by a test, but if the selection is only 1 subobject, we have to REDO since we previously undid
											if newEdge.count==1 then actionMan.executeAction 0 "40016"  -- Edit: Redo Scene Operation
								throw "Shift+selection overlaps previous selection"
							)
							
							with redraw off
							(
								--initialize array vars for the sandwiching edgeloops/rings to test against the old selection
								_loopEdges = #()
								_ringEdges = #()
								
								--store both a ring and loop operation to test which one we need to add
								unwrapMod.SelectEdgesByNode (newEdge as bitArray) selectedNode
								
								--If the mouse is within the uv editor window we can assume the user wants a uv-centric edgeloop, so just run uvLoop with a step set to 1, which just grows the loop by 1 on each side
								if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then	
								(
									unwrapMod.uvLoop 1
									_loopEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
								)
								else --Else, the mouse is in the viewport, so do a geometry loop, which takes a few more steps...
								(
									unwrapMod.syncTVSelection()
									unwrapMod.geomEdgeLoopSelection()
									local _tempLoopEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
									
									unwrapMod.SelectEdgesByNode (newEdge as bitArray) selectedNode
									unwrapMod.expandGeomEdgeSelection() 
									local _tempGrowEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
																			
									for adjacentEdge in _tempGrowEdges where (findItem _tempLoopEdges adjacentEdge> 0) do
										append _loopEdges adjacentEdge
								)										
								
									unwrapMod.SelectEdgesByNode (newEdge as BitArray) selectedNode

								--If mouse is within the UV editor window, simply run a uvRing with teh steps set to 1 so itll just grow 1 edge...
								if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then
								(	
									unwrapMod.uvRing 1
									_ringEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
								)
								else --Else, the mouse is in teh viewport, so do a geometry ring, which is harder to find adjacent edges...
								(
									--sync the selection to the viewport so any extra viewport versions of edges will be added and then do a geometry edgeRing
									unwrapMod.syncTVSelection()
									unwrapMod.geomEdgeRingSelection()
									local _tempRingEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
									
									--now that it's stored in a temporary variable for easy comparison, reselect the original edges and expand edges once, then convert to faces and back to edges - this should include all the necessary edges for typical edgerings
									unwrapMod.SelectEdgesByNode (newEdge as bitArray) selectedNode
									unwrapMod.expandGeomEdgeSelection() 
									unwrapMod.edgeToFaceSelect()
									unwrapMod.faceToEdgeSelect()
									local _tempGrowEdges = (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
									
									--now search within these adjacent edges for any that are within teh geometry edgering and store whichever ones exist in both arrays.  This is used as the comparison edge array in the next step
									for adjacentEdge in _tempGrowEdges where (findItem _tempRingEdges adjacentEdge> 0) do
										append _RingEdges adjacentEdge
								)	
								
								--restore original selection for the last time
								unwrapMod.SelectEdgesByNode (newEdge as BitArray) selectedNode
								if Not isMouseInUVeditor then
									unwrapMod.syncTVSelection()
								
								--print newEdge
								--now search through the old edges to find a match with the rings or loops
								for singleEdge in _loopEdges do
								(
									LoopSearch = findItem _oldEdges singleEdge
									if LoopSearch>0 then
									(
										if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then
											unwrapMod.uvLoop 0
										else
											unwrapMod.geomEdgeLoopSelection() 
										
										_addEdges =  (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
										foundEdgeMatch = true
										exit
									)
								)
								for singleEdge in _ringEdges where (foundEdgeMatch == false) do
								(
									RingSearch = findItem _oldEdges singleEdge
									if RingSearch>0 then
									(
										if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then
											unwrapMod.uvRing 0
										else
											unwrapMod.geomEdgeRingSelection() 
										
										_addEdges =  (unwrapMod.getSelectedEdgesByNode selectedNode ) as array
										foundEdgeMatch = true
										exit
									)
								)
							)
						--unwrapMod.SelectEdgesByNode ((join _addEdges _oldEdges) as BitArray) selectedNode
						CurrObjectSubobjs = SubObjSelectionPair subobjSel2:(join _addEdges _oldEdges) NodeSel:selectedNode
						append FinalSelectionPairs CurrObjectSubobjs
						)
						
						--print FinalSelectionPairs
						for CurrentSubObjPair in FinalSelectionPairs do
						(
							unwrapMod.SelectEdgesByNode (CurrentSubObjPair.subobjSel2 as BitArray) CurrentSubObjPair.NodeSel
						)
						
						FB_quickLoopRingStart = timeStamp()
					)
					else if (CurrSubObjMode == 1) then
					(

						--define a struct for the new subobject selections so we can reselect them easily
						Struct SubObjSelectionPair ( subobjSel1,subobjSel2, NodeSel)
						FinalSelectionPairs = #()
						newSelectionPairs = #()
						initSelectionPairs = #()
						
					--Store New selection
						for selectedNode in (selection as array) do
						(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
							testnewEdge = (selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array
							testnewVert = (selectedNode.modifiers[#unwrap_UVW].getSelectedVerticesByNode selectedNode) as array
							
							if (testnewVert).count > 1 then
							(
								--umm try and convert this to geometry verts later and see if they line up, otherwise halt operation because too many verts are selected - maybe marquee?
								if (selectedNode.modifiers[#unwrap_UVW].getSelectedGeomVertsByNode selectedNode as Array).count > 1 then
									Throw "More than 1 vertex selected"
							)
							--otherwise...
							append newSelectionPairs (SubObjSelectionPair SubObjSel1:testnewVert SubObjSel2:testnewEdge NodeSel:selectedNode)
							
						)
				--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
						max undo
				--UNDO THE PREVIOUSLY MADE SELECTION SO WE CAN FIGURE OUT WHAT'S CHANGED
						
					--Store old selections
						for iterate = 1 to newSelectionPairs.count do
						(--do a for loop to error check first, otherwise there's no way to check since we're gonna be undoing stuff
							selectedNode = newSelectionPairs[iterate].NodeSel
							append initSelectionPairs (SubObjSelectionPair SubObjSel1:((selectedNode.modifiers[#unwrap_UVW].getSelectedVerticesByNode selectedNode) as array) SubObjSel2:((selectedNode.modifiers[#unwrap_UVW].getSelectedEdgesByNode selectedNode) as array) NodeSel:selectedNode)
						)
						--now finally start the real loop
						for iterate = 1 to NewSelectionPairs.count do
						(
							print ("currently processing " + newSelectionPairs[iterate].nodeSel.name + " of " +  (NewSelectionPairs.count) as string + " objects")
							_newVert = newSelectionPairs[iterate].subObjSel1
							_oldverts = initSelectionPairs[iterate].subObjSel1
							_origEdgesel =  newSelectionPairs[iterate].subObjSel2
							selectedNode = newSelectionPairs[iterate].NodeSel
							unwrapMod = selectedNode.modifiers[#unwrap_UVW]
							
							_addVerts = #()
							newEdges = #()
							
							if (_newVert.count == 0) then
							(
								append FinalSelectionPairs (SubObjSelectionPair subobjSel1:_oldverts subobjSel2:_origEdgesel NodeSel:selectedNode)
								continue
							)
							-- Otherwise DO A THROW IF THE SELECTION OVERLAPS WITH PREVIOUS SELECTION AT ALL
							else	if (for i = 1 to _newVert.count where (findItem _oldverts _newVert[i])>0 collect i).count > 0 then
							(
								print "FB_Quickloopring aborted: Shift+selection overlaps previous selection"
								--if selection count is OVER 1, then it was already caught by a test, but if the selection is only 1 subobject, we have to REDO since we previously undid
									if _newVert.count==1 then actionMan.executeAction 0 "40016"  -- Edit: Redo Scene Operation
								throw "Shift+selection overlaps previous selection"
							)
							--convert to edges and store for easy comparison
								unwrapMod.selectVerticesbyNode (_oldVerts as BitArray) selectedNode
								unwrapMod.vertToEdgeSelect() 
								_oldEdges = (unwrapMod.getSelectedEdgesbyNode selectedNode) as array
							--add new vert to the initial vert selection
							unwrapMod.selectVerticesbyNode ((MakeUniqueArray (join _newVert _oldVerts)) as BitArray) selectedNode
								--now convert to edges again and compare teh 2 edge selections, leaving you only wit hteh edges that were created from this new selection
								unwrapMod.vertToEdgeSelect() 
								connectedEdges = (unwrapMod.getSelectedEdgesbyNode selectedNode ) as array

							EdgeloopFound = False
							unwrapMod.setTVSubObjectMode 2
							for connectedEdge in connectedEdges where (not EdgeloopFound) do
							(
								foundEdgeID = finditem _oldEdges connectedEdge
								if foundEdgeID<1 then
								(
									unwrapMod.selectEdgesbyNode (#(connectedEdge) as BitArray) SelectedNode
									if isMouseInUVeditor And ((maxVersion())[1] >= 12000) then
										unwrapMod.uvLoop 0
									else
										unwrapMod.geomEdgeloopSelection()
									EdgeloopFound = true
						
									newEdges = (unwrapMod.getSelectedEdgesbyNode selectedNode) as array
									if newEdges.count>1 then
									(
										EdgeloopFound = true
										unwrapMod.EdgeToVertSelect()
										_addVerts = (unwrapMod.getSelectedVerticesByNode selectedNode ) as array
									)
								)
							)
							--if no edgeloop was found in UVspace, try Worldspace in the viewport
							if Not edgeloopFound then
							(
								--print "no vertloop found"
							)
							
							--set back to vertex mode, set selection to add the vert-loop to the original vertex selection, and reset the edge selection to the initial values
							unwrapMod.setTVSubObjectMode 1
							
							CurrObjectSubobjs = SubObjSelectionPair subobjSel1:(join _addVerts _oldVerts) subobjSel2:_origEdgesel NodeSel:selectedNode
							append FinalSelectionPairs CurrObjectSubobjs

						)
						
						--print FinalSelectionPairs
						for CurrentSubObjPair in FinalSelectionPairs do
						(
							unwrapMod.SelectVerticesByNode (CurrentSubObjPair.subobjSel1 as BitArray) CurrentSubObjPair.NodeSel
							unwrapMod.SelectEdgesByNode (CurrentSubObjPair.subobjSel2 as BitArray) CurrentSubObjPair.NodeSel
						)
					
					)
				)
				if (currModifierType == skin) then
				(
					--currently only works with single skin modifiers, because that's all I use and it could get slow since there's no nice vert selection setup for skinOps
					if selection.count==1 then
					(
						numVerts = skinOps.GetNumberVertices( $.modifiers[#skin])
						skinMod = $.modifiers[#skin]
						initVertSelection = #()
						newVertSelection = #()
						connectedVerts = #()
						finalVertAddition = #()
						
						--store current NEW skinvert selection
						for iterate=1 to numVerts where (skinOps.IsVertexSelected skinMod iterate)==1 do
							(append newVertSelection iterate)
						
						--error out if the user has selected more than 1 skinvert [likely due to marquee selection]
						if newVertSelection.count>1 do
							throw "More than 1 new vert was selected"
						
						--Undo so we can store previous skinvert selection
						max undo
						for iterate=1 to numVerts where (skinOps.IsVertexSelected skinMod iterate)==1 do
							(append initVertSelection iterate)
						
						--make sure more than 0 verts newly selected, and make sure the selection isn't the same now as it was in the last step
						if (newVertSelection.count == 0) Or  (newVertSelection.count == initVertSelection.count AND (for i = 1 to newVertSelection.count where newVertSelection[i]!=initVertSelection[i] collect i).count == 0) then
						(
							actionMan.executeAction 0 "40016" --redo 
							--no need to redo since the selection is the same or null
							throw "Error occurred resumed selection"
						)
						
						with redraw off
						(
							--store an expanded selection to compare as edgeloops
							skinOps.growSelection $.modifiers[#Skin]
							for iterate=1 to numVerts where ((skinOps.IsVertexSelected skinMod iterate)==1 and Not iterate == newVertSelection[1]) do
								(append connectedVerts iterate)
							
							
							
							for SkinVert in initVertSelection do
							(
								skinVertID = findItem connectedVerts SkinVert
								if skinVertID >0 then
								(
									skinOps.SelectVertices skinMod #(newVertSelection[1], connectedVerts[skinVertID])
									skinOps.loopSelection $.modifiers[#Skin]
									
									--now...
									for iterate=1 to numVerts where (skinOps.IsVertexSelected skinMod iterate)==1 do
									(	append finalVertAddition iterate)
									if finalVertAddition.count<=2 then
										finalVertAddition = #()
									else
										exit
								)
							)
						)
						
						--finally apply new selection
						skinOps.SelectVertices skinMod (join initVertSelection finalVertAddition)
					)
					--else don't bother, multiple modifiers are a pain to deal with in skinOps.  I think avoiding it all together will make the script more elegant... but if someone wants it, however slow it may be, I could add it.
				)
			)
		)catch()
		completeRedraw()
		
		--used to use a timer but that's lame
		FB_quickLoopRingStart = timeStamp()	
	)
	FB_quickLoopRingWorking = false
)


--makes a callback for EVERY TIME your subobject selection changes, and runs the function above whenever that happens.
--The function itself just checks to see if you're on a unwrapUVW modifier, and if so it'll try and do this thing

callbackItem = NodeEventCallback mouseUp:true delay:10 subobjectSelectionChanged: FB_quickLoopRing


--the variable: callbackItem was used to store the callback instance,
--TO REMOVE this while max is running, use the following 2 lines:--
/*

				callbackItem = undefined
				gc light:true

*/
