Notifications
Clear all

[Closed] Fastest Attach – Collaborative Tool by CGS members

Hi, I think it would be an interesting experiment to see if we here at CGS could try collaborating on making a full “maxscript tool” together, because I was really impressed by the previous thread and the collaborating effort, speed of development and amazing results I think If we would collaborate and use everybody’s different strengths and knowledge, we should be able to create some amazing stuff.

To kick it off I started on making the tool: Fastest Attach (inspired by the previous thread)

Objective:
– Create the fastest attach tool possible
– Have it be stable/reliable
– Easy To use

Rules:
– Anyone can contribute, Ui improvements, speed improvements, streamline of code, etc

I[/I]
V0.11

-- Fastest Attach v0.11
-- Patrik Fröhler
-- 2017-03-08
-- Collaboration script tool

global fastestAttach
global fastestAttachWindow
global fastestAttachDB

if fastestAttachWindow != undefined then (
	if fastestAttachWindow.ui != undefined then (
		DestroyDialog  fastestAttachWindow.ui
	)
)

(
	DB
	sRo
	sfn
	bfn
	
	struct sDB -- DATABASE
	(
		targetObj, 
		attachObj,
		tmpMesh,
		algorithmSelected
	)

	struct sRo -- UI
	(
		Ui,
		/* #ui.2 | Main Ui */
		fn MainRo = (
			rollout uiFastestAttach "Fastest Attach v0.11" width:256 height:275
			(  -- ! TODO ! >> Fix so bitmaps load from URL
				local hBitmap =  (openBitMap  @"http://www.patan77.com/fastest_attach/fastest_attach_header_03.png")
				local m1Bitmap =  (openBitMap @"http://www.patan77.com/fastest_attach/fastest_attach_m01.png")
				local m1BitmapH =  (openBitMap @"http://www.patan77.com/fastest_attach/fastest_attach_m01_hover.png")
				local fBitmap =  (openBitMap @"http://www.patan77.com/fastest_attach/fastest_attach_footer_01.png")
				
				imgTag img_header bitmap:hBitmap align:#center offset: [0,-5]  transparent:[255,0,255]
				imgTag img_m1 bitmap:m1Bitmap align:#left offset: [-10,-5]  transparent:[255,0,255]
				pickbutton pbtn_target "Pick --> Target Object" tooltip:"Select object to attach to" width:256 height:25 offset: [0,0] 
				button btn_attach "Select [ ] Source Objects" width:256 tooltip:"Select object you want to attach" height:25
				radiobuttons rbtn_algorithm labels:#("Pflow", "kFast") default:1
				imgTag imgfooter bitmap:fBitmap align:#center  transparent:[255,0,255] offset: [0,-5] 
				label lb_status ""
					
				on pbtn_target picked obj do (
					if obj != undefined then (
						DB.targetObj = obj
						pbtn_target.text = obj.name
						pbtn_target.tooltip = "Rightclick to clear."
						sfn.fn_setStatusBar "" --> #s.8
					)
				)
									
				on pbtn_target rightclick do (
					DB.targetObj = undefined
					pbtn_target.text =  "Pick --> Target Object" 
					pbtn_target.tooltip = "Select main object you want to attach to."
					sfn.fn_setStatusBar "" --> #s.8
				)
				
				on btn_attach pressed do (
				--	selectByName() -- ! TODO ! >> ADD Filter to hide DB.targetObj in the selection list 
					actionMan.executeAction 0 "50029"  -- Selection: Select By Name
					if $ != undefined then (
						DB.attachObj = (selection as array)
						btn_attach.text = ((DB.attachObj[1].name as string) + "...")
						btn_attach.tooltip = "Rightclick to clear."
						sfn.run()  --> #s.1
					)
				)
				
				on btn_attach rightclick do (
					DB.attachObj = undefined
					btn_attach.text = "Select [ ] Source Objects"
					btn_attach.tooltip = "Select object you want to attach."
				)
				
				on img_m1 mouseover do (
					img_m1.bitmap = m1BitmapH
				)
				
				on img_m1 click  do (
					ShellLaunch "www.patan77.com" ""
				)
				
				on img_m1 mouseout do (
					img_m1.bitmap = m1Bitmap
				)
				
				on changed state do (
					DB.algorithmSelected = state
				)
			)
		),
		
		/* #ui.1 | Create Main Ui  */
		fn run = (
			Ui = sRo.MainRo() --> #ui.2
			Createdialog Ui bgcolor:[68,68,68]
		)
	)

	struct sfn -- FUNCTIONS
	(
		/* #s.10 | Convert To edit poly */
		fn fn_convertTOPoly inArr = (
			for i in inArr do (
				if classof i != Editable_Poly then (
					converttopoly i
				)
			)
			return inArr
		),
		
		/* #s.9 | Fast attach  */
		fn fn_kFast_attach inArr = (
			sfn.fn_convertTOPoly inArr--> #s.10
			local k = 1
			attach = polyop.attach
			while nodes.count > 1 do
			(
				k += 1
				attach nodes[k-1] nodes[k]
				deleteItem nodes k
				if k >= nodes.count do k = 1
			)
			DB.tmpMesh = inArr[1]
		),
		
		/* #s.8 | Set StatusBar Text */
		fn fn_setStatusBar inString = (
			fastestAttachWindow.ui.lb_status.text = inString
		),
		
		/* #s.7 | Reset Script */
		fn fn_resetScript = (
			DB.targetObj = undefined
			DB.attachObj = undefined
			DB.tmpMesh = undefined
			fastestAttachWindow.ui.pbtn_target.text = "Pick --> Target Object" 
			fastestAttachWindow.ui.pbtn_target.tooltip = "Select object to attach to."
			fastestAttachWindow.ui.btn_attach.text = "Select [ ] Source Objects." 
			fastestAttachWindow.ui.btn_attach.tooltip = "Select object you want to attach."
		),
		
		/* #s.6 | Check if Source and Target Object exist*/
		fn fn_chk_sourceTarget = (
			if DB.targetObj != undefined then (
				if DB.attachObj != undefined then (
					return true
				)else(
					messageBox "Please select Source Objects." 
					sfn.fn_setStatusBar "No Source Objects selected." --> #s.8
				)
			)
			messageBox "Please select Target Object." 
			sfn.fn_setStatusBar "No Source Objects Taget." --> #s.8
			return false
		),
		
		/* #s.5 | Create Pflow */
		fn fn_pflow = (
			local currentSliderTime 
			-- ! TODO ! >> Fix pCont.particleScale
			local pfScript = 
			("
				on ChannelsUsed pCont do
				(
					pCont.useShape = true
					pCont.useScale = true
					pCont.usePosition = true
					pCont.useOrientation = true
				)
				on Proceed pCont do 
				(
					count = pCont.NumParticles()
					for i in 1 to count do
					(
						pCont.particleIndex = i
						pCont.particleShape = fastestAttachDB.attachObj[ i ].mesh
						-- pCont.particleScale = fastestAttachDB.attachObj[ i ].scale
						pCont.particlePosition = fastestAttachDB.attachObj[ i ].pos
						eR = (quatToEuler fastestAttachDB.attachObj[ i ].rotation)
						pCont.particleOrientation = [eR.x,eR.y,eR.z]
					)
				)
			")
			local pf = PF_source Quantity_Viewport:100 Particle_Amount_Limit:1000000
			ParticleFlow.BeginEdit()
			pf.AppendAction (RenderParticles())
			local e1 = Event name:"pfTempEvent"
			e1.AppendAction (Birth Amount: (DB.attachObj.count) Emit_Start:0 Emit_Stop: 0)
			e1.AppendAction (Script_Operator Proceed_Script: pfScript)
			e1.AppendAction (DisplayParticles type:6)
			ParticleFlow.EndEdit()
			pf.appendInitialActionList e1
			local m = Mesher()
			m.pick = pf
			DB.tmpMesh = (snapshot m)
			particleFlow.BeginEdit()
			particleFlow.delete $'pfTempEvent'
			particleFlow.EndEdit()
			delete m 	
			delete pf
		),
		
		/* #s.4 | Check if object mesh or poly  */
		fn fn_checkIfMeshPoly inObject = (
			if classof inObject != Editable_Poly then (
				if classof inObject != Editable_Mesh then (
					local alert = (queryBox ("Do you want to convert " + (DB.targetObj.name as string) + " to Edit poly"))
					if alert then (
						converttopoly DB.targetObj
					)else(
						return false
					)
				)
			)
			return true
		),
		
		/* #s.3 | Attach Function */
		fn fn_attach = (
			if (sfn.fn_checkIfMeshPoly DB.targetObj) then (  --> #s.4
				local timeStart = timestamp()
				sfn.fn_setStatusBar "Running: Fastest Attach" --> #s.8
				case DB.algorithmSelected of
				(
					1: sfn.fn_pflow() --> #s.5
					2: sfn.fn_kFast_attach() --> #s.9
				)
				if classof DB.targetObj == Editable_Poly then (
					polyop.attach DB.targetObj DB.tmpMesh
				)else(
					meshop.attach DB.targetObj DB.tmpMesh
				)
				delete DB.attachObj
				sfn.fn_setStatusBar ("Done: Fastest Attach " + (((timestamp() - timeStart)/1000.0) as string) + " sec") --> #s.8
				sfn.fn_resetScript() --> #s.7
			)else(
				messageBox "Attach Canceled"
				sfn.fn_setStatusBar "Attach Canceled" --> #s.8
			)
		),
		
		/* #s.2 | sfn Script */
		fn script = (
			sfn.fn_initiate() -->  #s.0
			sfn.fn_attach() -->  #s.3
		),
		
		/* #s.1 | sfn Run */
		fn run = (
			gc()
			with redraw off(
				with undo off(
					sfn.script() --> #s.2
				)
			)
			gc()
		),
		
		/* #s.0 | sfn initiate DB values */
		fn fn_initiate = (
			DB.algorithmSelected = 1
		)
	)
	
	/* #1 | Main Build  */
	struct bfn 
	(
		fn build = (
			with undo false
			(
				fastestAttachWindow.run() --> #ui.1
			)
		)
	)
	
	DB = sDB()
	fastestAttach = bfn()
	fastestAttachWindow = sRo()
	fastestAttachDB = DB
	ok
)
fastestAttach.build() --> #1
  • Radio-buttons
  • kFast attach algorithm

– Older versions:
#0.1

Thanks & good luck.

5 Replies

First obvious thing needed to get fixed are the ability to load the Ui images from web url,
( I think it probably need like dotnet WebRequest or something? )

graphics are missing…but that’s not important.

after I selected the ‘Target’, then to select the Source, the list pops up, it should Exclude the Target itself (if possible)

So if I ‘know’ not to include the Target, it works great…but if I inadvertently include the Target…it won’t work, obviously it can’t attach it to itself…

Thanks again.

have 1 object,

pick that as Target, select Source…pick Target itself

Poooooof…gone !!! Damn fast too !!!

have a closed shape, Circle say…create a few more circles, Rectangles whatever

Target: 1st Circle
Source: rest of shapes

It asks if want to convert to Poly…sure, great, go ahead

Only 1st shape remains (which is now Poly), all others gone.

Thanks for your bug reporting.