Python tools that work in Maya and 3dsMax, possible?

Hey folks,

I’m wondering if anyone has tackled building set of tools that could work in both 3dsMax and Maya. The reason I’m asking is because, even though we were originally a 3dsMax shop, we’ve got a project that launched in Maya (in retrospect it was a bad idea). We’re just a few TA’s in the shop, and I feel that it makes no sense to have to port tools to accommodate various 3d platforms. I’ve made a plea to migrate our future projects to Maya, however in case we remain in 3dsMax has anyone had experience building for both platforms?

Because 3dsMax now has Python support, I thought of migrating our tools to Python and Qt. The concept is to build a single UI framework, but interface with the appropriate module based on what 3d software platform is running. That being said, it seems like a huge undertaking, namely because we’d have to build abstract classes for most of the data, and two set of functions based on what software we’re pulling and setting the data. It just seems like too much work for the amount of TAs (not to mention most of us are overlapping on three projects). It also feels like unless we build this efficiently we can end up with really slow/unresponsive tools.

Most of our existing tools are in Maxscript using .NET as UI, which makes me question even further whether the investment is worth the trouble. Don’t get me wrong, I’ve been dabbling in Python and QT the last few weeks, and I’m in love, it’s just that I can easily see this idea turning into a majestic puzzle.

Any thoughts or insight would be helpful.

Also has anyone have experience with Blur-Dev? It seems like a really novel approach to using Python in 3dsMax, but I haven’t heard any studios going exclusively with this solution (outside of Blur obviously).

Thanks!

CL Audio

I’d worry more about sharing functional code first and UI second. It would be pretty simple to share a module that, say, talks to a database or checks the status of files on disk or make sure things go into the right place on a server as long as the interface and the functional code are split out.

You can certainly determine which environment you’re running in and load a different module conditionally - that’s what the python OS module does for os.path, for example. You don’t want to do that too much - shared could should be mostly shared! - but it helps you with the unavoidable parts.

If your shared tools are complex and have lots of UI, they might want to be a standalone apps (in QT, or TK or another python GUI toolkit) which talk to either Max or Maya via a TCP server. That makes sure your functional code is always the same and pushes the platform specific differences out to the details of how to manage the TCP connection.

Making nice UIs however can take the most time. Sometimes the tool is really simple and then controlling those few command line parameters via a nice UI is where all the work is in. If you can reuse the UI then you’ll save yourself a lot of work. We have tools like that, which talk via TCP, but the TCP part, and controlling an external Python process from Max isn’t that funny. Personally I’d LOVE to experiment more with 2014, but we just didn’t have any chance to do that yet. … and we have to support older Max versions too due that we’re an outsourcer. But I really have high hopes for using Python directly in Max.

For Max, Maya specific parts, make sure you plan this carefully. Inheritance can be a good method to avoid having lots of code that goes like “if MAX then…else if MAYA then…”. Also research your 3rd party modules carefully! Nothing sucks more than writing your codebase around a python module that just won’t compile with the next VC version Autodesk choses to use for their products. i.e. stay away from C based modules unless they’re well established.

@Theodox: thanks for the TCP connection suggestion. It’s something another TA where I work suggested but I never considered it myself (or even knew it was possibly in 3dsMax). I’ll look into it once I get confirmation.

@RobertKist: have you had success using a TCP server to communicate with 3dsMax? It sounds like you’re talking from experience, albeit painful experience.

Until I get further info from our IT department and managers, I’m holding off on the idea. I’m focusing entirely on Python-ifying our current maxscript structs which won’t be wasted time.

Thanks for the insight.

I programmed a .NET library - basically a DLL - which I load in 3ds Max. From there I call the Python interpreter and a script. Then I use sockets and JSON-RPC to communicate between them.
Some tips:

  • make sure you have logging on the Python side or pass though any output, or else you will have no idea why the thing is not starting/crashing/doing something else.
  • have a way to deal with runaway Python processes so that you can re-start your tool without keeping dozens of python.exe’s running in the background.
  • if you need 2-way communication it gets more difficult. We wanted to control Max from Python and vice-versa.
  • if you want to use Qt, you should also consider where to put the DLLs and how to avoid conflicts with other Qt installs on the same machine. Same goes for various Python versions.
  • you can use the same .NET code on all max versions, no need to recompile or anything (great!)
  • you may still need to code some parts in MXS though.
  • .NET events sometimes don’t work triggering MXS. We had some weird crashes here and there when triggering max functions from Python->NET->MXS.

Overall the solution works fairly reliable. It’s not super fast. It’s not always as elegant as a built-in solution would be. The fact that you have to deal with 2 independent processes (Python, Max) makes debugging and troubleshooting more complicated.

