Zoo Maya Command

Note

We’re building a new version of undo commands for the api to more closely work with zapi(our api wrapper). This move has been made to simplify managing undo across tools and to make it easier to use. This will avoid having to write a custom zoo command for every tool and make undo far more stable

Python command pattern with undo,redo functionality for standard applications and or DCCs if supported via command executors

Commands follow some strict rules.

  • All commands must inherent from zoo.libs.command.command.ZooCommand.

  • All commands must have the following overrides.

    • id(property) the command id

    • isUndoable(property) Does the command support undo

    • doIt(method), Main method to do the operation

    • undoIt(method), if is undoable then undoIt() must be implemented

If a command is undoable then it will be part of maya internal undostack. Maya commands are a thin wrapper around the MPxCommand so we maintain the undo/redo feature’s but we extended the possibilities with maya by allowing for arbitrary data types to be passed to and from commands eg. om2.MObject. we only support using om2, cmds and pure python, no om1 code as per maya documentation. A few design decision have been made to simplify command creation.

  • Only the doIt and undoIt methods need to be implemented.

  • Zoo handles the registry of supported commands and only one plugin is registered to maya which is the undo.py in zoo.

  • User’s only need to tell zoo executor instance about the command location(Environment variable), no need for the initializePlugin().

  • Minimal differences between MPxCommand and Zoocommand

  • maya’s undo/redo stacks and zooCommands stacks are synced via the custom MPx.

  • ZooCommands support passing api objects and any datatype to and from a command(see below).

  • ZooCommands are not meant to do atomic operations and query ops. Only for maya state changes and only for large operations.

  • ZooCommands are not meant to replace c++ commands or for efficient code but for tool development, it’s not meant to be run in loops or something stupid like that. eg. you press a pushbutton then you execute a command that builds a rig which can be undone.

Usage

Users can add there own paths via the environment variable ‘ZOO_COMMAND_LIB’ then running the following

from zoo.libs.maya.mayacommand import mayaexecutor as executor
executor.Executor().registerEnv("ZOO_COMMAND_LIB")

To execute commands one must use the executor class and never execute the command directly otherwise it will not be added to the internal undo stack and or the redostack.

# to execute a command
from zoo.libs.maya.mayacommand import mayaexecutor as executor
exe = executor.Executor()
exe.executor("commandId", **kwargs)

To undo a command.

from zoo.libs.maya.mayacommand import mayaexecutor as executor
executor.Executor().registerEnv("ZOO_COMMAND_LIB")
executor.undoLast()

To redo a command from the undostack.

from zoo.libs.maya.mayacommand import mayaexecutor as executor
executor.Executor().registerEnv("ZOO_COMMAND_LIB")
executor.redoLast()

Example

from zoo.libs.maya.mayacommand import mayaexecutor as executor
exe = executorExecutor()
nodes = exe.execute("zoo.create.nodetype", name="transform", amount=10, Type="transform")
print(nodes)
# (<OpenMaya.MObjectHandle object at 0x0000024911572E70>, <OpenMaya.MObjectHandle object at 0x0000024911572E30>,
<OpenMaya.MObjectHandle object at 0x0000024911572CB0>, <OpenMaya.MObjectHandle object at 0x0000024911572E90>,
<OpenMaya.MObjectHandle object at 0x0000024911572EB0>, <OpenMaya.MObjectHandle object at 0x0000024911572ED0>,
<OpenMaya.MObjectHandle object at 0x0000024911572EF0>, <OpenMaya.MObjectHandle object at 0x0000024911572F10>,
<OpenMaya.MObjectHandle object at 0x0000024911572F30>, <OpenMaya.MObjectHandle object at 0x0000024911572F50>)


# see below for the command class

from zoo.libs.maya.mayacommand import command


