Max API
8.2.0
|
Your object can use scripting capabilities of the patcher to learn things about its context, such as the patcher's name, hierarchy, or the peer objects to your object in its patcher.
You can also modify a patcher, although any actions your object takes are not undoable and may not work in the runtime version.
To obtain the patcher object containing your object, you can use the obex hash table. The obex (for "object extensions") is, more generally, a way to store and recall data in your object. In this case, however, we are just using it in a read-only fashion.
Note that unlike the technique discussed in previous versions of the SDK, using the obex to find the patcher works at any time, not just in the new instance routine.
The patcher is an opaque Max object. To access data in a patcher, you'll use attributes and methods.
To obtain the name of the patcher and its file path (if any), obtain attribute values as shown below.
These attributes may return NULL or empty symbols.
To determine the patcher hierarchy above the patcher containing your object, you can use jpatcher_get_parentpatcher(). A patcher whose parent is NULL is a top-level patcher. Here is a loop that prints the name of each parent patcher as you ascend the hierarchy.
To obtain the first object in a patcher, you can use jpatcher_get_firstobject(). Subsequent objects are available with jbox_get_nextobject().
If you haven't read the Anatomy of a UI Object, we'll mention that the patcher does not keep a list of non-UI objects directly. Instead it keeps a list of UI objects called boxes, and the box that holds non-UI objects is called a newobj. The "objects" you obtain with calls such as jpatcher_get_firstobject() are boxes. The jbox_get_object() routine can be used to get the pointer to the actual object, whether the box is a UI object or a newobj containing a non-UI object. In the case of UI objects such as dials and sliders, the pointer returned by jbox_get_object() will be the same as the box. But for non-UI objects, it will be different.
Here is a function that prints the class of every object (in a box) in a patcher containing an object.
As an alternative to the technique shown above, you can write a callback function for use with the patcher's iteration service. The advantage of using iteration is that you can descend into the patcher hierarchy without needing to know the details of the various objects that may contain subpatchers (patcher, poly~, bpatcher, etc.). If you want to iterate only at one level of a patcher hierarchy, you can do that too.
Your iteration function is defined as follows. It will be called on every box in a patcher (and, if you specify, the patcher's subpatchers).
The function returns 0 if iteration should continue, or 1 if it should stop. This permits you to use an iterator as a way to search for a specific object.
Here is an example of using an iterator function:
The PI_WANTBOX flag tells the patcher iterator that it should pass your iterator function the box, rather than the object contained in the box. The PI_DEEP flag means that the iteration will descend, depth first, into subpatchers. The result parameter returns the last value returned by the iterator. For example, if the iterator terminates early by returning a non-zero value, it will contain that value. If the iterator function does not terminate early, result will be 0.
Assuming the iterator function receives boxes, here is an example iterator that prints out the class and scripting name (if any) of all of the objects in a patcher. Note that the scripting name is an attribute of the box, while the class we would like to know is of the object associated with the box.
Much of the Max user interface is implemented using patcher scripting. For example, the inspectors are patchers in which an inspector object has been created. The file browser window has four or five separate scripted objects in it. Even the debug window is a dynamically scripted patcher. We point this out just to inform you that creating objects in a patcher actually works (if you get all the details right). The xxx example object shows how to use patcher scripting to create an "editing window" similar to the ones you see when double-clicking on a table or buffer~ object.
Creating objects in a patcher generally requires the use of a Dictionary (see discussion of UI objects above), but there is a convenience function newobject_sprintf() that can be used to avoid some of the complexity.
To create an object, your task is to set some attributes. In the absence of any specific values, an object's attributes will be set to some default, but you'll probably care, at the very least, about specifying the object's location. Here is an example that creates a toggle and metro object using a combination of attribute parse syntax and sprintf. If you're interested in creating objects with newobject_sprintf(), it may help to examine a Max document to see some of the attribute name - value pairs used to specify objects.
Note that to create a non-UI object, you use set the maxclass attribute to newobj and the text attribute to the contents of the object box. Attributes can be specified in any order. Using the patching_position attribute permits you to specify only the top-left corner and use the object's default size. For text objects, the default size is based on the default font for the patcher.
Finally, note that newobject_sprintf() returns a pointer to the newly created box, not the newly created object inside the box. To get the object inside the box, use jbox_get_object().
If you'd like to script the connections between two objects, you can do so via a message to the patcher. Assuming you have the patcher, toggle, and metro objects above, you'll create an array of atoms to send the message using object_method_typed().
If you want to have a hidden connection, pass an optional fifth argument that is any negative number.
To delete an object in a patcher you call object_free() on the box. As of Max 5.0.6 this will properly redraw the patcher and remove any connected patch cords.
You can use object attribute functions to modify the appearance and behavior of objects in a patcher or the patcher itself. Note that only a few of these attributes can be modified by the user. The C level access to attributes is much more extensive.
Attributes whose type is object can be accessed via object_attr_getobj() / object_attr_setobj(). Attributes whose type is char can be accessed with object_attr_getchar() / object_attr_setchar(). Attributes whose type is long can be accessed with object_attr_getlong() / object_attr_setlong(). Attributes whose type is symbol can be accessed via object_attr_getsym() / object_attr_setsym(). For attributes that are arrays, such as colors and rectangles, use object_attr_getvalueof() / object_attr_setvalueof().
Name | Type | Settable | Description |
box | object | No | The box containing the patcher (NULL for top-level patcher) |
locked | char | Yes (not in runtime) | Locked state of the patcher |
presentation | char | Yes | Presentation mode of the patcher |
openinpresentation | char | Yes | Will patcher open in presentation mode? |
count | long | No | Number of objects in a patcher |
fgcount | long | No | Number of objects in the patcher's foreground layer |
bgcount | long | No | Number of objects in the patcher's background layer |
numvews | long | No | Number of currently open views of the patcher |
numwindowviews | long | No | Number of currently open window-based views of the patcher |
firstobject | object | No | First box in the patcher |
lastobject | object | No | Last box in the patcher |
firstline | object | No | First patch cord in the patcher |
firstview | object | No | First view object in the patcher |
title | symbol | Yes | Window title |
fulltitle | symbol | No | Complete title including "unlocked" etc. |
name | symbol | No | Name (could be different from title) |
filename | symbol | No | Filename |
filepath | symbol | No | File path (platform-independent file path syntax) |
fileversion | long | No | File version |
noedit | char | No | Whether patcher can be unlocked |
collective | object | No | Collective object, if patcher is inside a collective |
cansave | char | No | Whether patcher can be saved |
dirty | char | Yes (not in runtime) | Whether patcher is modified |
bglocked | char | Yes | Whether background is locked |
rect | double[4] | Yes | Patcher's rect (left, top, width, height) |
defrect | double[4] | Yes | Patcher's default rect (used when opening the first view) |
openrect | double[4] | Yes | Fixed initial window location |
parentpatcher | object | No | Immediate parent patcher (NULL for toplevel patchers) |
toppatcher | object | No | Topmost parent patcher (NULL for toplevel patchers) |
parentclass | object | No | Class object of parent (patcher, poly~, bpatcher etc.) |
bgcolor | double[4] | Yes | Locked background color (RGBA) |
editing_bgcolor | double[4] | Yes | Unlocked background color (RGBA) |
edit_framecolor | double[4] | Yes | Text editing frame color |
locked_iocolor | double[4] | Yes | Locked inlet/outlet color |
unlocked_iocolor | double[4] | Yes | Unlocked inlet/outlet color |
boguscolor | double[4] | Yes | Color of uninitialized (bogus) objects |
gridsize | double[2] | Yes | Editing grid size |
gridonopen | char | Yes | Show grid on open |
gridsnapopen | char | Yes | Snap to grid on open |
imprint | char | Yes | Save default-valued object attributes |
defaultfocusbox | symbol | Yes | Default focus box (varname) |
enablehscroll | char | Yes | Show horizontal scrollbar |
enablevscroll | char | Yes | Show vertical scrollbar |
boxanimatetime | long | Yes | Box animation time |
default_fontname | symbol | Yes | Default font name |
default_fontface | long | Yes | Default "fake" font face (0 plain, 1, bold, 2 italic, 3 bold italic) |
default_fontsize | long | Yes | Default font size in points |
toolbarvisible | char | Yes | Show toolbar on open |
toolbarheight | long | Yes | Height of toolbar (can use 0 for invisible) |
toolbarid | symbol | Yes | Name (in maxinterface.json) of toolbar, none = empty symbol |
Name | Type | Settable | Description |
rect | double[4] | Settable only | Changes both patching_rect and presentation_rect |
presentation_rect | double[4] | Yes | Presentation mode rect |
patching_rect | double[4] | Yes | Patching mode rect |
position | double[2] | Settable only | Changes both patching_position and presentation_position |
size | double[2] | Settable only | Changes both patching_size and presentation_size |
patching_position | double[2] | Yes | Patching mode position (top, left corner) |
presentation_position | d[2] | Yes | Presentation mode position |
patching_size | double[2] | Yes | Patching mode size (width, height) |
presentation_size | double[2] | Yes | Presentation mode size |
maxclass | symbol | No | Name of Max class (newobj for non-UI objects) |
object | object | No | Associated object (equivalent to jbox_get_object) |
patcher | object | No | Containing patcher |
hidden | char | Yes | Is box hidden on lock? |
fontname | symbol | Yes | Font name (if box has font attributes or a text field) |
fontface | long | Yes | "Fake" font face (if box has font attribute or a text field) |
fontsize | long | Yes | Font size (if box has font attributes or a text field) |
textcolor | double[4] | Yes | Text color (if box has font attributes or a text field) |
hint | symbol | Yes | Associated hint |
color | double[4] | Yes | Standard color attribute (may not be present in all objects) |
nextobject | object | No | Next object in the patcher's list |
prevobject | object | No | Previous object in the patcher's list |
varname | symbol | Yes | Scripting name |
id | symbol | No | Immutable object ID (stored in files) |
canhilite | char | No | Does this object accept focus? |
background | char | Yes | Include in background |
ignoreclick | char | Yes | Ignores clicks |
maxfilename | symbol | No | Filename if class is external |
description | symbol | No | Description used by assistance |
drawfirstin | char | No | Is leftmost inlet drawn? |
growy | char | No | Can object grow with fixed aspect ratio? |
growboth | char | No | Can object grow independently in width and height? |
nogrow | char | No | Is object fixed size? |
mousedragdelta | char | No | Does object use hidden-mouse drag tracking (number box) |
textfield | object | No | Textfield object associated with this box if any |
editactive | char | No | Is object the currently focused box in an unlocked patcher? |
prototypename | symbol | No | Name of the prototype file used to create this object |
presentation | char | Yes | Is object included in the presentation? |
annotation | symbol | Yes | Text shown in clue window when mouse is over the object |
numinlets | long | No | Number of inlets visible |
numoutlets | long | No | Number of outlets visible |
outlettype | symbol[] | No | Array of symbols with outlet types ("signal" etc.) |
To access an attribute of a non-UI object, use jbox_get_object() on the box to obtain the non-UI object first.