• 1/3

Py3dsMax: Python scripting for 3ds Max from Blur Studio

Posted by Christopher Diggins, 9 June 2011 8:00 pm

Many 3ds Max customers have expressed an interest in writing Python scripts for 3ds Max that are compatible with CPython so that they can use some of the popular CPython specific extensions such as NumPy and SciPy, the Python Imaging Library, and cross-platform UI toolkits like PyQT.One solution that exists for running CPython scripts from 3ds Max that provides MAXScript interoperability is the Py3dsMax plug-in from Blur Studio. Currently only 3ds Max 2009 to 3ds Max 2011 are supported, but Blur say they are actively working on supporting 3ds Max 2012.

Py3dsMax is part of a large package of open-source tools and scripts from Blur available on Google project hosting that includes a redistribution of the PyQT cross-platform GUI library.

Installing Blur Tools and API

Before installing the blur tool set I strongly recommend that you carefully read the installation guide otherwise you risk installing twice (like I did). Even though the Blur tools comes with a self-installing package (MSI) the default locations provided by the installer will not work, and instructions provided during the installation process are minimal. Also not that despite giving you an option to provide paths the installer will still write a number of files to the hard-coded path “c:blur”. 

Blur Dev Package Contents

The Blur package contains a lot of different tools and plug-ins used by Blur Studio. Some of the more noteworthy contents include:

  • Py3dsMax - A MAXScript extension plug-in that allows Python to be called from MAXScript and vice-versa. See: http://code.google.com/p/blur-dev/wiki/Py3dsMax .
  • Python Logger - An interactive Python interpreter, like the MAXScript listener.
  • Onion - A layer management system built using Python.
  • Blurdev.gui Module - A GUI library to facilitate launching PyQT interfaces from different digital content creation tools.
  • Blurdev.elemental Module - A generic framework that is under development for generating node-based tools and flow charts to solve various programmatic tasks in a visual way.
  • PyQT - A third-party library that provides a Python interface to the QT framework for buildin cross-platform graphical user interfaces (GUIs). See: http://code.google.com/p/blur-dev/wiki/PyQt.  
  • Treegrunt - A generic tool and script management system and framework used by Blur Studio. For more information see: http://code.google.com/p/blur-dev/wiki/Treegrunt.
  • Blur IDE - An editor for scripts and developing Treegrunt tools. For more information see: http://code.google.com/p/blur-dev/wiki/BlurIDE.

The rest of this blog post focuses primarily on Py3dsMax and PyQT, but I recommend taking a hard look at the other tools to see if they are useful

Calling MAXScript from Python

Once installation is completed successfully the next time you start-up 3ds Max you should see a new menu-item called “Python” to the right of the “MAXScript” menu item. I suggest starting by choosing “Show logger…” which will open a nifty Python console with syntax coloring. From this point you can write commands to have executed by the Python interpreter. For example:

>>> 6 * 7
42

To interface with MAXScript you need to import the “mxs” class from the Py3dsMax module.

>>> from Py3dsMax import mxs

The “mxs” module provides access to all of the global functions and variables of MAXScript. For example to create a teapot in the scene try:

>>> teapot = mxs.Teapot()

To actually see the changes in the viewport you have to click anywhere on a viewport with your mouse or type:

>>> mxs.completeRedraw()

Creating an object with named parameter is similar to MAXScript, for example:

>>> mybox = mxs.box( length = 20, width = 20, height = 20)

You can then change properties of the box easily:

>>> mybox.length = 70

Property values can be inspected using the Python logger as follows:

>>> mybox.position
[0,0,0]

Changing the position of a box is more sophisticated: it requires that we create a new Point3 object and assign it to the position, as follows:

>>> mybox.position = mxs.Point3(20, 30, 50)

Rhe Py3dMax module does automatic conversion of Python primitive values to and from MAXScript values, but more complex MAXScript types like Point3, have to be explicitly created using the MAXScript global functions.

