PDA

View Full Version : Maya crashes when sourcing other scripts


th0rse
11-17-2009, 10:48 AM
This is a two question-thread:




I have noticed that sometimes, I have mel files in my scripts folder with some procedures that don't seem to be read when maya starts. If I try to call one of those procedures in maya without sourcing manually those files, they don't work.


On the other hand, I have a few scripts that call source some other scripts in order to work. In some scripts, when I do so, Maya crashes without giving any information about what happened.
I do that using something like:

// Sources scripts if needed
if(! `exists nameOfAGivenProcedure`)
{
source "nameOfTheArray.mel";
}

I do not understand why that happens. In fact, if you execute the code of the script, it works but when that other script tries to source it, it crashes. Any ideas?

Dave

norbertnacu
11-18-2009, 05:50 AM
Hi There,
I recommend on doing modules, and the reason for that is control, you can quickly distribute your scripts, plugins, icons, etc.. quickly. We're using that pipeline at work, because its easy to modify and its clean. I'm not sure how your pipeline works, but if your scripts are not sourcing properly it could be global and local proc? If that's not the case, then maybe your scripts are not located in the valid scripts directory. If your scripts are crashing then try the catch or catchQuiet command? Again I'm not sure how your pipeline works or how you guys distribute/update your system.

Thank You,
Norbert

th0rse
11-18-2009, 08:28 AM
I am a bit confused now.

I thought that modules exist in Python but not in MEL. Is that right?

I do not think that it is a problem with the scripts directory since I have them in the scripts folder. In fact, to make sure that the path is right, I type in Maya the following command:

internalVar -usd

That returns the folder where I have those scripts.
On the other hand, If I source the script manually doing

source "nameOfTheScript.mel";

It works just fine.

I am not sure about what you say about local/global procs. I have all the procedures defined in my script as global.

As an example:

Let's say that I have a script named dmVis.mel with this content.

global proc dmSetVisNone()
{
// Gets the active panel
string $activePanel = `dmGetActivePanel()`;

// Turns off the visibility of all elements
modelEditor -e -allObjects 0 $activePanel;
}


I have that script in my scripts folder
Then I restart Maya or I type "rehash"

Once in Maya, if I type:

dmSetVisNone

I get an error so I have to source the script manually, and then call the procedure again.

That would be OK but what I am doing is to have script files that contain many procedures that I use in different scripts.

Am I missing something obvious here?
Thanks in advance

Mark-J
11-18-2009, 08:58 AM
Ok a few rules and explainations. Firstly Maya has had module systems in it for many many years now, used as a distribution method for code bases. They're really easy to setup and manage code around studios because all environment paths are setup for you. We use a highly modified version of the modules here to control the entire studios code distribution. Just take a look in the Maya manuals for 'modules'.

Now the issue you've probably got is in naming of procs and scipts. When Maya passes the scripts folder on boot it just builds a table of the names of the scripts, NOT the procs inside them. So in your example you have a scripts file called dmVis.mel, which means all that's entered in the scripts table is dmVis. You can't simply add global procs inside this and expect Maya to find them UNLESS the proc in the script you're calling is the same name as the file itself, or you've called a source cmd on it. So if you renamed dmSetVisNone to dmVis it would be found without sourcing.

The reason it works when you manually call 'source' is because that command passes all available global procs in the script, making them ALL available. Normally a script would have an entry point that's named the same as the script name (if it's a tool that would be the UI call).

Hope that helps

Mark

th0rse
11-18-2009, 09:41 AM
Firstly Maya has had module systems in it for many many years now, used as a distribution method for code bases. They're really easy to setup and manage code around studios because all environment paths are setup for you. We use a highly modified version of the modules here to control the entire studios code distribution. Just take a look in the Maya manuals for 'modules'.

I've tried to look in the documentation for "modules" but it shows up things related to the API. I always thought that if you use the API, you have to be using C++. Is it possible to do what I am trying to do with mel? Of so, could you please guide me in the right direction?

When Maya passes the scripts folder on boot it just builds a table of the names of the scripts, NOT the procs inside them. So in your example you have a scripts file called dmVis.mel, which means all that's entered in the scripts table is dmVis. You can't simply add global procs inside this and expect Maya to find them UNLESS the proc in the script you're calling is the same name as the file itself, or you've called a source cmd on it. So if you renamed dmSetVisNone to dmVis it would be found without sourcing.

The reason it works when you manually call 'source' is because that command passes all available global procs in the script, making them ALL available. Normally a script would have an entry point that's named the same as the script name (if it's a tool that would be the UI call).

That makes sense.
In fact, that means that my way of sourcing scripts is not accurate either because it only looks for one of the procedures inside of the file and not all the possible procedures:


// Sources scripts if needed
if(! `exists nameOfAGivenProcedure`)
{
source "nameOfTheArray.mel";
}

Thanks for your time Mark and Norbert

norbertnacu
11-18-2009, 01:56 PM
Hi There,
I wasn't talking about Python's module, I was actually talking about Maya's module (Folder Structure, Scripts, Icons, Plug-ins, etc) system. Please read the link below.