I have to add that as an outsourcer we have almost a dozen different Max versions (down to Max 9.0 x86/x64 used by a Chinese client), and many different machine setups (with and without client tools interfering). If you have a homogeneous environment, then your work will be MUCH easier. That’s why I’d think using an integrated Python would be easier - at least you don’t have to deal with all the other stuff that’s interfering because Python is built-in.

We have some tools that work in both. Using sockets in maya and com in max. We also have tools that are integrated (standard py in maya and blur’s python bridge in max) and share the same UI etc. and load different “bridges” depending on the application context they are started in.

I assume the latter is kind of what you are looking for. What we do in this case is create a base class containing all the application specific commands as not implemented methods (raising NotImplemented if called directly, or inherited and not implemented).
Lets say this is ICommand.py. Then we have a MaxCommands.py and a MayaCommands.py, that contain a class inheriting the baseclass and implement the application specific methods. Then the app checks which context it is beeing started in and sets an internal variable (e.g. something like self._commands) to the corresponding module. The tool itself always calls self._commands.method() in turn.

Cheers,
Thorsten

Sorry to revive this aging thread. Just wanted to share this about Namespace packages for shared DCC’s code & tools.

We do quite a few shared Python DCC tools and lib’s. With 3dsMax in the mix, this has recently gotten way easier with official Python and PySide support (though MaxPlus is pretty immature, but that’s another story).

One thing we wave have been using is a “namespace package”. This allow’s several folders on disk to merge into one logical namespace, using package utils (pkgutil). So we have something like the following folder structure:

shared_code/my_package
max_code/my_package
mobu_code/my_package
maya_code/my_package

Here Maya’s Python Path will include both “shared_code/my_package” and “maya_code/my_package”.

This way, anything in “shared_code/my_package” and “maya_code/my_package” is available in the same namespace and can import freely from one another etc. Works for sub packages too and PyCharm totally get’s it, unlike with other methods I’ve tried, where introspection and code completion broke down.

If something is defined in both folder locations, it’s the order of these folders on the Python Path, that dictates which module takes precedence. You can use this to create “local overrides” and I’ve set set it up, so the application specific folder overrides the shared folder. This detail has turned out to be pretty useful.

The only issue I found, is that a *.pyc file in one folder might “override” a *.py file in another folder. This can can cause unintentional “local overrides”, say you have removed a *.py file from source control, but the user still has the *.pyc file on disk. The solution was to delete any *.pyc files from disk as each application launches. Seems a little dirty, but has worked so far.

I’m pretty pleased with this setup.

I also posted this on my blog:
http://www.sunekempf.com/blog/?p=459&preview=true

Im working on a multifunctional tool right now to do exactly what you are talking about. Only it wont just be Max and Maya it will be a multiple Tool. I have the GUI created the hard way outside of the packages so that makes it independent from all. The hard part I am still working on altho Mobu, Maya and SoftImage are shaky it still outputs the right way for each individual package.

I have a decent amount of work left because my deadline will appear shortly but to make it easy to understand 1 GUI multiple selected modules per package and select from a drop down. The GUI has its on proprietary solution to detect the package. With lots of features included.

Its all I can say for now but I can give a demo in a few weeks if you all keep following.

@Sune: I ended up doing something similar, but manually by determining what software you’re running in and swapping namespace based on the result (import max.scene as scene, or import maya.scene as scene, etc…). In the end the whole idea was dropped, as it was decided it was overkill.

Regarding your .pyc issue, you can possibly use sys.dont_write_bytecode = True to prevent them from being built.

@PadraigOCuinn: I’m definitely curious as to how far you get. So far, MaxPlus has been useful for basic things but there are still many classes that remain unwrapped or incomplete (AppData, ITrackViewNodes, etc…).

@Sune: I ended up doing something similar, but manually by determining what software you’re running in and swapping namespace based on the result (import max.scene as scene, or import maya.scene as scene, etc…). In the end the whole idea was dropped, as it was decided it was overkill.

Regarding your .pyc issue, you can possibly use sys.dont_write_bytecode = True to prevent them from being built.

@PadraigOCuinn: I’m definitely curious as to how far you get. So far, MaxPlus has been useful for basic things but there are still many classes that remain unwrapped or incomplete (AppData, ITrackViewNodes, etc…).

sorry about the very late delay, it has been a very intense few years haha. I have the tools all complete and will be able to show you as soon as I locate my other HDD. I you are interested I can also show you some tutorials to speed up the process. I hope you had a good 3 years haha