Clarisse 3.6 SP10 SDK  3.6.0.0.10
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
The Command API

Table of Contents

Clarisse commands can be found under the namespace ix.cmds. Not only you get access to built-in commands that are shipped with Clarisse, but also to custom commands developed by any third parties that used the C++ SDK. Commands are focused functions allowing you to do a lot of things. More importantly, these commands support undo and can be called in batch (to avoid filling the undo stack).

Note
Currently the Log Output displays commands using the internal Clarisse scripting syntax. If you try to copy and paste the log output into the script editor, it won't execute and is likely to pop up a syntax error. This limitation will be overcome in future build so Clarisse directly displays the correct Python syntax.

Command signatures and arguments

Commands OfCommand are functions that may provide multiple signatures. While they are common and known as function overloads in some languages please note they are not really available in Python.

In Clarisse API, the signature of a specific command is defined by a set of arguments. If a same command accepts different sets of arguments then the command has multiple signatures. Each time a command is called, Clarisse will try to find the right candidate according to the arguments that were passed to the command. For example, the command CreateObject provides two signatures:

1 ix.cmds.CreateObject(object_name, class_name)
2 ix.cmds.CreateObject(object_name, class_name, context_path)

The first signature creates the object of the specified class name in the current application context, while the second one creates it in the specified one. In fact, it's not only the number of arguments that defines a signature but also their types. In the previous example, as stated in the documentation expected arguments are all of type string.

While argument types are listed for each command in the documentation, nevertheless, input command arguments OfCommandArgument aren't completely strict. To simplify scripting, they support implicit type conversion. For example, commands expecting objects defined by a path such as project://scene/image also accept directly OfObjects. In the very same way, commands expecting Python lists can also accept C++ CoreBasicArray. This way:

1 ix.cmds.DeleteItems(["project://scene/box1", "project://scene/box2"])

is equivalent to:

1 obj1 = ix.application.get_factory().get_object("project://scene/box1")
2 obj2 = ix.application.get_factory().get_object("project://scene/box2")
3 ix.cmds.DeleteItems([obj1, obj2])

and:

1 objects = ix.api.OfObjectVector()
2 obj1 = ix.application.get_factory().get_object("project://scene/box1")
3 obj2 = ix.application.get_factory().get_object("project://scene/box2")
4 objects.add(obj1)
5 objects.add(obj2)
6 ix.cmds.DeleteItems(objects)

Clarisse undo system overview

The undo in Clarisse is exclusively handled via commands. Each command implements what to do when it is called and what to restore when there's an undo. In a nutshell, commands must implement two methods: OfCommand::exec and OfCommand::unexec. OfCommand::exec implements what to do when the command is called, while OfCommand::unexec implements how undo should be handled. To learn more about Clarisse command and how to extend them, please refer to Using Clarisse commands system.

For example, let's see what happens when a user modifies an attribute of an object via the Attribute Editor. Instead of directly modifying the attribute value when it is modified, the Attribute Editor triggers a SetValue command.

The SetValue command records the previous attribute value and then SetValue::exec is called which changes the value by the new one. Finally, the command is stored and stacked in the CommandManager which is a dedicated class that handles application command history.

When undo is called, the Command::unexec of current command in the history is called. In our example, SetValue::unexec is called which replace the new value by the one it stored.

Enabling the undo system in a script

By default, when commands are called in a script, they are not added to the application command history. While the undo is then disabled by default, you can still enable it in your script by calling:

1 ix.enable_command_history()

This function comes in pair with ix.disable_command_history() that can be used to disable the command history in a specific portion of code.

Note
When the application history is enabled, directly accessing object attributes in Python using the following syntax my_object.attrs.translate[0] = 8.0 will automatically issue a command. In other words, the attribute value change will become undoable.

The reason why the command history is disabled by default is to prevents the script to fill the history with a large number of commands called in a script. Hopefully, Clarisse provides a way to enable the undo system while stacking all command calls and make them appear as a single one. This is achieved by enabling command batch so a single undo restores the previous state.

To enable store successful command calls in a batch command, you just need to wrap command calls using ix.begin_command_batch and ix.end_command_batch. Here is a working example:

1 ix.begin_command_batch('ResetKinematics')
2 # ResetKinematics is the name that will appear in the history editor
3 for i in range(ix.selection.get_count()):
4  obj = ix.selection[i]
5  if obj.get_class().is_kindof("SceneItem"):
6  obj.attrs.translate[0] = 0.0
7  obj.attrs.translate[1] = 0.0
8  obj.attrs.translate[2] = 0.0
9  obj.attrs.rotate[0] = 0.0
10  obj.attrs.rotate[1] = 0.0
11  obj.attrs.rotate[2] = 0.0
12  obj.attrs.scale[0] = 1.0
13  obj.attrs.scale[1] = 1.0
14  obj.attrs.scale[2] = 1.0
15 
16 ix.end_command_batch()

As you can see, similarly to the command history functions this function comes in pair with ix.end_command_batch(). It is used to mark the end of the command batch previously started. Calling ix.begin_command_batch automatically enables the command history while ix.end_command_batch disables it. In this example, a single undo will restore the state of all the objects that were modified in the selection.

Asynchronous command execution

As you've probably noticed, Clarisse is able to perform heavy background tasks to maximize the application interactivity. While this is a huge advantage, it comes with a tradeoff too: unlike in most software, commands are not necessarily immediately executed in Clarisse. In fact, when a command is executed in Python there's a good chance it is delayed. If the object you are modifying is protected, the execution of the command will be asynchronous. A protected object is an object that is currently in use in a background task.

For example, let's say you have a material on which you want to bind a texture:

1 ix.cmds.SetTexture(['project://scene/my_material.diffuse'], 'project://scene/my_texture')

If the object my_material is protected and you query right after in your script which texture is bound to my_material.diffuse, it will return None. To check if an OfObject is projected you can use the following method OfObject::is_protected

In Python:

1 my_material = ix.get_item('project://scene/my_material')
2 my_material.is_protected() # returns True if the object is protected

We have planned to extend Clarisse API in the near future to support a couple of special functions. Quite similar those used to enable or disable the command history, these ones will be placed on each block of code where commands are expected to run synchronously.