class CreateNodeTypeAmount(command.ZooCommandMaya):
    id = "zoo.create.nodetype" # id which is used for execution, and any filtering, lookups, GUIs etc
    creator = "David Sparrow"
    isUndoable = True
    _modifier = None

    def resolveArguments(self, arguments):
        """Method to Pre check arguments this is run outside of mayas internals and the result cached on to the command instance.
        Since the result is store for the life time of the command you need to convert MObjects to MObjectHandles.
        :param arguments: dict representing the arguments
        :type arguments: dict
        """
        name=  arguments.get("name")
        if not name:
            self.cancel("Please provide a name!")
        amount = arguments.get("amount")
        if amount < 1:
            self.cancel("The amount can't be below one")
        if not arguments.get("Type"):
            arguments["Type"] = "transform"
        return arguments

    def doIt(self, name=None, amount=1, Type=None):
        """Its expected that the arguments are setup correctly with the correct datatype,
        """
        mod = om2.MDagModifier()
        nodes = [None] * amount
        for i in xrange(amount):
            obj = mod.createNode(Type)
            mod.renameNode(obj, "name{}".format(i))
            nodes[i] = obj
        mod.doIt()
        nodes = map(om2.MObjectHandle, nodes)
        self._modifier = mod
        return tuple(nodes)

    def undoIt(self):
        if self._modifier is not None:
            self._modifier.undoIt()

API

class CommandInterface(stats=None)

Bases: object

The standard ZooCommand metaclass interface. Each command must implement doIt, id, creator, isUndoable, description

initialize()

Intended for overriding by the subclasses, intention here is if the subclass needs __init__ functionality then this function should be used instead to avoid any mishaps in any uncalled data.

abstract doIt(**kwargs)

Main method to implement the command operation. all subclasses must have a doIt method The DoIt method only support Kwargs meaning that every argument must have a default, this is by design to maintain clarity in people implementation.

Parameters:
  • kwargs – key value pairs, values can be any type , we are not restricted by types including custom objects or DCC dependent objects eg.MObjects.

  • kwargs – dict

:return This method should if desired by the developer return a value, this value can be anything including maya api MObject etc.

Example:

# correct doIt(source=None, target=None, translate=True) # incorrect doIt(source, target=None, translate=True)

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

runIt()

Runs doIt with the current arguments

Returns:

The result from doIt

runArguments(**arguments)

Parses the arguments then runs the command

Parameters:

arguments – key, value pairs that correspond to the DoIt method

Returns:

Return type:

resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

abstract property id

Returns the command id which is used to call the command and should be unique

Returns:

the Command id

Return type:

str

abstract property isUndoable

Returns whether this command is undoable or not

Returns:

Defaults to False

Return type:

bool

prepareCommand()
requiresWarning()
displayWarning(message)
warningMessage()
cancel(msg=None)

Raises the UserCancel error, useful when validating arguments

Parameters:

msg (str) – The Error message to display

Raise:

errors.UserCancel

hasArgument(name)
parseArguments(arguments)

Parse the arguments and get it ready for the command to use

Parameters:

arguments (duct) – dictionary

Returns:

Return type:

bool

class ArgumentParser

Bases: dict

class ZooCommandMaya(stats=None)

Bases: CommandInterface

isEnabled = True
useUndoChunk = True
disableQueue = False
disableUndoQueue(disable)

Disable Undo Queue

Parameters:

disable (bool) – Disable undo queue

Returns:

isQueueDisabled()

Check if it is disabled or not

Returns:

Return type:

type

runArguments(**arguments)

Parses the arguments then runs the command

Parameters:

arguments – key, value pairs that correspond to the DoIt method

Returns:

Return type:

Executor

class MayaExecutor(*args, **kwargs)

Bases: object

Maya Executor class for safely injecting zoo commands into the maya undo stack via MPXCommands. Always call executor.execute() method when executing commands

property commands
findCommand(id)
cancel(msg)
execute(commandName, **kwargs)

