The pymxs Python module provides a wrapper for the MAXScript engine, and exposes virtually all the interfaces, globals, and classes available in MAXScript. This set of topics covers the basics of how to work with 3ds Max scenes and objects (such as geometry and materials) using pymxs, as well as creating UIs with PySide2. Because pymxs is a light wrapper for MAXScript, this guide does not contain a description of every available API, but rather some overview and examples. Virtually every API described in the MAXScript Guide can be accessed with pymxs (with some exceptions outlined in the Differences Between pymxs and MAXScript topic).
While Python is case sensitive (so that, for example print() and Print() are not equivalent), MAXScript is not. The convention in the MAXScript documentation is to generally camelCase functions and properties to make them easier to read, but this is not always the case in samples, or in scripts you may find elsewhere. Because they are essentially MAXScript calls, members in pymxs.runtime are not case sensitive. Both pyxms.runtime.converttomesh() and pymxs.runtime.convertToMesh() are valid, which may seem odd to someone used to Python.
Another difference between Python and MAXScript is how array indices are managed. Python is 0-based, MAXScript is 1-based. When arrays are passed between Python and MAXScript, they are converted to the native index format. For example, when accessing the meditMaterials array of material editor slots from pymxs, use 0-based indices:
>>> len(pymxs.runtime.meditmaterials) 24 >>> pymxs.runtime.meditmaterials[0] <Standardmaterial<01 - Default:Standard>>
However, when using functions or methods that take index arguments, the indices are 1-based even in pymxs. For example, the setMeditMaterial(<slot_index>, <material>) function takes as its first argument the index of a material slot. In this case, to set the first slot:
>>> mat = pymxs.runtime.PhysicalMaterial() >>> pymxs.runtime.setMeditMaterial(1, mat)
While the pymxs module is a thin wrapper for MAXScript, it is not always obvious how to translate certain MAXScript syntax into the Python world. Here are some of the common cases:
Many MAXScript functions take keyword parameters. Consider this example that creates a bitmap and renders to it. It uses two keyword parameters, color: when constructing the Bitmap, and to: when rendering.
bm = Bitmap 320 240 color:white render to:bm display bm
The equivalent in pymxs also uses keyword arguments, and looks like this:
bm = pymxs.runtime.Bitmap(320,240,color=pymxs.runtime.white) pymxs.runtime.render(to=bm) pymxs.runtime.display(bm)
Name literals are commonly used in MAXScript to signify options passed to functions, and have no corresponding type in Python. They can be created with pymxs.runtime.Name(). For example, to use the equivalent of toolmode.coordsys #world:
pymxs.runtime.toolMode.coordsys(pymxs.runtime.Name("world"))
Many functions return names or arrays of names. For example, to get all the properties for a box, using the equivalent of getpropnames box:
boxprops = pymxs.runtime.getpropnames(pymxs.runtime.box)
This yields a MAXScript Array object containing runtime.Name objects. In this case, it might be more useful to generate a native list of Python strings:
boxprops = [str(x) for x in list(pymxs.runtime.getpropnames(pymxs.runtime.box))] # gives: ['typeinCreationMethod', 'typeInPos', 'typeInLength', 'typeInWidth', 'typeInHeight', 'length', 'width', 'height', 'widthsegs', 'lengthsegs', 'heightsegs', 'mapcoords']