Difference between "$" and "$selection"

polycounter lvl 11
Offline / Send Message
SimonT polycounter lvl 11
I tried Google but it's hard to google "$" - So i wasn't successful. :) I#M using 3Ds Max 2011 64Bit

I always thought $ and $selection give you the same result: the current selection.

BUT

If you have e.g. a box linked to another box, select the blue one and execute the code below, you'll get different results:

Capture01_1.jpg

Code with $
for obj in $ do print obj
Result
$Box:Box01Parent @ [0.000000,0.000000,0.000000]
$Box:Box01Child @ [20.000000,0.000000,0.000000]

Code with $selection
for obj in $selection do print obj
Result
$Box:Box01Parent @ [0.000000,0.000000,0.000000]

Interesting

If you have the same situation but twice, and you select both parents, the results are equal for both code variations:

Capture02.jpg

Code with $
for obj in $ do print obj
Result
$Box:Box01Parent @ [0.000000,0.000000,0.000000]
$Box:Box01Parent @ [0.000000,21.652542,0.000000]

Code with $selection
for obj in $selection do print obj
Result
$Box:Box01Parent @ [0.000000,0.000000,0.000000]
$Box:Box01Parent @ [0.000000,21.652542,0.000000]

Why is this important?

For example if you've a script which moves objects around. In this example i add +10 to the x axis and in one case the linked box moves relative, in the other example it moves too far:

caputre03.gif

Is this a bug? Or did i just misunderstand the system?

Replies

  • marks
    Offline / Send Message
    marks polycounter lvl 9
    o_O I always thought they were the same identifier too.
  • SimonT
    Offline / Send Message
    SimonT polycounter lvl 11
    A colleague just found the place in the documentation where "$" is documented. It recommends using "selection" but for other reasons:
    Inside a script, it is better to use the selection ObjectSet rather than $ .
    selection always contains an ObjectSet regardless of the number of selected objects. Where hide $ will generate an error if no objects are selected (because $ contains the value undefined ), hide selection will not generate an error.

    http://docs.autodesk.com/3DSMAX/14/ENU/MAXScript%20Help%202012/files/GUID-8395020C-E3B6-4282-AF1C-5B58BDB97A2-391.htm
  • Swordslayer
    Offline / Send Message
    Swordslayer greentooth
    It's maxscript time! Jokes aside, there are multiple ways to get currently selected objects:
    $
    $selection / selection
    getCurrentSelection()
    

    The $ is the most dangerous one - and in so many ways it's not even funny. It returns different values based on what how many nodes are selected:
    0 -- undefined
    1 -- the node itself
    2+ -- live selection set (same as $selection / selection)
    

    So when one node is selected, what happens? $ returns the node itself and you are not iterating an array of nodes, you are iterating that node, basically saying:
    for obj in $Box01Parent do print obj
    

    It just so happens that you can actually do that and it will give you the node and all its children and their children's children etc. Most of the time you want a snapshot of the selection as array, so selection as array or getCurrentSelection() is the safest bet.
  • SimonT
    Offline / Send Message
    SimonT polycounter lvl 11
    Thx Swordslayer! Sounds logic how you explained it. Not sure if "logic" and "maxscript" should be named in the same sentence but you know what i mean :D
  • monster
    Offline / Send Message
    monster Polycount Sponsor
    I never use $. There is just no reason. At the very least you should store $ in a variable. Look at the following example. $ is slower than "obj = $" and "selection[1]".

    92ms for $
    61ms for obj = $
    69ms for selection[1]

    I know 30ms isn't exactly a discernible difference, but if you've got a huge code project littered with little slow downs, it all adds up.
    (
    	clearlistener()
    	gc()
    
    	t = timeStamp()
    	for i = 1 to 100000 do
    	(
    		$.name
    	)
    
    	format "%ms\n" (timeStamp()-t)
    
    	gc()
    	obj = $
    
    	t = timeStamp()
    	for i = 1 to 100000 do
    	(
    		obj.name
    	)
    
    	format "%ms\n" (timeStamp()-t)
    
    	gc()
    
    	t = timeStamp()
    	for i = 1 to 100000 do
    	(
    		selection[1].name
    	)
    
    	format "%ms\n" (timeStamp()-t)
    )
    
  • SimonT
    Offline / Send Message
    SimonT polycounter lvl 11
    Wow, that's kind of significant. Thanks for the benchmark! :) I think it's often tempting to just use "$" when trying around in the Listener and sometimes it then sneaks into the final code snippets :D
Sign In or Register to comment.