Notifications
Clear all

[Closed] Maxscript initialization order frustrations

Hi,

for a long time I’ve been having issues with the order in which maxscripts are initialized and the countless workarounds you have to build in to scripts to avoid problems with this.
A simple example of what I mean is this:


  (
    function a = (
  	return b()
   )
  
    function b = (
  	return "b"
    )
  
    print (a())
  )

This doesn’t work, at the point where function a is parsed, function b doesn’t exist yet, and you get a crash. The easy solution here would be to move function b in front of function a:


  (
    function b = (
  	return "b"
    )
    
    function a = (
  	return b()
   )
  
    print (a())
  )
  

In my eyes a rather ugly solution, as it sort of forces you to organize your code in a backwards way. A function that is called first and calls other functions has to be at the bottom…

Still, this is all very doable and not much of a problem, more of an aesthetic issue. However, it gets more annoying when you have multiple script files relying on the existance of the other. Like a macroscript that calls a function in a struct of a script file that is loaded on startup. Imagine this situation:


  --A script file loaded at startup.
  struct someStruct (
    function a = (
  	return "a"
    )
  )
  

  --A macroscript that is put on a button in the UI.
  macroScript testMacro category:"test" 
  (
    print (someStruct.a())
  )
  

This works fine the first max session, when you stick it on the button, because at that point the struct is parsed. However, the second time you start max, the macro is parsed before the struct, and the function can not be called…

Now I could get around this by using execute “someStruct.a()”, but that is going to be very ugly.

Another example:


struct firstStruct (
  function a = (
	secondStruct.b()
  ),
 function b = (
    return "firstStruct.b"
  )
)


struct secondStruct (
 function a = (
  firstStruct.b()
 ),
 function b = (
   return "secondStruct.b"
 )
)

In order to get this to work, you’ll have to initialize the first file, then the second, and then the first file once again… :shrug:

Does anyone have any solutions or tips on how to avoid these kind of problems?

6 Replies

Hi Pier,

I have the same problem, and its usually from structs that call multiple functions. I have resorted to, like you, reordering the struct to load dependent functions first.

 JHN

No solution either, just sympathy and understanding… I had to move all functions in a rollout around a while ago, just to gain access to some silly little string in a UI control. Even after the script has run once you would suspect that a function beneath another could access it, but it can’t and it just sucks…

-Johan

Yes it’s rather annoying. What I usually do for tools is that I have a script called zInit.ms (so that it runs last) and have that do a fileIn on all files the tool depends on.
This way all scripts are basically run twice. Very ugly and hackish, but it works.

The real problem I’m having is with macroscripts (for minor tools) that depend on (parts of) the major tool scripts…

In your first example, to make function b visible to function a, you could declare the second function at the top of your script:

 (
[B]local b[/B]

function a = (
    return b()
)
  
function b = (
    return "b"
)
  
print (a())
)

The order in which max loads/parses script files is as follows:

  1. stdplugs/stdscripts
  2. custom scripts folder
  3. macroscripts
  4. startup folder

So for example if you place your struct file inside the stdplugs/stdscripts folder, you should have no problem accessing this struct from within a macroscript.

Hope this helps,
Martijn

 JHN

Martijn,

Would this “local trick” also work with “instanciated structs”, where one function depends on another?

Cause right now I have a topmost function I call “this” (which returns itself as struct) and after that all functions in the struct that depend on again other functions in the struct use “(this()).theOtherFunc()”

-Johan

We had this problem with our function library- our ‘stringOps’ use ‘arrayOps’ and ‘arrayOps’ use ‘stringOps’. There was no ordering solution possible.

What we did was this: Any function that will be called from multiple script files goes into some struct- usually these functions are pretty common, but you can have some specific structs as well. When we load max, in the first script we fileIn in our scriptloader, we declare globals for the instances of all these structs (so ‘global arrOps, strOps’), then at the bottom of each struct file we have ‘strOps = stringOps()’, or ‘arrOps = arrayOps()’, etc. This has worked without any problems.