[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.
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
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.
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()))
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.