Distributing Multi-File Modules (http://download.autodesk.com/us/maya/2010help/index.html?url=WS1a9193826455f5ff5cf1d02511b1d000978329c.htm,topicNumber=d0e655307)


// ie..
1. Download BonusTools (http://area.autodesk.com/bonus_tools)
2. Once the installation is complete, create a folder called modules in your script directory.
- C:\Users\XXX\Documents\maya\2010
3. Create a bonusTools.txt inside your modules folder, and append this code:

// the basic format is:
// + bonusTools “bonus tools version” “absolute path to bonusTools directory”

// sample windows path
+ bonusTools 2010 C:\Program Files\Autodesk\MayaBonusTools2010


As you can see, that setup is pretty simple and its easy distribute and update. What you can do is put all your scripts in a network drive, and add the modules folder in your co-workers script dir with the YOURCOMPTOOLS.txt. That's the old school way, what I did at work is use P4 to auto load/update our scripts, plug-ins, etc.. (Using the module system), so once the user open Maya, I call a simple C# application that I wrote, that talks to P4 and check if the user needs to update their scripts, plug-ins, etc..(Kinda like Windows Pop-up Window if you need to update).

Local/Global proc:
If you have a script that has a local proc, that other scripts wont be able to access that proc, cause its local proc. I don't use local proc, just be smart on how you rename your procs and everything should be fine. Here's my technique:


ie..
// EAC_CharacterGen.mel
// Company Name + Script Name
// Electronic Arts Canada + Character Gen
global proc EAC_CharacterGen()
{
// code
// code
// code
EAC_CharacterGen_UI();
EAC_CharacterGen_RecallUI();
}
// and inside the script, you can keep adding new proc:
// I usually append the Company Name + Script Name + Type
global proc EAC_CharacterGen_UI()
{
// code
// code
// code
}
global proc EAC_CharacterGen_RecallUI()
{
// blah
// i love taters
// blah
}



Assuming everything is good with your setup. I would double check your scripts name and proc name (name clashing?). BTW I used to your technique before :


global proc int IsProcSource()
{
// code
// tater sauce
// code

return true;
}


We have at least 200+ scripts [Static, Modeling, Characters, Animation, Weapon, and Vehicle Team] (Maya is fast enough to digest all those scripts without slowing it down). I used to check if a proc/script has been sourced, it was a headache and it will just get messy later on. I'm not gonna even talk about maintenance, update, renaming, etc...

Can we please see the error you're getting?

I hope this helps,
Norbert Nacu

th0rse
11-18-2009, 02:31 PM
I didn't know about modules! I'll try to use that to get my scripts working

All the procedures that I use are global, so that should not be the problem

Unfortunately, I can't show you the error that Maya gives because the error, closes Maya.


Thanks a lot

th0rse
11-18-2009, 03:16 PM
I think that I understand how modules work now

Even though that I will be able to update the scripts folder of the whole company in an easier way, the thing is that I will still face the same problem. I need to source a few files.

I have files like "dmUITools.mel" with some procedures related to UI
Should I create a file for every single procedure and name it the same to have access to all the procedures without sourcing each file manually?


Thanks


Dave

norbertnacu
11-18-2009, 04:12 PM
Hi th0rse,
Here's my rule:

1. If your script is more than 200 lines, then try breaking your proc up into modular pieces.
- It's easy to maintain
- It's nice and clean
- It's easy to debug
2. If your proc is gonna be use somewhere else then add it to your library.
- UI_Library.mel
- Modeling_Library.mel
- Rigging_Library.mel
- etc...

I have those scripts in my library folder, so before I ran any script I make sure I source those guys first :)

BTW how many MEL scripts do you have (You don't have to answer this - NDA :p)? So we can easily debug your problem?

Thank You,
Norbert Nacu

th0rse
11-18-2009, 04:26 PM
1. If your script is more than 200 lines, then try breaking your proc up into modular pieces.


I always try to split my scripts as much as possible into different procedures. I can take a look and see which ones can be put in modular pieces (Which will mean to have a file for everyone of those pieces, right?)

2. If your proc is gonna be use somewhere else then add it to your library.
- UI_Library.mel
- Modeling_Library.mel
- Rigging_Library.mel
- etc...


I have those scripts in my library folder, so before I ran any script I make sure I source those guys first :)


That sounds like a good idea.

So I think that I should put all the scripts into modules and have the name of the file to be the same one as the main procedure. If that script uses more procedures that are unique to that script, they should be put in modules (with the same name as the procedure) as well so I can update and the whole thing in an easier way and still works.

On the other hand, the procedures that are used by more than one script should be in a library folder that I update using a module as well. The difference is that the script that is using them, will have to source those library scripts and can have a different name, right ?

Should I always source those files when using them? I mean, is it a problem to source them more than once if more than one script is using them?

BTW how many MEL scripts do you have (You don't have to answer this - NDA :p)? So we can easily debug your problem?


I have up to 35 mel scripts and some of them have several procedures.

Thank You,

David

Mark-J
11-19-2009, 08:03 AM
It's definately worth building some form of standard lib scripts, things like stringUtils, fileUtils and referenceUtils. The one issue with modules is there's currently no entry point to them. By this I mean there's no mechanism to add a specific set of instructions. We've heavily modified the module code so we have our own version of the userSetup script per module, this then modified all the environment paths on the fly, allowing things like sub-script folders in the modules etc. (we run abour 11 different modules, making it easy to load and unload bulk code).

In general where you're calling these lib procs I'd just add a dependancy call. Maybe a small proc at the top of complex scripts called dependencies, all source calls are in this and you just run the proc at the head of the code. This way it's really clean and easy to see what that code is calling.

Failing that add the source calls to your library to the userSetup.mel. . . OR write a resourceAll proc that resources all scripts in a folder in one hit. Something we do for core lib code.

hope that helps

Mark

th0rse
11-19-2009, 08:30 AM
It's definitely worth building some form of standard lib scripts, things like stringUtils, fileUtils and referenceUtils. The one issue with modules is there's currently no entry point to them. By this I mean there's no mechanism to add a specific set of instructions. We've heavily modified the module code so we have our own version of the userSetup script per module

This is getting interesting. If I have a userSetup.mel in a module, would Maya use the one in the module instead of the one in the scripts folder ??

I so, What happens if some modules have that file??
Another possibility is that Maya executes all of them (Plus the one in the scripts folder)
How does it work?

this then modified all the environment paths on the fly, allowing things like sub-script folders in the modules etc. (we run about 11 different modules, making it easy to load and unload bulk code).

I am not sure that I understand what you are saying here.
Are you setting environment paths on the fly? And does it do that before loading more modules so the ones in those get loaded as well?

In general where you're calling these lib procs I'd just add a dependency call. Maybe a small proc at the top of complex scripts called dependencies, all source calls are in this and you just run the proc at the head of the code. This way it's really clean and easy to see what that code is calling.

So you mean that in my complex scripts (The ones that use libraries), I should create a procedure at the top of the file, so I can see which libraries is using with a glance, right?

Is it a problem to source the same file more than once?
What happens if a library has to source another library? What's the best way to approach the problem?

Failing that add the source calls to your library to the userSetup.mel. . . OR write a resourceAll proc that resources all scripts in a folder in one hit. Something we do for core lib code.


So for the procedures that I always use, I should go for the resourceAll script, sourcing every single file in a folder. That make sense but who would call that script? All the complex scripts? The userSetup.mel?

Sorry about all these questions but I just want to make sure that I understand what you guys are saying.

Thanks,


All the best

Mark-J
11-20-2009, 09:12 AM
This is getting interesting. If I have a userSetup.mel in a module, would Maya use the one in the module instead of the one in the scripts folder ??

Unfortunately no, the module system only adds the paths to the Maya Scripts and Plugin environments, it doesn't do any sourcing of the code. This is a bit of an issue if you want sub-folders in your modules since they wouldn't get added to the scripts path, and one of the reasons we've re-written the module systems to give us more flexibility.
Another issue is that if you have any plugins in the module plug-in folder they'll be loaded from that module location. So if you're running a server based studio wide module the plugins get locked and you won't be able to update them. Again, we've modified so we re-path and copy plugins locally to release the master mll's on the server.

Are you setting environment paths on the fly? And does it do that before loading more modules so the ones in those get loaded as well?
We have an entry point into the modules that we've added, effectively giving us our userSetup per module. This means that we can modify everything about that module when it boots. For example adding subfolders with:
putenv MAYA_SCRIPT_PATH ($module + $x)
putenv MAYA_PLUG_IN_PATH ($module + $x)
If fact there's not a lot about the default modules we actually use anymore.

So you mean that in my complex scripts (The ones that use libraries), I should create a procedure at the top of the file, so I can see which libraries is using with a glance, right?
For complex tools that rely on many library scripts, or source calls yes, this way you have a single point to look at for your dependencies.

Is it a problem to source the same file more than once?
What happens if a library has to source another library? What's the best way to approach the problem?

Sourcing multiple times isn't an issue, don't worry about it. As for libs relying on other libs, well that all depends on how you structure you're library. We have a 'resourceall' call that actively sources all the lib code during boot so we no longer worry about that.... bit like in python where you'd add an __init__ file and add standard packages to it so you know they're always up and running.. ie, you know that you'll maya.cmds and maya.mel so we just add them on boot.

So for the procedures that I always use, I should go for the resourceAll script, sourcing every single file in a folder. That make sense but who would call that script? All the complex scripts? The userSetup.mel?
No.... sourcing all straight of the bat is bad practice, as I said, we only do this for lib / util scripts which we know everything relies on. For tools and standard stuff we still use source calls, usually when the tool's UI boots (or rather, when the entry point code is called)




hope that helps




Mark

th0rse
11-20-2009, 09:46 AM
It does help Mark

Thanks!

CGTalk Moderation
11-20-2009, 09:46 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.