I’m trying to get a firmer understanding of the best ways to use structs for our max tools.
the Rollout_and_Struct_Pairs wiki page is down, it seems , a casualty of some past server issues.
Does anybody have a link/backup of that info?
I’m trying to get a firmer understanding of the best ways to use structs for our max tools.
the Rollout_and_Struct_Pairs wiki page is down, it seems , a casualty of some past server issues.
Does anybody have a link/backup of that info?
Failing that, what are you trying to do with structs?
all the things , of course.
I am re-factoring my single massive Game asset export script into different .ms files and loading them with filein.
each new file contains a struct with vars for data, functions for populating / altering said data,
and in some cases (where i could get it to work) a function for instantiating and intializing the struct.
it gets a bit convoluted when I have the structs referencing each other, I think I am creating dependency loops somewhere.
the symptom being that the main script failed on first run, but works on subsequent runs (until i restart max)
I think I have eliminated these dependencies by only initializing the offending structs in my main function,
after all the file in commands run and the preceding structs are initialized.
I suspect that my structs are not insulated enough from each other ,
and there is a noobish level cross-referencing of struct data happening,
so I am seeking advice on best practices.
I am looking over several struct threads at cg talk, and I can see that people are doing neat things with them,
but the gleenign useful approaches in my own tasks form discussions and examples is a challenge.
some specific questions:
is it wise/common for a struct to hold functions that populate its own fields ?
is there some Max Script struct version of this. or self. to use within a struct definition?
can a struct to have function that initializes itself?
is it wise/common for a struct to call functions and fields in another struct?
when you create a paired rollout / struct , where would you put the function to launch the rollout floater or dialog?
Should you include a struct function to display the rollout or keep the floater / dialog code separate?
suppose I need a roll-out button to launch a pop-up dialog (to pick a mesh or a bone from a list for example).
does the function for this go in the struct, the rollout block, or should I keep it external to both?
I have noticed in CG talk forums that some people have structs that contain roll out definitions and laucnh them, but I can’t seem to get this working.
[QUOTE=Mambo4;20636]some specific questions:
is it wise/common for a struct to hold functions that populate its own fields ?
[/QUOTE]
I’ve done it before to great effect but I would set it up like this:
struct thing
(
private
fn populateVar input =
(
input += 5
),
public
fooBar, --leaving this empty for the next example
theVar = populateVar 10
)--end struct
[QUOTE=Mambo4;20636]
is there some Max Script struct version of this. or self. to use within a struct definition?
[/QUOTE]
In the above example, I called the function populateVar without anything like that. It’s more like a namespace in that instance than a python-like class.
[QUOTE=Mambo4;20636]
can a struct to have function that initializes itself?
[/QUOTE]
You probably don’t want to do this. Using the above example struct, I instantiate it as shown below. You can change any public variable by treating it like a kwarg when you instantiate the struct.
myStruct = thing fooBar:"something"
[QUOTE=Mambo4;20636]
is it wise/common for a struct to call functions and fields in another struct?
[/QUOTE]
It’s possible, although you’re right in thinking it can lead to dependency loops.
[QUOTE=Mambo4;20636]
when you create a paired rollout / struct , where would you put the function to launch the rollout floater or dialog?
Should you include a struct function to display the rollout or keep the floater / dialog code separate?
[/QUOTE]
I’ve never done anything quite like that. I’m always in favor of separating UI from the logic it drives. If you want to create a dialog, just use “createDialog ”.
[QUOTE=Mambo4;20636]
suppose I need a roll-out button to launch a pop-up dialog (to pick a mesh or a bone forma list for example).
does the function for this go in the struct, the rollout block, or should I keep it external to both?[/QUOTE]
Whenever I did that, I kept it separate. In my workings with Maxscript, it would always spit out errors if I tried to put a rollout in a struct or vice versa.
You can cut down on dependency loops by drawing out a little map of how your structs interconnect. If you want to make sure they’re only instantiated once when you’re doing your set of fileIns do something like this:
if myStruct == undefined then fileIn "myStruct.ms"
thanks for your responses.
I’ve been thinking over the idea of separating the UI form the Logic and I figured out what bugs me about it.
Perhaps there is a better way to code
consider this example:
struct theStruct(
fn changeVar n=(
this.var+=1 --yes you can use "this." in structs
theRollout.sp_var.value=this.var
),
var
)
rollout theRollout ""(
button btn_changeVar "change var" across:2
spinner sp_var "var:" type:#float value:aStruct.var
on btn_changeVar pressed do(
astruct.changeVar 10
)
)
try (closeRolloutFloater thefloater )catch ()
global thefloater=newRolloutFloater "" 200 100
addRollout therollout theFloater
aStruct=theStruct var:10
i realize that sp_var does not intialize with astruct.var
there is probaly an on open intializing function i can throw in
but what really bugs me here is the hard-coding of struct names in the roll-out
mostly the struct name, since the struct could potentially be instantiated under any name.
this is where having a struct function that defines and launches its own roll-out might be more self contained…something I thought may be covered in the 404 wiki page.
interesting reply by DennisT to my related CG talk thread
it’s better to check most recent samples from this forum. in 2008 all scripters (including me) used structures a different way than today.
there is an old tool style (pseudo code):
the modern one is:
< struct ( <params> <structs> <rollouts> or <forms> <functions> <event handles> ) >
so the modern paradigm for a tool is “one tool - one global”
words for the wise:
http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html
theodox, are you pointing out this “do one thing” rule as a counter point to previous post, or just adding general wisdom?
Dennis T seems to know his stuff and so do you, so if there’s a flaw in the approach, I’d like to know…
Just wanted to encourage you not to give up on UI/implementation separation. The ‘Single Responsibilty’ method of doing that is, pseudo-code-wise
struct TheActualTool --- this is where you do all the real work
(
tool_state = 1,
other_tool_state = "string",
fn tool_function arg = (...),
fn other_function = (...)
)
struct ToolRolloutStruct -- the tool rollout includes one of the above and delegates the work to it...
(
implementation = TheActualTool(),
fn some_event_handler = (...), -- an event handler might call the implementation struct's functions
fn update_ui_event_handler = (...) , -- or it might just do UI updating
some_ui_state = "message or text or something",
rollout the_rollout "" (...)
)
Single responsibility doesn’t mean the you cant make complex stuff - you just build it up out of smaller, isolated pieces. In a case like this you might have a number of different ‘tool structs’ that do the work and have them all be included into the ToolRolloutStruct . You might even want to be able to configure them outside and inject them with appropriate options .
So I’m basically agreeing with the pattern you posted – though I’d add the caveat that you want those tool implementation pieces to have lives of their own outside the scope of the UI struct unless they are completely tied in to the UI – in this example, you’d want to be able to make TheActualTool somewhere else without carring about the ToolRolloutStruct – but something trivial like the fn update_ui_event_handler should be local to the ToolRolloutStruct.
I think I understand. You are advocating something Along the lines of taking the function executed by a button (or spinner change etc) , and moving it outside of the rollout declaration, into its own struct. And this external “actual tool” struct would also hold the “master” variables for the rollout’s controller object states(checkboxes states, edittext values, pickbutton values, listbox arrays etc). the rollout itself would house a function to update itself drawing on those external “master” variables.
Do I got that right?
Pretty much yes. Functions that are completely and only used for the rollout would live in the rollout struct – this generally means UI stuff like highlighting or displaying names and so on. The ‘ActualTool’ is pure functional code - it actually manipulates the scene. It lives in a self-contained struct so you can use it from multiple tools or from the listener without needing to create GUI just to get at the functionality.
The purpose of this arrangement is twofold
thanks again Theodox.