PDA

View Full Version : Can functions be declared in Structs?


Jon Huhn
11-17-2005, 07:43 AM
I like to declare all my functions at the beginning of my scripts so that I don't have to worry about in what order the functions are defined later. But I can't seem to do this inside a Struct, and I hate having to carefully order my function definitions to avoid "undefined function" errors.

Is it possible to declare functions in Structs somehow?

Thanks in advance!

eek
11-17-2005, 08:23 AM
yes they can,

struct mystruct_c
(


fn test_func a b = (
(a.pos[2] - b.pos[2])
)

)

mystruct = mystruct_c()

mystruct.test_func $point01 $point02

This is a simple version, im too getting into strut stuff, variables etc etc btw you could put this in a start up file so they dont have to be in the primary script.

eek

Jon Huhn
11-17-2005, 09:31 AM
Charles,

Thanks for your reply, but I think maybe I wasn't explicit enough about my question.

In your example, you defined a function, but you didn't declare it. Declarations are like placeholders at the beginning of your script; they tell the program that a function of a given name is going to be used in the script, but the actual definition will happen later. This allows a function to call another function even if the called function is placed below the first function in the script.

So my problem is that I can't seem to figure out how to declare functions in Structs the same way you would declare functions in the main body of the script.

Aearon
11-17-2005, 09:49 AM
structs are the greatest thing in maxscript ;) ... looking at paul hormis' script pack i learned how he uses them, and started to use them myself, now we have a library of functions inside structs that are used throughout our macroscripts, makes things very easy to manage and update

*edit: didn't see your second post when i wrote this ;)

LoneRobot
11-17-2005, 10:30 AM
this is an interesting discussion. I will check out paul's scripts like you suggest aearon.

In your example, you defined a function, but you didn't declare it. Declarations are like placeholders at the beginning of your script; they tell the program that a function of a given name is going to be used in the script, but the actual definition will happen later. This allows a function to call another function even if the called function is placed below the first function in the script.

does this mean you have to declare your functions in globals within the struct, or is there no need to declare them?. Sorry if i'm not following.

Jon Huhn
11-17-2005, 01:54 PM
Does this mean you have to declare your functions in globals within the struct, or is there no need to declare them?

Peter,