Function to execute Zoo commands which lightly wrap maya MPXCommands. Deals with prepping the Zoo plugin with the command instance. Safely opens and closes the undo chunks via maya commands (cmds.undoInfo)

Parameters:
  • commandName (str) – The command.id value

  • kwargs (dict) – A dict of command instance arguments, should much the signature of the command.doit() method

Returns:

The command instance returns arguments, up to the command developer

flush()
class CommandStats(tool)

Bases: object

finish(tb=None)

Called when the plugin has finish executing

execute(executeId, **kwargs)

Helper to execute zoo commands by id

Parameters:

executeId (basestring) – ID To execute

Returns:

Returns the executor and anything from exe execute

Errors

exception UserCancel(message, errors=None)

Bases: Exception

exception CommandExecutionError(message, *args, **kwargs)

Bases: Exception

Zoo Command Library

Alignselectedcommand

class AlignSelectedCommand(stats=None)

Bases: ZooCommandMaya

This command Creates a meta node from the registry.

id = 'zoo.maya.alignSelected'
isUndoable = True
transformations = None
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(target=None, driven=None, aimVector=MockExt.OpenMaya.MVector, upVector=MockExt.OpenMaya.MVector)

Create the meta node based on the type parameter, if the type isn’t specified then the baseMeta class will be used instead

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

Connectsrt

class ConnectSRTSelectedCommand(stats=None)

Bases: ZooCommandMaya

id = 'zoo.maya.connect.selection.localsrt'
isUndoable = True
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(driver=None, targets=None, translate=True, rotate=True, scale=True)

Create the meta node based on the type parameter, if the type isn’t specified then the baseMeta class will be used instead

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

Createmetacommand

class CreateMetaCommand(stats=None)

Bases: ZooCommandMaya

This command Creates a meta node from the registry.

id = 'zoo.meta.create'
isUndoable = True
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(node=None, name=None, type_=None, initDefaults=True)

Create the meta node based on the type parameter, if the type isn’t specified then the baseMeta class will be used instead

Parameters:
  • node (MObject) – The node to convert to the meta class(optional)

  • name (str) – The new name for the create meta node(optional)

  • type (str) – The meta node class name, if not specified then the base meta class is used. This is converted to the class instance during command.resolvearguments method operation.

  • initDefaults (bool) – If true then the standard meta attributes are added

Returns:

Returns the class instance of the meta class thats created

Return type:

base.MetaBase

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

Nodeeditorcommands

class NodeAlignmentCommand(stats=None)

Bases: ZooCommandMaya

id = 'zoo.maya.nodeEditor.alignment'
isUndoable = True
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(nodeEditor=None, nodeItems=None, align=0)

Create the meta node based on the type parameter, if the type isn’t specified then the baseMeta class will be used instead

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

Setselectednodes

class SetSelectedNodes(stats=None)

Bases: ZooCommandMaya

This command selected maya nodes

id = 'zoo.maya.setSelectedNodes'
isUndoable = True
currentSelection = []
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(nodes=None)
Parameters:

nodes (seq or om2.MSelectionList) –

Returns:

Return type:

om2.MObjectArray

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type:

Swapconnections

class SwapConnectionsCommand(stats=None)

Bases: ZooCommandMaya

This command Swaps the outgoing connections between two nodes

id = 'zoo.maya.connections.swap.all'
isUndoable = True
resolveArguments(arguments)

Method which allows the developer to pre doIt validate the incoming arguments. This method get executed before any operation on the command.

Parameters:

arguments (dict) – key, value pairs that correspond to the DoIt method

Returns:

Should always return a dict with the same key value pairs as the arguments param

Return type:

dict

doIt(source=None, target=None, plugs=None)
Parameters:
  • source (om2.MObject) –

  • target (om2.MObject) –

  • plugs (list[om2.MPlug] or None) –

Return type:

bool

undoIt()

If this command instance is set to undoable then this method needs to be implemented, by design you do the inverse operation of the doIt method

Returns:

Return type: