Wiki Rollout_and_Struct_Pairs Link Broken


Tried to go to this link, it sends me to a blank page. The link was recommend by some blog posts I was reading and I would like read it. Can somebody figure out what happened/bring it back?

Thanks, let me know if I can help somehow.


I’ll check that out cheers Erkmuss



That should be sorted now, thanks for the heads up.



[QUOTE=Butters;23471]That should be sorted now, thanks for the heads up.


Awesome, thank you!


I looked for this a while ago as well.

While the wiki is up , the code snippets are all killed due to (error loading supported language list)


And we’re sorted. If anyone sees any other issues, shoot me a pm.




It’s awesome to see this finally up, however, I learned in a thread over at cg talkthat this approach is a little out dated.

essentially, rather than separate struct and rollout code, the rollout code is now simply another function within the struct itself -and all other code the tool requires.


I think a better read on that thread could be paraphrased as ‘treat structs as if they were classes’. In which case you follow the basics of OOP, including single responsiblity (1 struct = 1 job), don’t repeat yourself (1 job may be a very narrowly defined job like ‘format path strings’ instead of ‘manage files’ so you can reusit generally) and ‘Prefer composition’ - build up complex classes (like a rollout UI) with a hierarchy of smaller, more tailored classes.


@theodox: So if you follow this approach, how do you manage the ‘classes’ ?
do you end up a with a bunch of smaller maxscript ‘class’ files
and use a bunch of filein expressions to load your ‘classes’ for a given tool?


Basically, I’d have two levels of organization. I tend to put one big struct into a file that contains smaller structs and any shared data - basically, the equivalent of a python module. I don’t use that one as an instance, but as a namespace (again, like a python module) and I’ll put that into a global. Other script that need the functionality from that file use the global, and then make/use individual structs within it. In the thread you probably saw this:

   <rollouts> or <forms>
   <event handles>

Which is really a way of saying “I make a class (= struct) that handles all the functionality for my tool in the same scope”. The only changes i might make to that : It doesn’t really need to be a global per se, as long as you can get a handle to it. My usual practice (warning: I’ve been out of MXS as a day job for 4+ years ) was to make globals structs that contained only other structs and functions and use them as if they were python modules.

global databasemodule
username = "steve"
password = "xxx"
connection = databaseModule.get_connection(username, password)  -- < a function in the databaseModule that gives back a struct (also defined there)
models = connection.request("models")

Individual dialogs or whatnot might be their own globals or not; if you are good about keeping UI and function separate, the “UI” structs will be 99% UI code with functions/structs from elsewhere doing the actual work. The ‘globalness’ only matters in the sense that you have to have a handle to the tool in whatever code scope you’re running; structs keep the scopes nice and tight instead of sending every callback out to the global scope all the time.

The main trick to keeping this working is that you don’t want to go nuts with fileins. To use a ‘module’ you would have a header that checked the global’s existence, and if it did not exist would filein the module file into the global. This is basically a lame version of the way python modules work.

fn using globalName script:undefined = 
if classof globalName == Name do globalName = globalName as string

scriptPath = if script == undefined then globalName else script
if not (matchPattern scriptPath pattern:"*:*") do scriptPath = (scriptDir + "/" + scriptPath)
if not (matchPattern scriptPath pattern:"*.ms") do scriptPath = (scriptPath + ".ms")
genericCommand = "" as stringStream
format "global %
" globalName  to: genericCommand
format "% = if % == undefined then (filein \"%\") else %
" globalName  globalName scriptPath globalName to: genericCommand
seek genericCommand 0
execute genericCommand

-- typical pattern
--using #materialMgr
--global materialMgr
-- materialMgr.DoSomething()

Looking at this now I realise the smart way to do this would have been to return the contents of the global from the call so the pattern would be shortened to

materialMgr= using #getMaterialFromFace

But that would require executing another eval to get the contents of the global. All of this might be better today, it seems like an obvious place for MXS to have gotten better.