At first you may not realize it (I only discovered by accident) but the Python logger has two separate panes like the MAXScript listener. At the bottom of the logger window is a horizontal divider that can be dragged to expose a text editor to enter multiple lines of code without having them evaluated immediately. This is useful for defining functions or classes. You can run the code (or some selection of it) using the “Run” menu item.

There are a number of built-in functions defined in the Py3dsMax module:

  • GetWindowHandle - Get the HWND value of the 3ds Max window
  • GetPluginInstance - Get the HINSTANCE value of a 3ds Max plug-in
  • DispatchMessage - Sends the 3ds Max window a message
  • Redo - Redoes the last action undone.
  • Undo - Undoes the latest action.
  • undoOn - Starts a new undo stack.
  • undoOff - Finishes the current undo stack.
  • getVisController - Get a nodes visibility controller
  • setVisController - Set a nodes visibility controller
  • runMaxscript - Runs a MAXScript file for proper error checking
  • runScript - Runs a python file in our global scope
  • getVersion - Returns the version of Py3dsMax

Some caveats to using the Python logger:

  • The Python print function does not output to the logger, at least not on my test set-up (3ds Max 2010 32-bit)
  • Some errors can crash 3ds Max without a chance to save your work. For example once I mistakenly tried to call a MAXScript value as if it was a function and 3ds Max shut down instantly.
  • After entering a command to make a scene change forget to click on the viewport to force a refresh and in order to see changes made to the scene or end your scripts with a call to mxs.completeRedraw().
  • Controller properties don’t work as expected due to quirks in MAXScript: instead you have to use mxs.getPropertyController( s.controller, "position" ).

Using the Generic Blur3d.API Module

Blur provides a module for working with some of the scripting API of both 3ds Max and Softimage in a generic way. While there are limitations, there are still some useful APIs exposed that emphasize pipeline specific tasks. This module was used to implement the generic Onion layer management tool provided by Blur (see the source code at C:blurdevofflinecodepythonlibblur3dguionion).

The following demonstrates how to access a generic scene object and set the name of an object in the scene, in a way that will work on both 3ds Max and Softimage.

>>> from blur3d.api import Scene
>>> scene = Scene.instance()
>>> objects = scene.objects()
>>> objects[0].setName( "Testing" )

The API comes with documentation accessible from the Blur IDE editor. When you open the Blur IDE Editor choose the “Help > SDK Help” menu item. This launches a tool called the SDK browser, which is similar to a compiled help module (CHM).The first time you run this tool you have to open the .SDK file found at: PYTHON_PATH/lib/site-packages/blurdev/resource/sdk/blurdev.sdk. After that you can browse documentation for many of the Python modules provided by Blur.

Using Python from MAXScript

In addition to allowing you to call MAXScript from Python Py3dsMax also allows Python to be called from MAXScript. From MAXScript a new global variable called “Python” gives access to Python modules. This variable in MAXScript provides four methods:

  • import – Import a Python module identified by a string parameter
  • reload – Reload a Python module identified by a string parameter
  • run – Runs a Python script
  • exec – Executes a Python command

The following example MAXScript code show how you can retrieve Python documentation on a Python module using the Python inspect module:

inspect = python.import "inspect"
inspect.getdoc inspect

The following MAXScript code displays your system path using the Python sys module:

sys = python.import "sys"
print sys.path

How Py3dsMax Works

The Py3dsMax plug-in is a MAXScript extension plug-in (extension .DLX). It uses the MAXScript API of the 3ds Max SDK and the CPython extension API.
The blur package comes with all of the source code released under the GPL. In the source code is a file “wrapper.h” that provides a wrapper around the basic MAXScript value class (Value) to expose and a wrapper around the CPython object class (PyObject).

Building Common UIs with PyQt4
 

One problem faced by tool developers is creating UIs for multiple DCC tool. Ideally one could reuse the same UI code for each product. Blur has solved this problem by providing a single way to launch a GUI application independent of the host application. For example consider the following Python script:

from blurdev.gui import Dialog

class HelloWorldDialog(Dialog):
  def __init__( self, parent = None ):
    Dialog.__init__( self, parent )
    self.setWindowTitle('Hello, World')

