Notifications
Clear all

[Closed] scope of functions?

This keeps happening to me, and I have searched for a solution with no direct answers found.

I have a maxscript file that looks like this, but I have to run it twice to get the functions to process:

fn someFunction = ()

fn someMoreFunctions = ()

(
Rollout
)

I have tried it like this, which causes the function to cease functioning:

(
fn someFunction = ()

fn someMoreFunctions = ()

Rollout
)

and this which also seems to need to run twice:

fn someFunction = ()

fn someMoreFunctions = ()

Rollout

It is frustrating, and I know the answer is relatively simple.

4 Replies

I really don’t know what exactly is so difficult – MAXScript can only see what it has already seen before in the current scope or ANY scopes above it, including the global scope.

So

(--open local scope
    fn someFunction = ()
    fn anotherFunction = ()
    rollout someRollout "Test" ()
    )--close local scope

*will allow anotherFunction to call someFunction (same scope, someFunction defined first!)
*will allow the rollout handlers to contain calls to both functions (higher scope, defined earlier)

If you want someFunction() to "see" and be able to call anotherFunction(), you can predeclare anotherFunction() as local in the beginning. You can do the same with the rollout if the two functions have to access the rollout for something.

(--open local scope
  --make second function and rollout visible to anything in this and any nested scopes:
    local anotherFunction, someRollout 
    fn someFunction = (anotherFunction()) --can call other function since it was predefined
     fn anotherFunction = (someRollout.someButton.pressed()) --can "see" the following rollout
     rollout someRollout "Test" 
 (
 button someButton "Press me"
 on someButton pressed do print "Hey!"
 )--end rollout
     )--close local scope

Questions?

If you want someFunction() to “see” and be able to call anotherFunction(), you can predeclare anotherFunction() as local in the beginning. You can do the same with the rollout if the two functions have to access the rollout for something.

Ha! The declaration bits solved my problem.

I was assuming that declaring the function inside the local scope would simply make it accessible to the local scope completely.

I really don’t know what exactly is so difficult – MAXScript can only see what it has already seen before in the current scope or ANY scopes above it, including the global scope.

My functions get put into global scope, so has MXS not seen them at this point? I understand when I run the script again, it is seeing them again. Is it good practice to explicitly declare the scope as outlined above?

Apologies if I am simply obtuse. Thank you for your tireless efforts on behalf of us novices. :buttrock:

It is generally a bad idea to use the global scope unless you HAVE to.
So starting with ( and ending with ) is the way to go 99.9% of the cases.
The only cases you might want something in the global scope is when you define function libraries to be used by all your scripts, but even then you would define a local scope using ( ) and then declare specific functions or structs as global explicitly:

(--start local scope
 global myGlobalStructOfFunctions
 struct myGlobalStructOfFunctions
 (
 fn importantFunction = (),
 fn anotherFunction = ()
  )
 )--end local scope

Such a script could be placed in the StrdPlugs\StdScripts folder and would be loaded at startup. Then, any of your scripts could call

myGlobalStructOfFunctions.importantFunction()

and would find the struct in the global scope (because we explicitly placed it there) and we can access all the functions inside that global struct without them being in global scope directly…

Another case you want to use global variables is when defining a rollout to be used as a dialog – you want to be able to “see” that dialog in another run of the script and be able to close it before redefining it. Also, other scripts would be able to access the dialog and press buttons or change settings in it.

(--local scope
 global someUniqueRolloutName
 try(destroyDialog someUniqueRolloutName)catch()--try to close if already open
 rollout someUniqueRolloutName "Rollout" 
 (
 button btn_pressMe "Press Me"
 )--end rollout
 createDialog someUniqueRolloutName
 )--end local scope

This local scope above very often is the scope of the MacroScript that creates a dialog… So if you are defining a Button for the UI, you have to create a local scope for the MacroScript anyway, but still keep the rollout global for later runs or other scripts to see it.

Perfect.

Thanks bobo.