Declaring struct functions globally (even if it is possible, I haven't tried it) defeats the purpose of having a neat and tidy localized struct package. And as far as I can tell, it seems like you can't declare functions in structs, only variables. If this is the case, it means that you have to be careful about defining your struct functions in a specific order: if you call a struct function from another struct function, the called function must appear in the struct before the calling function. This can become almost a puzzle at times.

Surely there's a way around this?

Aearon
11-17-2005, 01:56 PM
have you considered posting this on the autodesk maxscript forum?

if you discover anything on this topic i'd appreciate it if you'd drop me a line :thumbsup:

Bobo
11-17-2005, 02:15 PM
Peter,

Declaring struct functions globally (even if it is possible, I haven't tried it) defeats the purpose of having a neat and tidy localized struct package. And as far as I can tell, it seems like you can't declare functions in structs, only variables. If this is the case, it means that you have to be careful about defining your struct functions in a specific order: if you call a struct function from another struct function, the called function must appear in the struct before the calling function. This can become almost a puzzle at times.

Surely there's a way around this?


A large portion of the Max UI is implemented that way, also MAXScript itself provides many functions packaged in structs.

Here is the common way of doing it:

*You declare ONE global variable to hold the struct.
*You define a struct containing only functions separated by commas.
*You DON'T create an instance of this struct, you can access all the functions inside by prefixing their names with the global struct variable name.
*You save this to an .MS file in the StdPlugs/StdScripts or a subfolder of it.
*Once you restart Max, a single global variable is "wasted", but it gives you global access to an arbitrary number of functions...

Nice and tidy!

PEN
11-17-2005, 02:39 PM
Structs are very useful for keeping your code local but still being able to call what is inside globaly.

Here is an example.


struct testSt
(
myVariable=10,

fn myFn aString aFloat aPoint3:[0,1,2]=
(
format "A String Value: %\nA Float Value: %\nA Point3 Value: %\n\n" aString aFloat aPoint3
),

fn callMyFn =
(
myFn "test String" 20 aPoint3:[10,100,200]
)
)
testInst=testSt()

testInst.myVariable
testInst.myFn "test String" 20
testInst.callMyFn()


You don't want the functions to be global, but you can still call them from out side the struct.

PEN
11-17-2005, 02:41 PM
A large portion of the Max UI is implemented that way, also MAXScript itself provides many functions packaged in structs.

Here is the common way of doing it:

*You declare ONE global variable to hold the struct.
*You define a struct containing only functions separated by commas.
*You DON'T create an instance of this struct, you can access all the functions inside by prefixing their names with the global struct variable name.
*You save this to an .MS file in the StdPlugs/StdScripts or a subfolder of it.
*Once you restart Max, a single global variable is "wasted", but it gives you global access to an arbitrary number of functions...

Nice and tidy!

Bobo you say DON'T create an instance? Why not? If I don't I can't access variables without it but I can access FN's. So why not do it?

Aearon
11-17-2005, 03:29 PM
Bobo,

until now i've put all my structs in scripts\startup, can you tell me where the difference/advantage with StdPlugs/StdScripts is?

PEN
11-17-2005, 03:30 PM
Bobo,

until now i've put all my structs in scripts\startup, can you tell me where the difference/advantage with StdPlugs/StdScripts is?

stdScripts gets loaded first.

kees
11-17-2005, 03:53 PM
Bobo you say DON'T create an instance? Why not? If I don't I can't access variables without it but I can access FN's. So why not do it?

I don't know why Bobo wouldn't, but when I only have functions in it and no variables (which is true for about 95% of the structs I use) I don't create an instance either.

I'd say that not creating another instance saves memory, but I've never really checked if that really makes a significant difference.

-Kees

Bobo
11-17-2005, 04:04 PM
Bobo,

until now i've put all my structs in scripts\startup, can you tell me where the difference/advantage with StdPlugs/StdScripts is?

As Paul said, it get's loaded earlier. In fact, it is the place Autodesk developers put their functions ;) The reason is that you want your functions to be defined before the .MCRs from Ui/MacroScripts get loaded. Scripts\Startup is one of the last places to load, so it is ok only if nothing depends on what is declared there.
Check out the "Startup Scripts" topic in MAXScript Reference. It lists the order and explains what happens under to hood...

Bobo
11-17-2005, 04:06 PM
Bobo you say DON'T create an instance? Why not? If I don't I can't access variables without it but I can access FN's. So why not do it?

When I am using a struct for just packaging functions, I never define variables inside, so I really don't have to create an instance of the struct... YMMV :)

Jon-Huhn
11-17-2005, 04:08 PM
Thanks to all contributing to this topic, I think some valuable things are being covered.

But I'm affraid my original question is being overlooked, so let me give an example:

struct myStruct (

fn myFunction01 = (
myFunction02()
)

fn myFunction02 = (
-- do something
)

)

a=myStruct()
a.myFunction01()

This creates an error because the first function is calling a second function which isn't declared/defined yet. I would like to be able to not worry about what order my functions are definded within the struct because it can become quite a puzzle sometimes.

Light
11-17-2005, 04:20 PM
You need to call the fn from the struct:

fn myFunction01 = (
myStruct.myFunction02()
)




Light

Jon-Huhn
11-17-2005, 04:25 PM
You need to call the fn from the struct:

fn myFunction01 = (
myStruct.myFunction02()
)



Light,

How would I do that if I was running the struct as an instance? Would use the struct name or the variable name that holds the instance?

Light
11-17-2005, 04:28 PM
Struct name, but note that with this:

fn myFunction01 = (
myStruct.myFunction02()
)

I meant to show the fn definition in the original struct.




Light

PEN
11-17-2005, 04:28 PM
struct testSt
(
fn myFn=(),
fn run=
(
myFn()
),
fn myFn=
(
print "This works"
)

)
testInst=testSt()
testInst.run()


This is the way that I go about it. Just declare the fn uptop like you might declare a variable but as a function.

Bobo, this is one of those cases that I find I get errors if I don't create an instance of it. I often have fn's calling fn's in the struct but I do it directly.

If I do this:

struct testSt
(
fn myFn=(),
fn run=
(
myFn()
),
fn myFn=
(
print "This works"
)

)
testSt.run()


I get an error telling me that it needs an instance. Or I can do this.


struct testSt
(
fn run=
(
testSt.myFn()
),
fn myFn=
(
print "This works"
)

)
testSt.run()


This gets around having to create the instance of the struct as well I don't have to declare the function for scope.

What is the better method? I have used both without problems but I have never really done any major testing on them. I should point out that I have gone with the instance of the struct because I understood that access a struct was slower then directly access the functions. Is this the case?

Thanks to all contributing to this topic, I think some valuable things are being covered.

But I'm affraid my original question is being overlooked, so let me give an example:

struct myStruct (

fn myFunction01 = (
myFunction02()
)

fn myFunction02 = (
-- do something
)

)

a=myStruct()
a.myFunction01()

This creates an error because the first function is calling a second function which isn't declared/defined yet. I would like to be able to not worry about what order my functions are definded within the struct because it can become quite a puzzle sometimes.

Jon-Huhn
11-17-2005, 04:43 PM
Ok, so now I think you guys are hitting my problem on the head! Thanks so much.

So Paul, it looks like you're using a "dummy" function definition to act as a declaration, and then you just re-define the function whenever you like. That's exactly what I was looking for.

Light, you've introducted my to and idea I hadn't thought of before; calling functions of a struct from the outside in. That may come in handy in the future, thanks.

Bobo, thanks for addressing the issue of using global structs to tidy up groups of related functions. That is also opening my mind to new possibilities...

PEN
11-17-2005, 05:02 PM
struct testSt
(
fn run=
(
stTime=timeStamp()
for x = 1 to 10000 do
(
testSt.myFn()
)
edTime=timeStamp()
format "Processing took % seconds\n" ((edTime - stTime) / 1000.0)
),
fn myFn=
(
print "This works"
)

)
testSt.run()

Processing took 12.766 seconds
Processing took 9.766 seconds
Processing took 9.985 seconds
Processing took 10.25 seconds
Processing took 9.734 seconds



struct testSt
(
fn myFn=(),
fn run=
(
stTime=timeStamp()
for x = 1 to 10000 do
(
myFn()
)
edTime=timeStamp()
format "Processing took % seconds\n" ((edTime - stTime) / 1000.0)
),
fn myFn=
(
print "This works"
)

)
testInst=testSt()
testInst.run()

Processing took 10.297 seconds
Processing took 9.703 seconds
Processing took 9.875 seconds
Processing took 9.703 seconds
Processing took 10.0 seconds



Processed both 5 times and those are the results. Doesn't look like there is a big difference in speed. So it looks like you only really need to use the instance if you want to get access to variables in the struct which I do use from time to time as I will store data collected in a struct that will be used by other structs.

And the last test without the struct:

global myFn
fn run=
(
stTime=timeStamp()
for x = 1 to 10000 do
(
myFn()
)
edTime=timeStamp()
format "Processing took % seconds\n" ((edTime - stTime) / 1000.0)
)
fn myFn=
(
print "This works"
)
run()

Processing took 10.359 seconds
Processing took 10.719 seconds
Processing took 10.516 seconds
Processing took 10.407 seconds
Processing took 10.515 seconds

eek
11-17-2005, 05:15 PM
Paul,

What if myFn has variables. Eg.

Fn MyFn a b = (

print a
print b
)

eek

Bobo
11-17-2005, 08:50 PM
Paul,

What if myFn has variables. Eg.

Fn MyFn a b = (

print a
print b
)

eek


Your function has PARAMETERS. Just pass them as parameters, they will be local to the function and garbage collected when the function exits.
Not sure what the problem would be...

CGTalk Moderation
11-17-2005, 08:50 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.