PDA

View Full Version : get a string thats defined in a proc


Gabester
09-06-2005, 03:45 AM
Hi All,

Is there a way to get a string that has been defined in a proc after a series of events?

I don't want to recreate the series of the events outside the proc, just want to take the variable, and say, this is now a global variable and it will exist outside the proc.

mhovland
09-06-2005, 04:39 AM
Just declare the variable you want to store the info in as a global at the beginning of your proc, and also make sure to reference the global variable at the start of any procedure you want to use the variable in.

For example:

global proc myProc()
{
global string $myGlobal;

//do all kinds of fun stuff to strings here
//and store the result in the variable from above.

}

global proc myProcAgain()
{
global string $myGlobal;

//now you can use the info in the $myGlobal variable
//in this procedure
}

Hope that helps.

john_homer
09-06-2005, 06:42 AM
I never use global veraibles, because they are evil...
I'm not saying never use 'em, but I have only had to once EVER.

you can generally pass them between procs...

just my 2c
.j

kletterget
09-07-2005, 04:23 PM
Why are they so evil? I kinda use them all the time- mostly if I write an MELscript which has an UI with options, and I want these options to be remembered even if the user deletes the window.

It'd be good to know if this is the wrong way of going about things.

/c.

PS: does your opinion on global variables include global procedures?

GennadiyKorol
09-07-2005, 04:40 PM
I also use global variables a lot, it's much more easier to have like a global storage of values and then each procedure will take what it needs from there. If you parse the values through the procedure itself, in complex scripts you're ending with tons of input values for a procedure, one call of the procedure with all variables will be one column long, not the best solution. Also the undo issues can show up when not using global variables, in cases when you'd use the scriptJob with compressUndo flag. The global values that the procedure changed will not be global, and won't be undone this way. I've tried writing a couple of scripts without global proc, I also thought they are bad somehow. It turned out to be very complicated. In cases of complex scripts it's almost impossible to keep the track of the flow of variables from one proc to another, not even talking about the discribed issues. The only difference between global variables is that they are defined once and you aren't able to have more than one variable with the same name. By using nice naming convenctions you prevent any errors that could show up.
Also about the memory usage, global variables take less place in the memory than local ones, cause every time the procedure is called, an instance of it's local variable is created again, so each call produces new variable in the memory, which is much more memory expensive. That's why I always suggest to cleanUp the array, string variables inside of the procedure once you don't need them. Just keep your names unique and you will have no problems using global procedures.

Cheers :)

Winner
09-07-2005, 09:35 PM
yeah why so evil ?

john_homer
09-08-2005, 06:19 AM
PS: does your opinion on global variables include global procedures?


haha, no.


Also about the memory usage, global variables take less place in the memory than local ones, cause every time the procedure is called, an instance of it's local variable is created again, so each call produces new variable in the memory, which is much more memory expensive. :)

ummmm.. global variables sit in memory untill you manually clear them or quit maya, its local variables that only exist (and use RAM) while they are needed.
All those local "instances" disappear when the proc is done.

I have had bad experiences with them, and I'm not going to go into what the script did..blah blah, but I have been screwed by them (in scripts written by other people) especially if there are 2 versions of maya running.

hay, thats just my opinion (and the other scripters), I'm certainly not telling anyone what they can and cant do. well not people on the internet anyway.... :thumbsup:

:wavey:
.j

GennadiyKorol
09-08-2005, 12:27 PM
Well, nobody is telling anyone what to do, we are just discussing something. I think we all learn by sharing our experience, that's what forums are for, right :)?

About memory, I didn't like speaking without having actual facts, so I made some memory usage tests and I should say it looks like we both are wrong.

Here's what I did:


float $OldMemory[], $Memory[];
proc Bob()
{
string $BobArray[];
for ( $i = 0; $i < 3000; $i++)
$BobArray[$i] = ("Bobby"+$i);
}

global string $BobGlobalArray[];
proc Bob1()
{
global string $BobGlobalArray[];clear $BobGlobalArray;
for ( $i = 0; $i < 3000; $i++)
$BobGlobalArray[$i] = ("Bobby"+$i);
}



Here I've defined two procedures. One of them called "Bob" creates it's own local variable and supplys 3000 values there.
The second procedure uses the defined global variable and just rewrites it with the "new" values, by first clearing the array, secondly by filling it up with values just like the first proc.


