Vertex script no longer compatible in 3ds max 2009

This script works well in 3ds max 9 even though I'm sure has some wrongs in it. It attaches an animated box linked on each animated selected vertex.

In 3ds max 2009 it creates the boxes, but they are linked to random vertices not to the selected ones.

How can I make it compatible to 3ds max 2009+ ?

for i = 1 to $.selectedVerts.count do 
		(
		    box name:("bake_" + ($.selectedVerts[i] as string)) position:((getVert $ i) + [0,0,-.02]) length:1 width:1 height:1
                         )
		    for i = (animationrange.start as integer) to (animationrange.end as integer) do
		       (
			with animate on
			    (
				slidertime = i
				if currentTime == 188f do exit
				for m = 1 to $.selectedVerts.count do
				   (
				       (execute ("$'"+"bake_" + $.selectedVerts[m] as string + "'")).pos = (getVert $ m)
 
				    )
 
		                  )
		       )

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
sebastian___'s picture

Thank you again for your

Thank you again for your efforts. About your advice, I spend hours reading that manual and trying, but I guess I need to upgrade my scripting skill level :)

Unfortunately it still doesn't work. I tried to debug it myself with no luck. The last script is way above my head.

If I don't select any vertex it gives me the message box "You need to select some verts first!" and it doesn't throw any red errors. But if I select some verts in an edit mesh mod it gives me this : 

-- Error occurred in collectVertsPos(); filename: ; position: 613
-- Frame:
-- selVerts: undefined
-- vertsIdxArr: #{131..132, 143..144, 310..311}
-- tmpArr: #()
-- obj: $Box01
-- modif: Edit_Mesh:Edit Mesh
-- called in anonymous codeblock
-- Frame:
-- animObj: $Box01
-- End: undefined
-- selVerts: #{131..132, 143..144, 310..311}
-- start: undefined
-- size: undefined
-- curmod: Edit_Mesh:Edit Mesh
-- boxarr: undefined
-- checkClass: Edit_Mesh
-- idx: 1
-- collectVertsPos: collectVertsPos()
-- vertsPosArr: undefined
-- No "map" function for undefined

barigazy's picture

Try this one


