Command System: Basics

From The Foundry MODO SDK wiki
Jump to: navigation, search

This article covers the basics of the Command System, including the different classes of commands, standard command syntax formatting, arguments, and command blocks.

Command Naming Convention

Commands have a standard naming convention, generally in the form of "noun.verb", or "object.action". The first part of the command is the system or type of selection the action can acts on, while the second part after the period is the action that will be performed. Some common examples are item.name, script.run, tool.attr and poly.subdivide. There is never more than one dot in a command name. Multiple words in the second part of a command string are formatted as per camel case, with each word after the first capitalized: cmds.saveList.

Command Classes

There are four main classes of commands: UI, Side Effect, Model and Undoable. There are also two less-used classes, Undo Special and Quiet, as well as the ability to associate common commands in Containers.

Various commands of different classes in the Command History's undo list.

UI

UI commands are those that affect the user interface but do not affect or rely on any other state in the application. viewport.turntable is a good example of this, as spinning the model around doesn't rely on any specific model state, nor does it change the model state in any way. A UI command has short yellow slash marks next to it in the Command History. These commands will shuffle through the undo list as you performs undos so that they can never move into the redo section.

Side Effect

Side Effect commands are similar to UI commands in that they do not change the model state. However, they do rely on the model for their state. An example is the macro.record command, which starts and stops macro recording. The commands executed between two calls to macro.record commands are captured as a macro, but the command doesn't actually affect the model itself. Side effect commands are shown with a short blue dash in the Command History.

Undoable

Undoable commands are the most common command type in modo. The poly.subdivide command is an example of an undoable command that directly affects the model. Undoable commands can be undone and redone. In the Command History, such commands have a circular green arrow if they can be undone, and a grayed out arrow looping the other way if they can be redone and are beyond the undo insertion point (the "Drag to undo/redo" line in the Undo List of the Command History).

Model

Non-undoable commands that affect the model state are very rare. Executing a non-undoable command clears the undo stack. Non-undoable commands are sometimes referred to as model commands, while undoable commands are sometimes called undoable model commands.

Sub-Commands and Class Inheritance

Commands are often executed from within other commands. These are referred to as sub-commands. If the class of a sub-command is more restrictive than its parent's class, the parent's class may also change. For example, a UI command executing an undoable command would itself be listed as undoable in the history. Similarly, an undoable command executing a non-undoable command would become non-undoable. In fact, if a non-undoable sub-command is executed, any parents would become non-undoable as well. An undoable or non-undoable command executing a UI command would not be changed, since a UI command doesn't have any extra state that needs to be preserved. Commands can also explicitly change their class during execution depending on their arguments, although this is rare.

This table shows the inheritance of the different command classes during sub-command execution. You can see that the class of a parent UI command is overridden by the class of any sub-command, while non-undoable model sub- commands always override the parent's original class.

Original Parent Class Sub-Command Class Final Parent Class
UI UI UI
UI Side Effect Side Effect
UI Undoable Undoable
UI Model Model
Side Effect UI Side Effect
Side Effect Side Effect Side Effect
Side Effect Undoable Undoable
Undoable Model Side Effect
Side Effect Model Model
Undoable UI Undoable
Undoable Side Effect Undoable
Undoable Undoable Undoable
Undoable Model Model
Model UI Model
Model Side Effect Model
Model Undoable Model
Model Model Model

Quiet

Quiet commands are special user interface commands that perform more complex operations. The quiet command itself doesn't appear in the history, but the commands that it executes will. Often they are used to provide a user interface for another command, such as opening a file dialog. An alternate way of doing this is to have the command set its own optional filename argument after it has opened the file dialog itself.

Undo Special, Containers and Other Flags

The remaining command classes are not used in scripting, nor are they used by many commands, but are listed for completeness:

Undo Special commands are commands like app.undo and app.redo, which directly affect the undo stack. In general, such commands are not used in scripts or by plug-ins, and in fact cannot be called from either. They also do not appear in the undo list, but do appear in the history.

Multiple commands that effectively perform the same basic operation on different selections can be grouped into Containers. Each command within a container operates in a specific context, and only one will be executed when the container is fired. The delete command is a container that executes different deletion commands depending on the current selection. All containers have a single optional ToggleValue type argument, allowing the bevel and extrude containers to create tool-style toggle buttons in the UI. Simpler containers, such as delete, do not make use of this argument. Any plug-in can claim to belong to a container, but scripts cannot. See the command interface documentation for more information on containers.

There are also a some special flags used by the command system and various clients. These are used to tag internal commands, selection commands, select-through commands, post-mode commands and commands that require at least one argument to be set, even if all arguments are optional. These are fairly esoteric and are more relevant when writing commands than when using them. See the command interface documentation for more information.

Command Arguments