for ( $d = 0; $d < 8; $d++)
{
for ($i = 0; $i < 100; $i++)
{

Bob(); // currently tested procedure

}
$Memory = `memory -he`;
print ("\n"+ ($Memory[0] - $OldMemory[0]));
$OldMemory[0] = $Memory[0] ;
}


This part of code runs our procedure in a cycle many times to better see the effect.
Then I read the current memory heaped by maya, substract from it the old memory value and print it. This way I have like a "delta" memory which the procedure call has taken.
Then I loop this again 8 times to make sure I get rid of all possible little foults and see the results clearer.

Well, and this is what I've got:
This is for Bob procedure, that uses local variable:
5.76171875
5.63671875
5.6328125
5.62890625
5.6328125
5.6328125
5.6328125
5.63671875
This is for Bob1 procedure, that uses global variable:
5.63671875
5.625
5.640625
5.62890625
5.6328125
5.6328125
5.6328125

The conclusion I can make is: The memory usage in both cases is equal. I found no way to clean up the memory after the procedure, not by fushing the undo, not by clearing the array.
Also turning off the undo at the time of the operation or clearing the array won't affect memory by any way! I just got the same results. Looks like all that maya stores into memory is the "action" itself. Depending on the size of the array itc it can vary, but it's the same for all type of variables and any usage ways. Looks like MEL is not dealing with memory as API does, so cleaning up the procedures members won't result in memory reduction, MEL just stores the action, i.e. what procedure did and there's no way to go back. I think that's great advantage of API.
Though the real procedure, even complex will take much less memory than my test procedures cycled did, though the tendention is clear.
Thanks, hope you've learned something from this little report :)

Mikademius
09-08-2005, 02:04 PM
I had a UI with buttons that called procs from the scripts to execute. They wouldn't execute unless I had global procs. Is it so that you have to use global procs if you are using them in a UI? And only local if you are using the procs within the script itself??

john_homer
09-08-2005, 09:15 PM
interesting Mr.HawK, although I didn't have time to do the tests myself, I'll take your word for it.

I had a UI with buttons that called procs from the scripts to execute. They wouldn't execute unless I had global procs. Is it so that you have to use global procs if you are using them in a UI? And only local if you are using the procs within the script itself??

I do it all the time without globals...
can you supply an example... a simple one??

.j

Mikademius
09-08-2005, 10:17 PM
I'd like to post a simple one, but then it would probably work with a local one :p
It works if you copy the whole script into the shelf, but if I source it it goes global :banghead:

Sorry for not going simple, but here's the script:
shaderAssigner (http://www.final3.com/html/shaderAssigner.htm)

EigenPuff
09-09-2005, 12:36 AM
I find that the biggest advantage to avoiding global variables in general (besides helping you make assumptions in debugging) is that it allows you to "package" a proc so that you can carry it around, and apply it in different places more easily - all you have to know is what to put into it and what to expect out of it. And just by writing your script so that it is structured that way tends to make it easier to follow, and then easier for you to fix later on down the road.

IMHO, if MEL would support user-defined types (structs, records, aggregates, what ever you want to call them) like most other programming languages (including MaxScript), then this would also go a long way to helping to package data together so that globals wouldn't be so necessary.

The main reason for global/local distinction is code clarity, which ever makes your stuff easier for you to follow without getting confusted is probably best. Incidentally, I try to make my proc's local unless I absolutely have to. But then again I am a programmer, and I think funny.

Incidentally, the memory usage difference between globals and locals isn't as important. You can construct situations where you can have more memory usage in either case - especially if you have a lot of functions that call other functions and get pretty deep - but an int/float is probably 8-20 bytes, a string is probably 20 + however many letters it has; and a model will probably around 10,000 - 1,000,000 (~10k to ~1Mb - lets not get started on textures..), so local variables used by a scripting system can be pretty insignificant by comparision. When maya has claimed a gig of your memory for large scenes, you can be pretty sure that scripting variables are probably not the problem.

EigenPuff
09-09-2005, 02:01 AM
More on why globals are "evil": just looking over MohvLand's example on how to use globals reminds me of another reason why one usually avoids globals if they can (which may not necessarily always be the case, or the best option, either).

Take a look at MyProc() and MyProcAgain(). Now, let say we also have MyProcAThirdTime(), MyProcYetAgain(), and MyProcGodWillItEverEnd(), and we have a bug that pops where that global string has been changed to some unreasonable and horrible value. We have to hunt through all of those functions before we find out that the bug is actually in MyProcIBetNobodyWillNotice() that was added late last night by the intern. If you keep your data locally then either a) it doesn't get passed around; b) it gets passed around and you can follow the chain; or c) it gets passed everywhere which lets you know that it might be a good idea to redesign your stuff.