clearlistener()
 if selection.count != 1 then messagebox "Select an animated object with EPolyMod or EMeshMod on top!" title:"Bake Boxes" beep:false else
 (
	animObj = selection[1]
	curMod = if animObj.modifiers[#Edit_Poly] == undefined then animObj.modifiers[#Edit_Mesh] else animObj.modifiers[#Edit_Poly]  	
	if curMod != undefined do
	(
		fn collectVertsPos vertsIdxArr obj:animObj modif:curMod = 
		(
			local tmpArr = #()
			for v in vertsIdxArr do 
			(
				case classof modif of (
					(Edit_Poly): append tmpArr (modif.GetVertex v)
					(Edit_Mesh): append tmpArr (getVert obj v)
				)
			) ; tmpArr			
		)
		local checkClass = classof curMod
		local idx = finditem animObj.modifiers curMod
		if getCommandPanelTaskMode() != #modify do setCommandPanelTaskMode mode:#modify
		modPanel.setCurrentObject animObj.modifiers[idx] ; subObjectLevel = 1
		--if this don't works try to replace in next line: (getVertSelection animObj curMod) with (animObj.selectedverts as bitarray)
 
		local selVerts = if checkClass == Edit_Poly then (curMod.getSelection #Vertex) else if checkClass == Edit_Mesh do (getVertSelection animObj curMod)
		if selVerts.numberset == 0 then (messagebox "You need to select some verts first!" title:"Bake Boxes" beep:false) else
		(
			local vertsPosArr = collectVertsPos selVerts
			local start = animationrange.start, end = animationrange.end, size = 1
			if not currentTime == start do currentTime = start
 
			boxarr = for i in 1 to selVerts.numberset collect  
			(
				boxPos = vertsPosArr[i] - [0,0,size/2.0]
				box name:("bakeBox_vert"+(i as string)) length:size width:size height:size pos:boxPos wirecolor:yellow
			)	
			for t = start to end do
			(
				--uncomment the line "slidertime = t" and delete "at time t" if you want to se realtime preview in viewport (but this is slow solution and is not recommended)
				with animate on at time t 
				(
					--slidertime = t 
					vertsPosArr = collectVertsPos selVerts
					for b = 1 to boxarr.count do boxarr[b].pos = vertsPosArr[b] - [0,0,size/2.0]
				)
			)
			--uncomment next line if you want to select newly created boxes
			--select boxarr
			free vertsPosArr ; free boxarr
		)
	)	
)	

bga

sebastian___'s picture

Thank you, now it's working.

Thank you, now it's working.

barigazy's picture

#4 question

Q: ...That's the same result I got with the old script. Perhaps a bug in 3ds max 2009?
It's not a buq. Edit_Poly Modifier use different functions (methods)
than Editable_Poly object. But this is not a case with Edit_Mesh
Modifier and Editable_Mesh (simply mesh) object.
But in every way max2009 is not max2012 :).
You probably have some more questions, but my suggestion is
read MXS HELP to see differences and find more answers than I can give you.
Cheers man!

bga

barigazy's picture

#3 question

Q: ...I would want to see the script update every frame, what should I change ?
Rather than use a method that is faster:
... with animate on at time t ...
you want to use this:
... with animate on (sliderTime = t) ...
Unnecessarily slowing the whole process, which is usually slow.
Think about that.

bga

barigazy's picture

#2 question

Q: If I would want to eliminate this : local start = 0f, end = 188f and just have the script perform for the lenght of timeline ? What should be changed?
In the new code you'll see what i changed
Just replace with this

start = animationrange.start
end = animationrange.end


Or you can set any time range (interval)

bga

barigazy's picture

#1 question

Q: I forgot to mention that it's important this script should perform with a modifier on top - like edit mesh, edit poly or select poly.
The solution with modifiers is slower then previous that i posted.
I recreate the code and now supports EditPoly or EditMesh Modifier only. I think that's the all that you need.

 clearlistener()
 if selection.count != 1 then messagebox "Select an animated object with EPolyMod or EMeshMod on top!" title:"Bake Boxes" beep:false else
 (
	animObj = selection[1]
	curMod = if animObj.modifiers[#Edit_Poly] == undefined then animObj.modifiers[#Edit_Mesh] else animObj.modifiers[#Edit_Poly]  	
	if curMod != undefined do
	(
		fn collectVertsPos vertsIdxArr obj:animObj modif:curMod = 
		(
			local tmpArr = #()
			for v in selVerts do 
			(
				case classof modif of (
					(Edit_Poly): append tmpArr (modif.GetVertex v)
					(Edit_Mesh): append tmpArr (getVert obj v)
				)
			) ; tmpArr			
		)
		local checkClass = classof curMod
		local idx = finditem animObj.modifiers curMod
		if getCommandPanelTaskMode() != #modify do setCommandPanelTaskMode mode:#modify
		modPanel.setCurrentObject animObj.modifiers[idx] ; subObjectLevel = 1
		local selVerts = if checkClass == Edit_Poly then (curMod.getSelection #Vertex) else if checkClass == Edit_Mesh do (getVertSelection animObj curMod)
		if selVerts.numberset == 0 then (messagebox "You need to select some verts first!") else
		(
			local vertsPosArr = collectVertsPos selVerts
			local start = animationrange.start, end = animationrange.end, size = 1
			if not currentTime == start do currentTime = start
 
			boxarr = for i in 1 to selVerts.numberset collect  
			(
				boxPos = vertsPosArr[i] - [0,0,size/2.0]
				box name:("bakeBox_vert"+(i as string)) length:size width:size height:size pos:boxPos wirecolor:yellow
			)	
			for t = start to end do
			(
				--uncomment the line "slidertime = t" and delete "at time t" if you want to se realtime preview in viewport (but this is slow solution and is not recommended)
				with animate on at time t 
				(
					--slidertime = t 
					vertsPosArr = collectVertsPos selVerts
					for b = 1 to boxarr.count do boxarr[b].pos = vertsPosArr[b] - [0,0,size/2.0]
				)
			)
			--uncomment next line if you want to select newly created boxes
			--select boxarr
			free vertsPosArr ; free boxarr
		)
	)	
)	

bga

sebastian___'s picture

WOW Great. Thank you.I

WOW Great. Thank you.

I wondered how could I make the boxes name shorter because they were very long, and you did that.

I forgot to mention that it's important this script should perform with a modifier on top - like edit mesh, edit poly or select poly.
And I noticed it works with Edit Mesh on top, manages most of the vertices right, but misses some and also places some boxes on top of unselected vertices. In my old testings I also did see the same errors.
Here is a gif animation with the error
http://www.scriptspot.com/files/vertex_boxes_2.gif

-------
If I would want to eliminate this : local start = 0f, end = 188f and just have the script perform for the lenght of timeline ? What should be changed ?

-------
Also I realize that having a script perform faster is something skilled scripters manage to achieve and this script is almost instant while on my old script I had to reduce the length of frames if I had many tests, because it could take so long. However if I would want to see the script update every frame, what should I change ? But this is not something important for me.

-----
UPDATE
Unfortunately I tested again with a simple box with both Editable Poly and Editable Mesh and it's not working. I select a bunch of vertices on a side, execute the script, and a bunch of boxes get created on the floor, instead of the side. That's the same result I got with the old script. Perhaps a bug in 3ds max 2009 ?
Do I need to install some ServicePack for max ?

AttachmentSize
vertex_boxes.gif 14.3 KB
barigazy's picture

Works now :)


if selection.count != 1 then messagebox "Select an animated Epoly or EMesh object!" title:"Bake Boxes" beep:false else
(
	local obj = selection[1]
	local selVertsBitarr = obj.selectedVerts as bitarray
	if selVertsBitarr.numberset != 0 do
	(
		local start = 0f, end = 188f, size = 1
		if not currentTime == start do currentTime = start
		if getCommandPanelTaskMode() != #create do setCommandPanelTaskMode mode:#create
		local getVertPos = if iskindof obj Editable_Poly then polyOp.getVert else if iskindof obj Editable_Mesh do meshOp.getVert
		boxarr = for i in selVertsBitarr where iskindof obj Editable_Poly or iskindof obj Editable_Mesh collect  
		(
			boxPos = (getVertPos obj i) - [0,0,size/2.0]
			box name:("bakeBox_vert"+(i as string)) length:size width:size height:size pos:boxPos wirecolor:yellow
		)	
		for i = animationrange.start to animationrange.end where i <= end do
		(
			with animate on at time i (for b = 1 to boxarr.count do boxarr[b].pos = (getVertPos obj b) - [0,0,size/2.0])
		)
		--uncomment next line if you want to select newly created boxes
		--select boxarr
	)
)

bga

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.