if ( __name__ == "__main__" ):
  import blurdev
  blurdev.launch(HelloWorldDialog)

This same script can be run from within 3ds Max as an embedded application (using the Python > Run Script menu item) or as a standalone application (e.g. from the Python shell or by double clicking the file in Windows explorer). This assumes of course that you have Python and Blur properly installed.

PyQT is a third-party Python wrapper around the QT UI framework. Using PyQT and the blurdev.gui module allows tool writers to use the same QT interface regardless of the host application. Out of the box the Blur GUI framework works with 3ds Max and Softimage but has been used successfully with other applications (e.g. Maya).

Comparing Py3dsMax with MaxSharp and IronPython

Another approach to using Python with 3ds Max that I've discussed before is to use IronPython (the .NET implementation of Python) and a .NET wrapper around the 3ds Max SDK (such as MaxSharp). There are two main differences between Py3dsMax and using IronPython via MaxSharp.

  • Py3dsMax exposes only features of MAXScript, while MaxSharp exposes the entire 3ds Max SDK (some with a high-level API some not wrapped). This means that Py3dsMax generally is simpler to use, but lacks exposure of some features of 3ds Max that are only exposed to the SDK.
  • Py3dsMax is a CPython extension and MaxSharp is an IronPython extension. Both support the Python language, but Py3dsMax allows CPython extensions to be used (e.g. NumPy, SciPy, PIL, PyQT, etc.) while MaxSharp allows .NET libraries to be used (e.g. System.Windows.Forms, System.Xml, System.IO, System.Threading.Tasks, etc.)

Which one is better, depends on your needs and the expertise available in your studio. It is also worth noting that MaxSharp does not include an interactive Python console like is provided by blur studios with Py3dsMax.

Conclusion

Py3dsMax and the rest of the blur development package is a very useful set of tools for people interested in using Python (specifically CPython) from within 3ds Max. There are of course certain limitations (such as minimal documentation and some issues around usability and robustness) which one would naturally expect from a toolset developed primarily for in-house use. At the same time these tools have been used extensively in a production environment and are very sophisticated and useful.

I would appreciate hearing any feedback from other people who have used the Blur tools.
 

5 Comments

Morita

Posted 7 July 2011 1:04 am

wonderful write up! Seems like it should be part of their documentation ;-)

Christopher Diggins

Posted 7 July 2011 1:05 am

Thank you very much Morita! That made my evening!

ChangsooEun

Posted 27 July 2011 4:36 am

How about python for .net?
http://pythonnet.sourceforge.net/

Would it be possible to use this with MaxSharp project?
If so, can we use PyQt in 3ds max?
What would be pros/cons compare to CPython implementation like Blur's?

lalamax3d

Posted 30 April 2013 5:29 am

thanks, very useful.

BurrowsTD

Posted 5 March 2014 5:46 pm

Been having some issues with installing the blur plug in. I have posted on their site and awaiting feedback but thought I might find some useful info here. No Maya installed at this time on the machine I am working on, but the blur install will be rolled out to machines that have Maya 2011 64 bit and Maya 2014 64 bit

Installed:

Max 2011 64 bit and Max 2014 64 bit
Python 2.7.4 64 bit
PyWin32 64 bit
PyQt4 4.10.3 and Qt 4.8.5
PySide 1.1.2
Microsoft Visual C++ 2008 - x86 9.0.30729.4148
Microsoft Visual C++ 2008 - x64 9.0.30729.4148
Microsoft Visual C++ 2010 - x86 10.0.40219
Microsoft Visual C++ 2010 - x64 10.0.40219

I installed BlurOffline_python27_2013-12-05_install_15445_64.exe but the desktop shortcuts do not open the targets and the Python menu in the Max toolbar throws an error as well. I was able to make a simple script in 2014 and run it but I cannot access any features in max 2011.

Any ideas guys?

Add Your Comment

You must be logged in to post a comment.

Please only report comments that are spam or abusive.