View Full Version : Getting a subanim from a value

05 May 2008, 07:19 AM
I've got a script that's returning something like this:
What I want is to convert it and any other returning value expressions to their respective subanim forms. ie. $teapot01.baseobject[#radius]
How can I do that?

05 May 2008, 12:01 PM
No takers? OK...

Well, what I'm doing specifically is trying to extract the details of a script controller; trying to create the code that will create a target, object, constant or node variable in a script controller by extracting the information contained within it. The problem is however, that maxscript's commands for getting that info have a few holes in them.

For example, if I try to extract the info of a variable assigned to a controller on an object using .getobject, I get something like Controller:bezier_float. No detail on the object's name or where in the controller hierachy it is. So, I use the command .printDetails() which gives me a good array of stuff that I can sift through with string stream commands to get what I need.


If that variable's target is the weight of a list controller, the result printed isn't correct.
For example, this is what's returned from .printDetails():
$Teapot01.pos.controller.X_Position.controller.weight.controllerWhen what it should be is:
How can I extract the specific controller that it is? Especially as in this example, both weights are called weight__bezier_float, how do you extract the index of the weights from the small amount of information given?

05 May 2008, 12:48 PM
Can you use some combination of



05 May 2008, 01:41 PM
Hmm, looks like a real head ache. Can you elaborate on what it is you are doing and why? Maybe there are other ways to go about it.

05 May 2008, 02:27 PM
Dave: I just discovered exprForMAXObject for the .getObject stuff and that saves me a lot of stringstream searching through the .printDetails() result.

However, the same problem remains, how do I get the right weight controller/subanim?

Paul: What I'm doing is turning a rig into code. Rigging something by hand, then running the script to create a new script that when run, will rebuild the rig. I've got it to build objects, name them, link them, assign CAs, assign controllers and wire them. I can put script controllers on them but it fails when assigning variable targets and/or objects when they are list weights.

For example:
for i = 5 to obj.controller.numvariables() do
scriptVar = obj.controller.getName i
scriptTarget = exprForMAXObject (obj.controller.getTarget i)
format (objname + "_script.addTarget \"" + scriptVar + "\" " + scriptTarget + "\n") to:ScriptFile
When it comes to list weights, the scriptTarget variable is returning: blah.weight.controller when it should return: blah.weight.weight__bezier_float.controller or better still: blah.weights[1].controller
I could easily do some string replacing to turn "weight" into "weights[1]" but I can't find the index number of the weight I should be using. It won't always be 1.

Does that make sense?

05 May 2008, 03:52 PM
What I would try is this:

Get your target controller as an object
Create a recursive function that recurses through any object's subanims
Recurse through the object (as you have its name) building up the string as you go with name and index values, eg "$object.position.controller[2].controller"
When your target == your iterator, you have your string!
Would that work? Probably not perfectly on instanced controllers, but you may be able to write checks for this.

Any good to ya?


05 May 2008, 03:57 PM
Hi Chinwagon,

a way that' i found to get the real string and avoid that bug is to use the string from the exprForMAXObject function, then loop in each of its controllers, and compare it to the controller gotten from the "getObject" function.

Here i made a try:

targetController=(scriptController.getobject "variable")
stringVal=exprForMAXObject targetController explicitNames:true
auxCtrl=execute stringVal
if auxCtrl==undefined then
--Here i copy the string without the ".controller" part
for i=1 to (stringval.count-11) do
append stringval2 stringval[i]

--get the number of weights and loop throught them
n=execute (stringval2+".count")
for i=1 to n do
--compare to the controller to find the right string
aux=(stringval2+"["+(i as string)+"].controller")
if (execute aux)==targetController then stringVal=aux

05 May 2008, 03:59 PM
Didn't notice that davestewart posted a similar answer XD

05 May 2008, 04:25 PM
Didn't notice that davestewart posted a similar answer XD

Ha ha, well at least you save me the trouble of finding out :)

05 May 2008, 07:23 PM
YIKES!, looked into that at one point and just ran away screaming. good on ya. That would be very handy to have.

05 May 2008, 10:09 PM
OK, Here's my take:

struct scriptExpr
expr = "",

function getSubAnims src trg path =
local sas = getSubAnimNames src
if sas != undefined do
for sa in sas do
local ctrl = src[sa].controller
local temp = path + "[#" + sa + "]"

if ctrl != undefined AND ctrl == trg then
-- success!
expr = temp + ".controller"
-- failure
getSubAnims src[sa] trg temp

function get trg =
-- get the source object if unsupplied
local obj = exprformaxobject trg explicitNames:true
local src = execute (filterstring obj ".")[1]

-- recurse through src and attempt to find target controller
getSubAnims src trg ("$" +

-- return the final script path

-- objects
trg = $.pos.controller[2].controller -- second controller in a position list
se = scriptExpr()

-- get the expression
expr = se.get trg
trg == (execute expr)

-- results
-- "$Teapot01[#transform][#position][#Pos_2].controller"
-- true

I was trying to make a standalone struct, but I was having a bit of trouble figuring out how to pass the final expression back up the recursion chain.

Still, this is an OK starting point. You may need to add checks to check for unique names, or use indices instead, but this proves the theory at least.

Hope that helps.


05 May 2008, 12:46 PM
Thanks for the help guys.
In the end, I went with phoelix's method (as I'm not too familiar with structs) and it worked a treat.

CGTalk Moderation
05 May 2008, 12:46 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.