Many commands have arguments that specify their behavior. For example, cmds.saveList is defined like so:

cmds.saveList <filename:string> <verbose:boolean>

This format is commonly used for describing command syntax. The first part is the command name, cmds.saveList, followed by two arguments. These arguments are in the form of name:datatype. The enclosing less than (<) and greater than (>) signs mark them as optional arguments; as such, they do not require a value for the command to execute. The arguments are named filename and verbose. The filename argument is a string, in this case the name of the file to save the command list to. The verbose argument is a boolean; giving it a value of 1 (or "true") will save more detailed information about each command.

Required versus Optional Arguments

Normally, a command's arguments are required to have a value before executing. These are called required arguments. If any required arguments not set, a command dialog will open asking for values. By contrast, optional arguments do not need to be given values. These are marked in the format string within a set of <...> symbols. For example, the item.channel command has two required arguments and one optional argument. Only the required arguments need to have a value.

item.channel name:string ?value:* <mode:{set|shift|scale}>

Argument Datatypes

Argument are listed with the argument name, followed immediately by a colon and the argument's datatype, as mentioned above. In some cases, the datatype is dynamic and is determined by the current program state or another argument at the time of execution. An asterisk marks an argument with a variable datatype. Above, the item.channel command uses a required name argument to figure out the datatype for the value argument. Common argument datatypes are described in detail later on.

Queriable Arguments

As well as having a variable datatype, the value argument is preceded by a question mark. This marks the argument as queriable, allowing a script or other client to retrieve its current value. Command queries will be described in detail later on.

Choices/TextValueHints

The optional mode argument doesn't list a datatype, but instead shows a list of mutually exclusive choices. The internal datatype for these kinds of arguments is an integer. Either the named choice or the integer can be entered, but be aware that the choices may not be enumerated as you see them here. Furthermore, the ordering of the options may change between versions of the application. In general it is best to use one of the named choices, which in this case are set, shift and scale. These choices are also commonly referred to as TextValueHints or simply text hints

It is possible for the argument's choices to themselves be dynamic, usually based on the value of another argument. In that case, the choices are shown as {...}.

Read Only

Some arguments are read-only. These arguments can be queried for their value, but can not be set. This is generally discouraged, as ScriptQuery interfaces should be used to avoid cluttering the namespace with read-only commands. Read-only arguments are prefixed with a #. select.count is an example of such a legacy command.

select.count <type:string> #count:integer

ToggleValue Arguments

Lastly, there are a few commands that feature ToggleValue arguments. Only one argument of any given command may be defined this way. The argument has one off state and numerous possible on states. tool.set is one such command that is used often in modo:

tool.set preset:string
            ?mode:{off|on|clear|remove|add}!{off}
           <task:{actor|center|axis|falloff|snap|show|constraint}>

The first argument is the name of a tool preset, the second is what to do with the preset, and the optional third argument sets task the preset affects.

The mode argument is what we're interested in; notice that at the end of the list of possible states, there's an exclamation point and the word {off}. The exclamation point marks this as a ToggleValue argument, and the word after that is the "off" state, in this case the word "off". The curly braces ensure that any spaces or quotes are correctly wrapped.

Examples of ToggleValue commands as buttons. The Cube button is on.

The primary reason for this mechanism is to create toggle-style buttons (not to be confused with boolean checkmarks) in the UI. For example, every tool button on the interface is actually a call to the tool.set command with a different value specified for the preset argument. This example activates the Cube tool:

tool.set prim.cube on

When used in a form, the Forms system detects the ToggleValue argument and queries it automatically. For tool.set, the command query returns "on" if the tool is currently in the tool pipe and "off" if it is not, translating this into the tool button itself being drawn as on or off. See the Forms documentation for more information on using queried commands in forms. Note that it is now possible to create toggle-style buttons directly through the Forms system, so this is only useful if you really need it.

Command Usage Marker Guide

This table shows the possible argument modifiers.

Markers Description Example
(nothing) Required name:datatype
<...> Optional <name:datatype>
? Queriable ?name:datatype
# Read-Only #name:datatype
* Variable Datatype name:*
{a|b|c} Choices (TextValueHints) name:{a|b|c}
{...} Dynamic Choices name:{...}
!{off} ToggleValue off state name:datatype!{off}

Command Blocks

The Command History viewport's Undo List showing a Tool Adjustment command block expanded to show its sub-commands.

Command blocks allow multiple commands to be treated as a single event in the history. This is useful when a single click might execute multiple undoable commands, but they should all be undone as a single entity. While not usable by scripts, command blocks are important in how they affect the command history and undo stack. Scripts are automatically encapsulated when executed, and so do not need to use command blocks directly.

In the Command History, a command block is shown in the same way as nested sub-commands, with the text "Command Block" in the second column.