I'll shut up now :)

GennadiyKorol
09-09-2005, 02:19 AM
Well, for such scripts it's ok, but for one I wrote just now it is very hard to make everyhing work with local variables. It's an interactive tool. I have dynamic scriptJobs with only one command that decides what to do based on global variables, so I can undo that command without any problems. Also I need some data to use almost everywhere through the script, parsing it everytime will be simply impossible in my case, cause some procedure changes that global value, other reads it etc. Trying to make it flow from one proc to another will be real pain in this case.
If you want take a look at it, it's my latest Local Tools script: http://forums.cgsociety.org/showthread.php?t=273254
But that's only for interactive tools and such I guess, I should admit MEL is pretty unsuited for that, API with it's private members for the object and stuff is much better. For any other type of scripts like UI stuff etc I think local procedures will do just fine. It's the matter of the need, I would also avoid declaring another global variable when I simply don't need it.

Just my experience again :)

But, let's talk about global/local procedures now, any opinions on that?

Mikademius
09-09-2005, 08:44 AM
Thought I should dump this one in here too. Maya uses more memory dividing things so instead of dividing let's say 6 with 4 (6/4) multiply it with 0.25 ;) Something to remember if your script relies heavily on math.

Robert Bateman
09-09-2005, 10:20 AM
avoid global variables as much as possible. In maya you really shouldn't need to use them. If the global needs to be defined for a scene, store it in a node. If you need global tool settings, use option var.

Mr.HawK, the problem you are describing is basically the reason why globals are bad. As soon as you use one, your code 'touches the ground' so to speak. It's ok to walk with a foot on the ground, however it gets a lot harder if you need to keep your nose, all 10 fingers and your knees on the ground etc....

In your case, if the data is needed thoughout the script, should it not be in a node and therefore accessible via getAtr/setAttr?

Bear in mind that mel is not structured (ie, has no struct as in C). It really is not designed to store data..... merely manipulate a large data structure (the Dependency graph). At least data stored in a node can be deleted.....

(and yes, adding global variables does affect your memory usage within maya)

Having said all of that, globals are sometimes required for specific UI elements, contexts etc. But keep it to a minimum.

Robert Bateman
09-09-2005, 10:22 AM
Why are they so evil? I kinda use them all the time- mostly if I write an MELscript which has an UI with options, and I want these options to be remembered even if the user deletes the window.

It'd be good to know if this is the wrong way of going about things.


yes, optionVar is there for that exact purpose with the benefit that those settings are stored for the next time you run maya....

GennadiyKorol
09-09-2005, 06:47 PM
Well, in my script global variables are stored inside an attributes of the object created by script and atributes are rewriten when needed so the scene could be easily opened and the tool could finish itself without any problems or if the crash occured. But I'm using globals very often, I change them during the procedure. It was simply easier to set/read a variable than each time read it to an array and get values from there, or clean the attribute every time and assign new values. I agree I could write procedures that would do that though, though it would be a bit slower, see my memory tests, every call to something uses string arrays, reads them, setts them etc fills memory up. So a procedure that will take a string array attribute and say return some item of it will fill memory with the size of the string array on each call, since I'm using the globals a lot this will be much more memory expensive. Instead of that just reading a global variable directly or setting it directly will take no memory, thus is much faster on complex meshes and scenes. But that's again I had to do that due to the script I wrote, you should just think what will bring/take out each method you use in the script and take the fastest/reliable one for the task.

lucille
09-12-2005, 02:11 AM
I think an issue that has been neglected here is when I use a global variable in a script--
I have no idea where or how this value was defined.

2 examples

String $myArray = `returnSelectedCharacterJoints`;

global string $myArray[];

I the first example--I can go right to the proc that defined the variable; in the second
example I have to parse through all possible uses of $myArray, including those that
may be defined in other scripts. No thanks.

CGTalk Moderation
09-12-2005, 02:11 AM
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.