[Closed] include scripts not working?
I have a script that uses functions from another script.
So i start the main script with:
include "other_script.ms"
I see the text of other_script.ms pop up in the Listener, but when I subsequently call its functions in my main script, I get errors as if those functions are undefined.
Am I not using include correctly, or does it not function like an include in other scripting languages?
It sounds like you need to use FileIn instead:
fileIn "other_script.ms"
I find that I need to make variables global if I want to send them to or from a fileIn’d script – it seems that it runs the script and then “closes” it, effectively, so local variables from one cannot be read from another. Just a heads up, because I don’t think that’s the case with ‘include’.
If anyone can add more light, please do!
Running fileIn on two scripts is like executing two scripts in a seperate tab in Maxscript Editor. Global values will of course be accessible, but the local values will be separate and will return undefined if accessing them from outside the scope. It sounds like you should investigate structs, where you can have local values readable in both structs by nesting them in a master struct:
--Main ms file
struct exampleStruct (
localValue = true,
localValue2 = false,
msFile1,
msFile2
)
global example = exampleStruct()
--fileIn msFile1, file 1 would contain:
struct msFile1Struct (
fn doSomething = print example.localValue,
something = true
)
example.msFile1 = msFile1Struct()
--fileIn msFile2, file 2 would contain:
struct msFile2Struct (
fn doSomething = print example.localValue2,
something = false
)
example.msFile2 = msFile2Struct()
This is just one of the ways to use structs which I really like. It allows you to have one global value and access all instanced functions, values and controls within it, while splitting it all into smaller maxscript files. I’m half expecting someone on this forum to tell me that this way is not good now
There are a lot of other ways too that are very much worth reading:
http://forums.cgsociety.org/showthread.php?t=1068517
http://forums.cgsociety.org/showthread.php?t=1032455
I’ve just done a load of reading and I’m trying to get my head around this – I think part of my problem is that, whilst I’m familiar with nested “things”, I’ve never actually used Structures at all in all my maxscripting, so I’m trying to stack a few new concepts on top of one another at once!
As best as I can see, structures are like inventing a new class. So you declare a structure, and that structure has properties that you can define (almost like an array having values, but with given names instead of an index). However, the clever bit comes from having a structure be a property of another structure. so instead of struct01.height, you could have struct01.struct02.height. Am I right so far?
I also understand that you can define initial values (just like how you can define any variable when it is defined, or otherwise you can choose to not define certain properties of an object and they’ll revert to a default). By doing this, you can access data within a structure, almost like it’s a function declaring a global variable. Am I right so far?
I think what I’m not quite getting with this particular example is quite how this impacts fileIn’s. At what point are the fileIn’s being called? Are the msFile1 and msFile2 in the initial structure the paths, or the names, or the actual fileIn calls themselves? Or am I over-thinking it, and it’s simply that, later on, the localValue variables being called are done via the initial global calling of the structure into the variable ‘example’, irrespective of when or how they are called? In which case, what does the msFile1 mean in the initial structure?
Thanks very much for your help, this does look like a great way of working!
Edit: Ok, I think I’m getting it now! msFile1 and 2 are later defined as the new structures being created! Thus the nesting. And the contents of these nested structures can refer to the variables (that are never declared globally) in the initial structure. Do these have to be assigned to these variables afterwards then, rather than within the initial structure?
Yep, exactly. You can sort out all your structs into namespaces that make sense. It really helps organise things nicely.
Yep, also true. You only need one global variable to store the struct, and everything within that global struct, including structs within the main struct, and values within that, are now accessable globally via the struct (whatever.somestruct.value)
Yeah sorry that example wasn’t exactly that clear. Have a look at this where I’ve made it more obvious how to split it up and how you can use fileIn to fill your undefined struct values with another struct instance:
--Main ms file
(--Brackets around everything ensures every value is in local scope unless declared global.
struct exampleStruct (
localValue = true,
localValue2 = false,
msFile1,
msFile2
)
global example = exampleStruct()
fileIn "msFile1.ms"
fileIn "msFile2.ms"
)
--msFile1.ms would contain:
(--Keep everything in local scope, the only global value we want is the main struct instance.
struct msFile1Struct (
fn doSomething = print example.localValue,
something = true
)
example.msFile1 = msFile1Struct()
)
--msFile2.ms would contain:
(--Keep everything in local scope, the only global value we want is the main struct instance.
struct msFile2Struct (
fn doSomething = print example.localValue2,
something = false
)
example.msFile2 = msFile2Struct()
)
You are a scholar and a gentleman, thank you very much.
That said, for the sake of declaring global variables that you don’t really want to be global, there’s actually no need for the nested structures, right? The filein’s could refer to example.localvalue right off the bat? And they could also assign a value to a variable declared in the original structure too, to pass information back? I guess the usefulness of the nested structures comes in logically naming these variables, right? So that each fileIn could effectively have it’s own subset of variables within the main structure?
So for example, I have a set of scripts where one of the fileIn’s submits a job to backburner via netrender, and another which submits another job to backburner via cmdjob. This latter fileIn needs the job handle of the job submitted in the first fileIn. At the moment, I’m declaring that globally (so the last line of the first fileIn is: ‘global jobhandle = newjob.handle’). What I could do is have a structure in the main script called “rogerStruct” and inside that declare a variable called “handle”. This structure is applied to a global variable called “roger”. The last line of the first filein could then be “roger.handle = newjob.handle” and the second filein read this value too?
And, if I wanted to avoid confusion should I have a huge slew of variables, I could have a structure within both filein’s, so that I could later refer to roger.filein.var1 etc? Is there a use to this beyond cleanliness?
Yes and no. A fileIn always executes in global scope, so anything that the fileIn returns (for example an instanced struct) will become a global variable, which makes nesting structs completely pointless. You may as well have multiple global structs where you can access each others data by running struct1.value1 in struct2, and struct2.value in struct1.
Using the fileIn method I showed above, but enclosing every script in brackets ( ) at the very beginning and very end will ensure that the fileIn is kept in local scope, and the only global variable you have is the master struct. (I’ve updated the previous post to include the brackets I’m talking about here.)
Yes, this would work. In my example you can see that at the end of each fileIn I am assigning the instanced struct to the master struct.
Good question. Structs don’t really allow you to do anything you couldn’t do with hundreds of globals, but it sure makes things easier, tidier, and significantly reduces the risk of clashing global names with other scripts. Max 2010+ (I think) also introduces public and private keywords into structs which can be excellent if you would like to keep a function or value private and only accessible within the struct instance. There are also events you can add to a struct, for example “on create do ( whatever = something ; somethingelse = true)” which can be very useful.