/*
Using single one hotkey of Attach/Detach. Works with:
Edit Poly
Editable poly
Edit mesh
Editable mesh
Edit Spline modifer
SplineShape
line
UnwrapUVW

 Script: UniAttach-Detacher
 Author: Nikolay Litvinov
 Created in the 3dsMax 2016
*/
messagebox "category:\"Niklit Scripts\"\nIf button ResetMtl pressed with Ctrl then assign one color to several objects\nIf button pressed with Esc then will select by color"
macroScript UniAttach Category:"Niklit Scripts" Tooltip:"UniAttach"
(
------------------------ FUNCTIONS ------------------------

fn MultiAttach_Spl_fn=
(
spl_ar=for i in selection where IsShapeObject i collect (convertToSplineShape i);
for i=2  to spl_ar.count do addandweld spl_ar[1] spl_ar[i] 0.002
)

fn MultiAttach_Geometry_fn = (
armesh=for s in selection where superclassof s == GeometryClass collect (converttopoly s)
for i=2 to armesh.count do (armesh[1]).attach armesh[i] armesh[1]
)

fn AttachMul_fn = (
	arO = for o in selection collect superclassof o
	if (findItem arO GeometryClass)==0 
	then with redraw off MultiAttach_Spl_fn()
	else MultiAttach_Geometry_fn()
)

fn WeldBorder_fn fco=
(
Num1=fco.getNumVertices()
if subobjectlevel==2 then fco.ConvertSelection #Edge #Vertex
if subobjectlevel==3 then fco.ConvertSelection #Border #Vertex
if subobjectlevel==4 or subobjectlevel==5 then fco.ConvertSelection #Face #Vertex
try fco.ButtonOp #WeldVertex catch (polyop.weldVertsByThreshold $ (polyop.getVertSelection $))
Num2=fco.getNumVertices()
Num1!=Num2
)

fn EPoly_Attach_fn fco= (
if ((subobjectlevel==4 or subobjectlevel==5) and not(fco.getselection #Face).isEmpty) or (subobjectlevel==1 and not(fco.getselection #Vertex).isEmpty) or (subobjectlevel==3 or subobjectlevel==2) and not(fco.getselection #Edge).isEmpty
then if not WeldBorder_fn fco do macros.run "Editable Polygon Object" "EPoly_Attach"
)
------------------------ SCRIPT ------------------------

 if getCommandPanelTaskMode() != #modify then (max modify mode)
local gco = modPanel.getCurrentObject()
if selection.count > 1
then AttachMul_fn()
else
 Case classOf gco of
				(
	   Edit_Poly:	EPoly_Attach_fn gco
   Editable_poly:	EPoly_Attach_fn gco
	   Edit_mesh:	macros.run "Editable Mesh Object" "EMesh_Attach"
   Editable_mesh:	macros.run "Editable Mesh Object" "EMesh_Attach"
   	 		line:	macros.run "Editable Spline Object" "ESpline_Attach"
	 SplineShape:	macros.run "Editable Spline Object" "ESpline_Attach"
	 Edit_Spline:	macros.run "Editable Spline Object" "ESpline_Attach"
	  unwrap_uvw:	gco.stitchVertsDialog()
				)
	)
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------

macroScript UniDetach Category:"Niklit Scripts" Tooltip:"UniDetach"
(
global ResetMtl_UniDetach, Sel_LastObj
if ResetMtl_UniDetach==undefined do ResetMtl_UniDetach=false
if Sel_LastObj==undefined do Sel_LastObj=false
------------------------ FUNCTIONS ------------------------
fn ResetWirecolor_fn = try ($.wirecolor = color (random 0 255) (random 0 255) (random 0 255); if $.material!=undefined do $.material=undefined) catch()

fn SelLastCrObj_fn = select (maxOps.getNodeByHandle (amax (for i in objects collect i.inode.handle)))

fn DetachToElements obj num:1 =
		while obj.getNumFaces() != 0 do (
			polyop.setFaceSelection obj #{1}
			obj.selectElement()
			ele = polyop.getFaceSelection obj
			newName = num as string
			num += 1 -- pump up counter
			polyop.detachFaces obj ele asNode:true name:newName
		)

fn Explode_El_to_Objects=
(
obj0=objects as array
cur=$
	n=0
 while(getFaceSelection $.mesh).numberset != 0
	do(
		El = polyOp.getElementsUsingFace $ #{1}
		polyOp.detachFaces $ El asNode:true name: (uniqueName (""+$.name as string))
		select cur
		n+=1
	  )

	if n==1 then (max undo; macros.run "Editable Polygon Object" "EPoly_Detach")
	

	else (
	delete $

	Exploded_objects = for i in objects where findItem obj0 i == 0 collect i
	for i in Exploded_objects do 
	(centerPivot i; worldAlignPivot i; i.wirecolor = color (random 0 255) (random 0 255) (random 0 255))
	 select Exploded_objects[1]
	)

)
fn U_detach_fn fco=
try fco.DetachToObject selection[1].name
catch polyop.detachFaces $ (polyop.getFaceSelection $) delete:true asNode:true name: $.name --node:$

fn so4_opEP_fn fco=(numobj=objects.count
	numV0=$.GetNumVertices()
	if getNumFaces $.mesh==(getFaceSelection $.mesh).numberset 
	then 
		if keyboard.escPressed 
		then (convertToMesh $; meshOps.explode $)
		else Explode_El_to_Objects()
	else
		(
			U_detach_fn fco
	 		if numobj!=objects.count or $.GetNumVertices()!=numV0 do
	 		(
	 		if Sel_LastObj do SelLastCrObj_fn()
	 		if ResetMtl_UniDetach do ResetWirecolor_fn()
	 		)
	 	)
	)

fn numvert_fn=(sum=0; for i in (for i in selection collect numPoints i) do sum=sum+i; sum)
/*
fn so4_opEPmod_fn fco = (
	(Btn_hwnd=for i in windows.getChildrenHWND #max where i[5]=="Detach" do exit with i[1]; UIAccessor.PressButton Btn_hwnd)
	if ResetMtl_UniDetach do (ResetWirecolor_fn())
 	)
*/

fn createShapeFromEdges_fn=(try (polyop.createShape $ (getEdgeSelection $))
catch (Btn_hwnd=for i in windows.getChildrenHWND #max where i[5]=="Create Shape" do exit with i[1]; UIAccessor.PressButton Btn_hwnd)
select (maxOps.getNodeByHandle (amax (for o in objects collect o.inode.handle)))
$.pivot=$.center)

fn explodeSpl_fn=(
s0=$
for i=1 to numsplines $ do
(
	maxOps.cloneNodes s0 cloneType:#copy newNodes:&nnl
	select nnl
	subobjectlevel=3
	setSplineSelection $ #(i)
	actionMan.executeAction 0 "40044"  -- Selection: Select Invert
	max delete
)
delete s0
subObjectLevel=0
max select
)

------------------------ SCRIPT ------------------------
if subobjectlevel!=undefined or subobjectlevel!=0 
then (
 if getCommandPanelTaskMode() != #modify then max modify mode
 local gco = modPanel.getCurrentObject()
 	case classOf gco of
	(
	Unwrap_UVW: gco.breakSelected()
Editable_poly:	Case subobjectLevel of
				(
				 1: macros.run "Editable Polygon Object" "EPoly_VBreak"
				 2: $.EditablePoly.splitEdges ()
				 3: createShapeFromEdges_fn()
				 4: so4_opEP_fn gco
				 5: if (getFaceSelection $.mesh).isEmpty then DetachToElements $ else so4_opEP_fn gco
				)
	Edit_Poly:	Case subobjectLevel of
				(
				 1: gco.SetOperation #BreakVertex
				 2: gco.ButtonOp #SplitEdges
				 3: createShapeFromEdges_fn()
				 4: U_detach_fn gco
				 5: if (getFaceSelection $.mesh).isEmpty then DetachToElements $ else so4_opEP_fn gco
				)
	Edit_mesh:	if subObjectLevel==1 
	 			then macros.run "Editable Mesh Object" "EMesh_VBreak"
				else macros.run "Editable Mesh Object" "EMesh_Detach"
Editable_mesh:	if subObjectLevel==1
	 			then macros.run "Editable Mesh Object" "EMesh_VBreak"
				else macros.run "Editable Mesh Object" "EMesh_Detach"
	   line: Case subobjectLevel of
				(
				 1:	macros.run "Editable Spline Object" "ESpline_Break"
				 2: (macros.run "Editable Spline Object" "ESpline_Detach_Segment"
				 UIAccessor.PressDefaultButton())
				 3: (macros.run "Editable Spline Object" "ESpline_Detach_spline"
				 UIAccessor.PressDefaultButton())
				)
SplineShape: Case subobjectLevel of
				(
				 1: macros.run "Editable Spline Object" "ESpline_Break"
				 2: (macros.run "Editable Spline Object" "ESpline_Detach_Segment"
				 UIAccessor.PressDefaultButton())
				 3: (
				if (GetSplineSelection $).count==numsplines $ 
				then explodeSpl_fn()
					else(
					 	macros.run "Editable Spline Object" "ESpline_Detach_spline"
						UIAccessor.PressDefaultButton()
						)
				 	)
				)
Edit_Spline: Case subobjectLevel of
			(
			 1: splineOps.startBreak gco	
			 2: (splineOps.detach gco
			 	UIAccessor.PressDefaultButton())
			 3: (
			 	splineOps.detach gco
			 	UIAccessor.PressDefaultButton()
			 	)
			)
	)
)
else
(sel0=selection as array
maxOps.cloneNodes $ cloneType:#copy newNodes:&nnl
hide sel0
select nnl)

)


macroScript UniDetach_ResetMtl_macro Category:"Niklit Scripts" Tooltip:"UniDetach ResetMtl"
icon:#("Material_Modifiers",3)
(
	global ResetMtl_UniDetach
	on ischecked return ResetMtl_UniDetach
	on Execute do (
		ResetMtl_UniDetach = if ResetMtl_UniDetach != true then true else false

	if subobjectlevel==0 or subobjectlevel==undefined do	(
		-------------------FUNCTIONS-------------------
			fn ResWC =(try(
				$.material=undefined
				$.wirecolor = (color (random 0.0 255) (random 0.0 255) (random 0.0 255)))Catch()
				)
		-------------------SCRIPTS-------------------
			sel=selection as array
			if keyboard.EscPressed then actionMan.executeAction 0 "40109" -- Edit: Select By Color
				else
			if selection.count == 1 
				then ResWC()
					else
			if keyboard.ShiftPressed then ResWC()
			else
			 (
				for k in sel do
				try(k.material=undefined
					k.wirecolor = (color (random 0.0 255) (random 0.0 255) (random 0.0 255))) catch()
			select sel
			)
			redrawViews()
		 )
	)
)


macroScript UniDetach_Sel_LastObj Category:"Niklit Scripts" Tooltip:"Detach SelLastObj Switcher"
icon:#("enss_tools",9)
(
	global Sel_LastObj
	on ischecked return Sel_LastObj
	on Execute do Sel_LastObj = if Sel_LastObj != true then true else false
)