Notifications
Clear all

[Closed] SubAnim RCMenu? How?

Is there a standard SubAnim RCMenu (like Wire Parameters or Reaction Manager -> Pick Master/Slave (see below)?

I’ve made one but the code is UGLY!

fn FixName str = 
 (
 	pStr = filterString str " .+-/=,;:\"[]{}!@#$%^&*()"
 	
 	sStr = ""
 	
 	for s in pStr do
 		sStr += s
 		
 	sStr
 )
 
 fn GetSubAnims obj str:"" bMI:true  =
 (
 	ssRCM = ""
 	if obj == undefined then return undefined
 	
 	numSubs = obj.numSubs
 	
 	for i = 1 to numSubs do
 	(
 		sub = obj[i]
 		if sub == undefined then continue
 		
 		if sub.numSubs != 0 then
 		(
 			if bMI then
 			(
 				ssRCM += "subMenu \"" + sub.name
 				ssRCM += "\"
(
"
 				ssRCM += GetSubAnims sub
 				ssRCM += ")
"
 			)
 			else
 		    	ssRCM += GetSubAnims sub str:(str + "[" + sub.index as string + "]") bMI:bMI
 		)
 		else
 		(
 			if bMI then
 			(
 		    	ssRCM += "menuItem mi" + (getSubAnimName obj i as string)
 				ssRCM += " \"" + sub.name + "\"
"
 			)
 			else
 			(
 		    	ssRCM += "on mi"  + (getSubAnimName obj i as string) + " picked do
"
 		    	ssRCM += "	 temp_SARCM = " + (str + "[" + i as string + "]") + "
"
 			)
 		)
 	)
 	
 	ssRCM
 )
 
 fn MakeRCMenu obj =
 (
 	sRCM = "rcm" + FixName (obj.name)
 	
 	ssRCM = "(global temp_SARCM
"
 	
 	ssRCM += "rcMenu "
 	ssRCM += sRCM + "
(
"
 	ssRCM += "subMenu \"Transform\" 
(
"
 	
 	ssRCM += GetSubAnims obj[3]
 	
 	ssRCM += ")
"
 	
 	ssRCM += "subMenu \"Object\" 
(
"
 	ssRCM += GetSubAnims obj[4]
 	ssRCM += ")
"
 	
 	ssRCM += GetSubAnims obj[3] str:("$'" + obj.name + "'[3]") bMI:false
 	ssRCM += GetSubAnims obj[4] str:("$'" + obj.name + "'[4]") bMI:false
 	
 	ssRCM += ")
"
 	ssRCM += "popUpMenu " + sRCM + "
"
 	ssRCM += "temp_SARCM)
"
 	
 --	format ssRCM
 	
 	(execute ssRCM)
 )
 
 clearListener()
 (MakeRCMenu $).controller

I wrote this last night while I was half asleep, so I haven’t optimised it at all yet, but can anyone tell me if there is a better way or even if there is a standard function in max that does this.

Thanks.

8 Replies
 rdg

Wahooney,

I don’t know of a standard function, but this is cool.
I didn’t even know this is possible.

You could maybe straighten some of the code by replacing some of the “ssRCM +=” with the format function.

But the way you wrote it is very readable.

Georg

Is it possible to return a value from an rcMenu without using globals? I’ve modified the code to use format() and it’s much neater but still doesn’t do exactly what I’d like.

fn FixName str = 
 (
 	pStr = filterString str " .+-/=,;:\"[]{}!@#$%^&*()"
 	sStr = ""
 	
 	for s in pStr do sStr += s
 		
 	sStr
 )
 
 fn GetSubAnims obj str:"" bMI:true  =
 (
 	saRCM = stringStream ""
 	if obj == undefined then return undefined
 	
 	numSubs = obj.numSubs
 	
 	for i = 1 to numSubs do
 	(
 		sub = obj[i]
 		if sub == undefined then continue
 		
 		if sub.numSubs != 0 then
 		(
 			if bMI then
 		    	format "subMenu \"%\"
(
%)
" sub.name (GetSubAnims sub) to:saRCM
 			else
 		    	format "%" (GetSubAnims sub str:(str + "[" + sub.index as string + "]") bMI:bMI) to:saRCM
 		)
 		else
 		(
 			if bMI then
 		    	format "menuItem mi% \"%\"
" (getSubAnimName obj i as string) sub.name to:saRCM
 			else
 		    	format "on mi% picked do
	val = %[%]
" (getSubAnimName obj i as string) str i to:saRCM
 		)
 	)
 	
 	saRCM as string
 )
 
 fn MakeRCMenu obj =
 (
 	sRCM = "rcm" + FixName (obj.name)
 	
 	ssRCM = stringStream ""
 	
 	format "(
global val
rcMenu %
(
" sRCM to:ssRCM
 	format "subMenu \"Transform\" 
(
%)
" (GetSubAnims obj[3]) to:ssRCM
 
 	format "subMenu \"Object\" 
(
%)
" (GetSubAnims obj[4]) to:ssRCM
 	
 	format "%" (GetSubAnims obj[3] str:("$'" + obj.name + "'[3]") bMI:false) to:ssRCM
 	format "%)
" (GetSubAnims obj[4] str:("$'" + obj.name + "'[4]") bMI:false) to:ssRCM
 	
 	format "popUpMenu %
val
)
" sRCM to:ssRCM
 	
 	--format (ssRCM as string) to:(newScript())
 	
 	(execute (ssRCM as string))
 )
 
 clearListener()
 MakeRCMenu $Teapot01
 PEN

Return a value in what way Keith? If you need the value to be accesed by another script something has to be global. What is the RC menu being called from? Can you store a value there somewhere and access it?

I want a menu like the one that pops up when you use the Wire Parameters function. So the flow would be, the user clicks a button in a floater, picks a scene object, navigates the rcMenu and click the subAnim they want to use and then the script gets the path to that subAnim (eg. $object[1][2][3])

Now I’ve got the rcMenu, I can make the tree that the user navigates and I can generate the subAnim path. The final step that eludes me is actually getting that path back into my script.

The global that I define, temp_SARCM, only gives me the previously chosen subAnim, which doesn’t help much. I’m stumped.

 PEN

I’ll have a look at this now for you as I have always wanted to do something like this as well.

Thanks Paul

One would imagine that this feature would have made it’s way into maxScript yonks ago. The trackView.pickTrackDlg() is a bit too chunky for my tastes.

Here is my latest attempt, this returns the previously picked subAnim (not to be confused with the last picked subAnim)

-- Eliminate the spaces from strings
 fn FixName str = 
 (
 	pStr = filterString str " .+-/=,;:\"[]{}!@#$%^&*()"
 	sStr = ""
 	
 	for s in pStr do sStr += s
 		
 	sStr
 )
 
 -- Recursively get all the subAnims in an object
 fn GetSubAnims obj str:"" bMI:true  =
 (
 	saRCM = stringStream ""
 	if obj == undefined then return undefined
 	
 	numSubs = obj.numSubs
 	
 	for i = 1 to numSubs do
 	(
 		sub = obj[i]
 		if sub == undefined then continue
 		
 		if sub.numSubs != 0 then
 		(
 			if bMI then
 		    	format "subMenu \"%\"
(
%)
" sub.name (GetSubAnims sub) to:saRCM
 			else
 		    	format "%" (GetSubAnims sub str:(str + "[" + sub.index as string + "]") bMI:bMI) to:saRCM
 		)
 		else
 		(
 			if bMI then
 		    	format "menuItem mi% \"%\"
" (getSubAnimName obj i as string) sub.name to:saRCM
 			else
 		    	format "on mi% picked do
	tempSARCM = (%[%])
" (getSubAnimName obj i as string) str i to:saRCM
 		)
 	)
 	
 	saRCM as string
 )
 
 -- Make the RCMenu string
 fn MakeRCMenu obj =
 (
 	global tempSARCM
 
 	sRCM = "rcm" + FixName (obj.name)
 	
 	ssRCM = stringStream ""
 
 	format "fn SetVal theVal &v = (v = theVal)
" to:ssRCM
 	format "(
rcMenu %
(
" sRCM to:ssRCM
 
 	if (obj[3].numSubs > 0) then
 		format "subMenu \"Transform\" 
(
%)
" (GetSubAnims obj[3]) to:ssRCM
 	if (obj[4].numSubs > 0) then
 		format "subMenu \"Object (%)\" 
(
%)
" obj.name (GetSubAnims obj[4]) to:ssRCM
 	if (obj[5].numSubs > 0) then
 		format "subMenu \"Material\" 
(
%)
" (GetSubAnims obj[5]) to:ssRCM
 	
 	if (obj[3].numSubs > 0) then
 		format "%" (GetSubAnims obj[3] str:("$'" + obj.name + "'[3]") bMI:false) to:ssRCM
 	if (obj[4].numSubs > 0) then
 		format "%" (GetSubAnims obj[4] str:("$'" + obj.name + "'[4]") bMI:false) to:ssRCM
 	if (obj[5].numSubs > 0) then
 		format "%" (GetSubAnims obj[5] str:("$'" + obj.name + "'[5]") bMI:false) to:ssRCM
 
 	format ")
" to:ssRCM
 	
 	format "popUpMenu %
val
)
" sRCM to:ssRCM
 	
 	-- Uncomment to write the temporary script to a new script window
 	--format (ssRCM as string) to:(newScript())
 	
 	(execute (ssRCM as string))
 	tempSARCM
 )
 
 clearListener()
 
 format "> % <
" (MakeRCMenu (PickObject()))
 PEN

I’m just not getting anywhere with it. It is still returning the old track that was picked. If you format the rcMenu to a window and run it from there you can make it work, just not when it is executed.

If I have time later I will play again if you are still in need.

I’m definitely in need. So that’ll be appreciated.