Command

  • LXe_CMD_ALREADY_EXISTS

  • LXe_CMD_MISSING_ARGS

  • LXe_CMD_NOT_AVAILABLE

  • LXe_CMD_DISABLED

  • LXe_CMD_UNKNOWN_COMMAND

  • LXe_CMD_INVALID_ON_PROTO

  • LXe_CMD_DIFFERENT_TYPES

  • LXe_CMD_UNBALANCED_BRACES

  • LXe_CMD_BAD_DEFINITION

  • LXe_CMD_UNKNOWN_ARGUMENT

  • LXe_CMD_TOO_MANY_ARGUMENTS

  • LXe_CMD_ARGUMENT_ALREADY_SET

  • LXe_CMD_ARGUMENT_NOT_QUERYABLE

  • LXe_CMD_NO_QUERY_MARKED

  • LXe_CMD_TOO_MANY_QUERIES_MARKED

  • LXe_CMD_ILLEGAL_REFIRE_BEGIN

  • LXe_CMD_ILLEGAL_REFIRE_END

  • LXe_CMD_ALREADY_REFIRING

  • LXe_CMD_NOT_ALIASED

  • LXe_CMD_ERROR_SETTING_DATATYPE

  • LXe_CMD_ERROR_ARG_MISSING_VALUE

  • LXe_CMD_SANDBOX_NOT_COMPATIBLE

  • LXe_CMD_SANDBOX_ONLY

  • LXe_CMD_EXPECTED_OPENING_BRACE

  • LXe_CMD_VARIABLE_DATATYPES_SET

  • LXe_CMD_VARIABLE_DATATYPES_PENDING

  • LXe_CMD_REQUIRES_USER_INTERACTION

  • LXe_CMD_HAS_NO_ARGUMENTS

  • LXe_CMD_QUERY_MISMATCHED_DATATYPES

  • LXe_CMD_ALL_ARGUMENTS_HIDDEN

  • LXe_CMD_BAD_DIALOG_FORMAT

  • LXe_CMD_UNDOS_LOCKED_OUT

  • LXe_CMD_DATATYPE_UNAVAILABLE

  • LXe_CMD_ILLEGAL_DURING_INITIALIZATION

  • LXe_CMD_NOT_EXECUTABLE

  • LXe_CMD_SANDBOX_GLOBAL

  • LXe_CMD_SANDBOXED

  • LXe_CMD_ACTION_COMPLETED

typedef unsigned short LXtCommandTag

This returns a command’s tag. This function is implemented by the command system and does not need to be provided by the command itself.

  • LXiCTAG_NULL

ILxCommand

class ILxCommand

The command object is mainly defined by the ILxCommand interface.

Public Functions

LxResult Tag(LXtObjectID self, LXtCommandTag *tag)
LxResult Name(LXtObjectID self, const char **name)

These functions return the name, username, button name, description, tooltip and example associated with an entry in the config. Name always returns the internal name of the command. The other functions will return either a string from the message table, or possibly a dynamic string provided by the command based on its current arguments and environment, falling back to the message table and possibly other reasonable defaults if the method fails or is NULL.

LxResult UserName(LXtObjectID self, const char **userName)
LxResult ButtonName(LXtObjectID self, const char **buttonName)
LxResult Desc(LXtObjectID self, const char **desc)
LxResult Tooltip(LXtObjectID self, const char **tooltip)
LxResult Help(LXtObjectID self, const char **help)

The help method returns a key, which in turn is resolved into a URL from the HelpURL part of the config.

LxResult Example(LXtObjectID self, const char **example)

Commands can also return an example string.

LxResult Icon(LXtObjectID self, const char **iconNames)

The icon name can also be obtained, which may be read directly from cmdhelp.cfg or dynamically specified by the command’s current arguments. Note that this is the raw icon name without any size information attached. Multiple icons can be specified in the icon name string, but this is not required. A simple icon string can just be “icon”. For multiple icons, the form is “besticon;fallbackicon;defaulticon”. There can be any number of icons; the first in the list will be tried, followed by the nexxt, and so on until one matches at the size requested. If the icon name contains a semicolon, two semicolons can be used instead.

LxResult Flags(LXtObjectID self, unsigned int *flags)

It is possible to for the command to use the value of its arguments during the flags method. However, it is important to handle cases where the arguments have no value, even if they are required arguments. This can happen when the prototype command is created, in which case no arguments have yet been set. In these cases, the client should just return default flags without relying on the command’s arguments.

LxResult PostExecFlags(LXtObjectID self, unsigned int *flags)

Also available are “post-execution” flags. The original flags assigned to a command may change after a pending command has fired. For example, an undoable command firing non-undoable commands would itself become non-undoable. Post-fire flags are only available after a command has been fired; if this hasn’t yet occured, LXe_CMD_NOT_AVAILABLE is returned. This function is provided by the command system and does not need to be specified by commands themselves.

LxResult PostExecBehaviorFlags(LXtObjectID self, unsigned int *flags)

The exuection flags are also available. These are the flags that were passed to the Execute() method, and include the LXfCMD_EXEC_ and LXfCMD_ALERT_ flags. These are only valid after the command has been executed.

LxResult PostExecHints(LXtObjectID self, unsigned int *hints)
LxResult SandboxGUID(LXtObjectID self, const LXtGUID **guid)

Certain commands can only be executed within specific sandboxes. If this method returns LXe_CMD_SANDBOX_GLOBAL, then the command operates in the global sandbox. LXeCMD_OK means that only a sandbox containing an object with the specific GUID returned is supported. Sandboxed commands can NOT be undoable.

LxResult Message(LXtObjectID self, void **ppvObj)

Each command contains an ILxMessage object. This can be obtained through the following method. This object is used for by the Execute() method and others to report error states. The client must release the message returned by this method.

LxResult Enable(LXtObjectID self, LXtObjectID msg)

A command may be disabled based on the current environment. This function can be called to see if a command is enabled. LXe_CMD_DISABLED will be returned if the command is disabled and the message string will be set to a user-readable string describing the condition. This simply checks to see if the command itself could be fired; it does not check to see if the arguments are set and valid. There is an alternate disabled state, LXe_CMD_NOT_AVAILABLE. This should be set if there is no context at all for the command’s arguments, not even enough to display a control of the correct type in an attribute sheet (as the dynamic datatypes arguments cannot be resolved). An example is the item.channel command, which requires an item selection so it can infer the type of channel; without that selection, it cannot guess what kind of control to display. LXe_CMD_DISABLED should be used when the argument parsing and dynamic datatypes can still be set, but there is no context for the command to execute in. In general, the return code should match the code set in the ILxMessage object.

LxResult ContainedEnable(LXtObjectID self, LXtID4 *types)

Commands in containers should provide a contained enable function. This is called by the container to see if the command can be executed. The ID_NULL-terminated types array should tested be with SelTopmostType() to ensure that they are the topmost type in the container.

void Interact(LXtObjectID self)

Just before the command executes, the Interact() method is called. This can be used to open file and confirmation dialogs so the user can confirm that they want to perform the operation. This is particularly useful for MODEL commands, since as soon as the Execute() method is called the undo stack is discarded; by opening dialogs from Interact(), the undo stack is preserved if the user chooses to abort. The Interact() method does not return an error code. Instead, the ILxMessageID of the command is used just like it is in the Execute() method. If the code is anything besides LXe_OK(), the execute method is not called. This method is not called if LXxCMD_IS_USER_INTERACTION_OK() would fail. This allows the user to suppress any dialogs that might have been opened, including confirmation and file dialogs. Commands should perform default behaviors if this occurs.

void PreExecute(LXtObjectID self)

We have one final test before Execute() is called. The PreExecute() method can be used to verify that the command state is set in such a way that it can still execute. This is most useful if the command requires a filename, but the Interact() method was suppressed by the user, and the filename argument was not set. Rather than have a MODEL command fail and clear the undo stack, it instead can do a final test to ensure the appropriate arguments are set. Again, no LxResult code is returned; instead, the ILxMessageID that is part of the command itself is used to provide errors.

void Execute(LXtObjectID self, unsigned int flags)

The user should only be presented with dialogs or questions if LXxCMD_IS_USER_INTERACTION_OK() is true; otherwise, the command should handle the case quietly. Note that these flags are used by the command system itself, but are passed on to the command for its own benefit. Direct action should not be taken by the command based on these flags, and they can be safely ignored.

LxResult ToggleArg(LXtObjectID self, unsigned int *index, void **ppvObj, unsigned int *typeID, const char **typeName)

Toggle commands have a single argument that can have one of many possible but mutually exclusive states (for example, only one tool can be activate at a time). When inserted into an attribute sheet, a toggle button is created that switches between an “off” state and the “on” state assigned to that arg in the sheet definition. When one of these buttons is activated, other buttons using the same command but different “on” states are automatically turned off. tool.set is an example of a command that does this, creating toggle buttons in attribute sheets that determined the currently active tool. Note that when attrs sets up the UI for a toggle arg command, if the toggle arg is optional and has no value, the command will be created as a simple button, not a toggle command. The command stores the “off” state in its definition, as well as the index of the toggle argument and its ExoType as either (or both) an ID and name. This method can retrieve any or all of these states. The index, value, typeID or typeName can be NULL if desired, in which case only the non-NULL arguments will be set. Note that the ppvObj value argument should be considered read-only, as it is owned by the command. However, the ILxValueID returned must be released through XObjectRelease() by the client. If no arguments are set for toggling in this manner, LXe_CMD_NOT_AVAILABLE is returned.

LxResult ArgFlags(LXtObjectID self, unsigned int index, unsigned int *flags)

Although most of the argument data is read from the command’s ILxAttributes interface, there is some extra information not encapsulated there. This method allows the flags of a particular argument to be read.

LxResult ArgClear(LXtObjectID self, unsigned int index)

The INIT_ONLY flags are only set during initialization, and include the following:

  • OPTIONAL If present, the argument is optional for the command to work. By default all arguments are required.

  • QUERY If present, the query function can be used to get the value for a control. Only arguments with this flag can be used in an Attribute Sheet.

  • READONLY If present, the argument is not editable by the user, and is there purely to provide statistical information, such as point/polygon counts or image bit depth. Read only arguments display as special labels in forms, not as interactive controls. Read-only implies queriable.

  • VARIABLE If present, the datatype for the argument is variable. The datatype must be set with the datatype callback using the REQFORVARIABLE arguments as keys, and thus this flag is not compatible with REQFORVARIABLE.

  • DYNAMICHINTS If present, the text hints array member is overridden by the callback provided to CmdDefineTextHintFunc(). See that function for more information. The hints array can still be provided and used as defaults if the callback returns NULL. REQFORVARIABLE arguments will be set before this function is called, and thus REQFORVARIABLE and DYNAMICHINTS are not compatible.

  • REQFORVARIABLE If present, the argument is used as to determine the datatype of a variable argument. These arguments will be set before any others, allowing them to be read from the datatype and dynamic hints callbacks for setting those argument’s datatypes and hints. They will not show up in the command dialogs, since changing them could change the type of control presented in the dialog. Note that it is technically legal to have an argument that is both OPTIONAL and REQFORVARIABLE; in this case, the argument is required only if it is set, and it is up to the command to make sure it is set before trying to use it, and it must handle the case of the argument not being set.

  • HIDDEN If present, the argument can be entered from a command line, but is not shown in the command dialog. This is useful for arguments that are only really uesful internally or from scripts but not in the command dialog.

  • DYNAMIC_DEFAULTS If set, the default values for the argument will always be used when displaying in a dialog. Normally, the dialog caches non-query arguments so the same value will show up the next time the dialog is opened, but behavior isn’t desirable for dynamically-computed values.

  • LXfCMDARG_DIALOG_ALWAYS_SETS Normally, when a command dialog is opened for the user, only the arguments the user has actually changed will be passed to the client. If this flag is set, an optional argument will always get a value if the dialog was opened, even if the user did not change the value. This is useful when the previous dialog values are used as defaults for another argument’s value, such as in poly.setMaterial.

  • LXfCMDARG_CAN_QUERY_WHEN_DISABLED Normally, if the command is disabled, none of its arguments can be queried. This simplifies the command’s Query() method by removing the need to repeat the enable test there where the query relies on the current system state. However, there are times when a command is disabled even though a query state is available, and thus can still display a useful state in the UI. A common case is tool and item properties, where the user has turned off a feature via a checkmark, which in turn causes this command’s control to appear disabled in the interface.

  • LXfCMDARG_DIALOG_DIVIDER_AFTER_ARG If set, an divider will be inserted between the controls representing this argument and the next argument in the command’s dialog. This allows for some extra organization within the dialog. The STATE_ONLY flags are used for testing the current state of arguments: As of modo 701, this flag has been superceded by the more powerful DialogFormatting() method.

  • VALUE_SET If present, the value of an argument has been set by the user (but does not necessarily represent an internal default) and can be retrieved from the ILxAttributes interface. If not present, the value has not been set by the user; however, a static default value may still be present. Furthermore, both default and queried values (which can be based on the system state) may be different from the set value. Arguments without this flag set will not be displayed in the command history. You should only set the VALUE_SET flag for your argument if your command’s ILxAttributes interface’s SetFlt(), SetInt() or SetString() have been called, or if Value() was called with writeOK set to true. Until then, the argument should be considered unset, but calls to GetFlt(), GetInt(), GetString() and Value() should still succeed by returning a default initial value for the argument.

  • CHANGED If present, the value of an argument has been changed through the DialogArgChange() method. This lets the command system know that it should use this value, even if VALUE_SET is false or the value can be queried. This is only used for command dialogs.

  • REQFORVAR_SET If present, then ILxCommand::ArgSetDatatypes() has been called and the variable datatype arguments have had their datatypes set. This means that the values of variable datatype arguments can now be set, and required-for-variable arguments are now “locked”. Note that this flag is the same for all arguments, and is really a property of the command and not a single argument. This flag is not relevant if the command does not have any variable datatype arguments. These macros are provided for quick tests on specific arguments.

  • ISREQFORVARIABLE() This returns true if the argument is required to set a variable argument’s datatype.

  • ISVARIABLE() This returns true if the argument has a variable datatype.

  • ISREQUIRED() A pure required argument is one that has none of these flags set, or only the REQFORVARIABLE flag. Required-for-variable-datatype arguments must be set before the command can be run (although optional ones need not be set at all). This returns true if this is the case.

  • ISNEEDED() Arguments that are not OPTIONAL or READONLY arguments must have a value before the command can be run. This can be used to test an argument to see if it is needed.

  • ISQUERY() This returns true if the value of an argument can be obtained directly from the command. LXfCMDARG_QUERY and LXfCMDARG_READONLY arguments can do this.

  • ISSET() This returns true if the value of an argument is set, and false if not. This clears the value for an argument, resetting its VALUE_SET flag.

LxResult ArgResetAll(LXtObjectID self)

This clears the values of all arguments in the command.

LxResult ArgSetDatatypes(LXtObjectID self)

Commands that have arguments with dynamic datatypes can use this function to set those datatypes. This will be called by the command system itself when all required for variable arguments have been set, and then whenever a required for variable argument’s value changes. When changing an argument’s datatype, it is assumed that the argument’s value has also been cleared. If the arguments new datatype is the same as the old datatype (so, the datatype didn’t actually change), the argument’s value should not be cleared.

LxResult ArgUserName(LXtObjectID self, unsigned int index, const char **userName)

Arguments also have user-readable names provided through these methods. Note that the wrapper will always return a valid string if the argument index is valid, and return LXe_CMD_NOT_AVAILABLE otherwise.

LxResult ArgDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgExample(LXtObjectID self, unsigned int index, const char **example)
LxResult ArgType(LXtObjectID self, unsigned int index, const char **type)

Some arguments use text hints to display a list of choices. Text hints are represented as internal strings that are not very human-readable. UI- friendly strings can be obtained via an “ArgumentType” atom on the argument’s cmdhelp. This in turn references an “ArgumentType” hash at the root of the “CommandHelp” block, and contains usernames and descriptions for each text hint, and for the ArgumentType itself. Because the ArgumentType is stored at the root of the CommandHelp block, the same ArgumentType can be used to provide user strings for multiple commands that use the same text hints. Information about the ArgumentType can be accessed with these functions. ArgType() returns the internal argument type name, which may be fail if no type is set in cmdhelp; the other functions return human-readable strings if available.

LxResult ArgTypeUserName(LXtObjectID self, unsigned int index, const char **userName)
LxResult ArgTypeDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgOptionUserName(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **userName)

The individual options in the argument type (such as popup entries) can also be listed. The username method will always return a valid string, falling back to the internal name if no username can be found. index is the index of the argument, while optIndex is the index of the option in the LXtTextValueHint array.

LxResult ArgOptionDesc(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **desc)
LxResult DialogInit(LXtObjectID self)

If all required arguments of a command aren’t set by the user when it is executed, a dialog is opened to ask for those values. This method is called to allow the dialog to set the values of any of its arguments after the last used dialog values and any queried values have been plugged in. Note that some or none of arguments may have values when this method is called.

LxResult DialogArgChange(LXtObjectID self, unsigned int arg)

This method is called by command dialogs and similar entities to let the command know that one of its arguments has been changed by the user. It allows the command to change the value of any of its arguments to provide more useful default values based on system state or the set values of other arguments. For example, the poly.subdivide command has a different default “Max Smoothing Angles “depending on what the mode argument is set to. Note that the flag LXfCMDARG_CHANGED should be set on arguments whos values have been modified by the change function, and the LXfCMDARG_VALUE_SET flag should be unset (since the changed value is presumably a default of some sort). The CHANGED flag lets the command system know that it should use the current argument value, while unsetting VALUE_SET tells the command system to not include that value in the output string in the command history.

LxResult ArgEnable(LXtObjectID self, unsigned int arg)

Dialogs will often call this method to see if a control within should be enabled or disabled. An example is that the Max Smoothing Angle control in the poly.subdivide command should be disabled when in Faceted mode. Return LXe_OK if enabled or LXe_CMD_DISABLED if disabled.

LxResult ArgParseString(LXtObjectID self, unsigned int argIndex, const char *argString)

Normally, the command system automatically parses arguments for each command. However, commands are also given an opportunity to manually parse the arguments themselves. This method is called for each argument just before its value is parsed out of the command line. If the method handles all argument parsing, it should return LXe_OK and set its own value. If it wants the command system to parse the argument, this should return LXe_NOTIMPL. It is important to note that this function is called only when the arguments are parsed as a string; directly setting the argument values via the ILxAttributes interface will not call this function as the arguments are already in in their intrinsic forms and never presented as strings.

LxResult Copy(LXtObjectID self, LXtObjectID sourceCommand)

This function copies the dynamic contents of one command into another. This should include everything possible, such as the argument values and error states. Note that this will only work on commands that have the same tag; dissimilar commands can not be copied to each other. For this reason, it can be assumed that the two instances have the same internal data and thus can be manipulated directly without the need to go through the interface when creating an implementation. To create a new duplicate of a command, use the command system global’s SpawnFromCommand() method.

LxResult Query(LXtObjectID self, unsigned int index, LXtObjectID vaQuery)

Querying is done through this function. An ILxValueArray interface is provided to the command, which is filled in with as many values as the current argument may represent in the current environment. This is the main way that clients can ask commands about their VALUE argument’s default states. The values in the ILxQuery will have the same datatype as the argument being queried.

LxResult NotifyAddClient(LXtObjectID self, int argument, LXtObjectID object)

Commands need to communicate with clients, such as the attribute system, when their data needs to be refreshed in the user interface. The client calls this method to let the command know that it wants to be notified when it needs to be updated. Normally, a client asks specifically for the notifier associated with a single argument of a command (say, because it’s displaying a UI for the queried value of that argument), so the client needs to specify which argument they would like additional notifiers from. If the argument index is -1, then only the notifers defined by the entire command will be added. Clients rarely have to implement this method themselves, but can if they want to. If not implemented, adding and removing clients is handled automatically by calling the command’s ILxUIValueHInts::NotifierCount() and NOtifierByIndex() methods.

LxResult NotifyRemoveClient(LXtObjectID self, LXtObjectID object)

When a client no longer needs to listen for notifications, it calls this method. Clients should be automatically removed from the queue when the command object is released as well.

LxResult DialogFormatting(LXtObjectID self, const char **formatting)

Any argument not included in the string will be omitted from the dialog. This can be used as an alternative to the HIDDEN argument flag. The command dialog will not open if all arguments are hidden, and the command will simply fail.

LxResult IconImage(LXtObjectID self, int w, int h, void **ppvObj)

This alternative to the Icon() method allows a command to return a dynamically-defined image. This is rarely used, as the config-based Icon() method is preferable in most cases. The image returned must be of the w and h provided; if not, the image will simply be discarded and ignored. In general, this method is called before calling Icon(), with Icon() being used if IconImage() is not implemented. Note that as of 801, this is only supported on simple buttons in Form Views, and is not used for popups, ToolChoices, pie menus, or any other kind of control.

bool GetMessage(CLxLoc_Message &msg)

User Class Only:


LXfCMD_SELECT

The current command flags are available through this function. A command may return different flags based on its required arguments. The following flags can be set only during setup:

  • SELECT If present this flag marks the command as a selection command.

  • QUIET These are a special type of command that allows lower-level operations to be wrapped. They do not have an undo context, thus allowing them to issue undos themselves. The primary use of QUIET commands is specific UI behaviors that in turn call lower level commands to perform the actual operation. Since they do not show up in the history and do not have an undo context, a command block is often used to encapsulate a QUIET commands’ multiple sub-command firings. Otherwies, each sub-command will show up as a separate entry in the history.

If set, the command will not be recorded in the history or undo system when activated. This can be useful either for commands that make no sense in scripts, or for commands that are mearly front-ends for real commands. If a quiet command fires a real command, the real command will be recorded. QUIET commands do not directly affect the undo stack, but may fire commands that do. Note that each command fired by a QUIET command will show up as a separate events, so more complex uses should include a command block to wrap multiple undoable commands. The QUIET flag overrides all others.

Note that a QUIET command does not get an undo context, and in itself is not undoable, although the commands it fires can be undoable. If multiple commands need to be fired, a command block can be used, creating a single undoable event. Note that creating a command block within a QUIET command is not enough to begin executing undoable code.

  • POSTCMD This command supports the post command mechanism.

  • MUSTSETARG If set, at least one argument of a command that contains all optional arguments must be set for the command to execute. If no arugments have a value, a dialog is opened as though a required argument were missing. If any value is set, the command is executed.

  • EXTRA1 If set, app.undo does an extra undo after this command is undone. This flag is reset when this command is not fired in post command mode.

  • EXTRA2 If set, app.undo does an extra undo when next command block includes this flag.

These flags may be set both during setup and through the flags callback.

  • REPEAT The command supports key repeat and will be fired continuously while the shortcut key is held down.

  • UI The command affects the user interface. This affects how the command is shown in the Command History viewport. UI commands should not affect the model and are not undoable. UI commands can be executed from sandboxes if the UI flag is set for the sandbox.

  • MODEL The command affects the internal state of the program, such as modifying geometry, changing motions, or performing some other model-level change. Model commands are not undable by default, and cause any pending undos or redos to be purged. Model commands can NOT be used in a sandbox.

  • NO_EXEC The command is not executable, and its Interact(), PreExecute(), Execute(), and other related methods will never be called. Such commands are often used for special behaviors like form command lists (FCLs), command filters in forms, and so on. The string defined by the command’s NoExecReason atom in its cmdhelp will be used to tell the user whey it is never executed.

  • UNDO This defines an undoable MODEL command, which can be undone and redone. The command is responsible for correctly registering its undos with the undo system, or calling other functions that do this themselves. Undoable commands can NOT be used in a sandbox.

  • UNDO_UI This defines an undoable UI command. These are similar to undoable MODEL commands, but undo UI constructs. They are also fairly transient; when a MODEL or undoable MODEL command is executed, any undoable UI command undos or redos are flushed. They are mostly intended to allow the user to correct immediate or very recent mistakes made to UI constructs themselves, rather than allowing them to step all the way back to the beginning of UI changes as can be done with undoable MODEL commands. Note that UNDO_UI commands can only be executed as a root command, or a child of another UNDO_UI command or UNDO_UI command block and retain their undos; executing as a child of any other command or block type will cause the undos to be lost.

  • UNDOSPECIAL This is used by the commands that actually modify the undo state directly through the undo system, such as app.undo, app.redo and app.undoClear. It should rarely ever be used. UNDOSPECIAL commands are very much like QUIET commands, and cannot be called from sub-commands or inside scripts, and are not recorded by the command history that they are likely changing.

  • UNDO_AFTER_EXEC This flag is used in conjunction with UNDO or UNDO_UI. The command can execute undoable actions as normal, but after the command finishes executing the undo blocks within are discarded, effectively undoing the command, even if it executes successfully. This is useful when performing temporary operations where you need to modify the scene but don’t want those changes to be permanent. The command will appear in the history as a side effect command.

  • Side Effect This isn’t a flag, but rather an absence of the UI, MODEL, UNDO or UNDOSPECIAL flags. If none of these are set, this is a Side Effect command. They are basically the same as UI commands, but don’t shuffle through the command history during undos. Side Effect commands can be executed from sandboxes if the UI flag is set for the sandbox.

  • SANDBOXED Sandboxed commands are not undoable, and are not recorded in the command history. They can only be executed in a sandbox containing an object with the interface GUID returned by the command’s Sandbox() method. The Sandbox() method is not used elsewhere. Sandboxed commands are special commands used for scripting in specific contexts.

  • SELECTIONLESS Marks a command that does not rely on the selection for the purposes of region assignments, and may derrive the selection itself or simply not use any kind of selection. If this command is executed as part of a region assignment, it will not cause the Pick function to be triggered first.

  • STICKYLESS Normally, executing a command with a boolean argument marked for query will that is mapped to a key in the Input Editor will automatically act as a sticky if the key is held down for a brief period of time instead of being tapped. This can be undesirable for certain commands, especially those like restoring layouts in palettes that for some reason seems to delay the key up event. Making those commands sticky-less will keep them for being considered for sticky key behaivor tapping and holding the key will only execute the command on down, not again on up.

  • INTERNAL If set, the command is hidden from the command list in the Command History. It will still show up in the undo list when executed.

  • MOUSEDOWNOK The command can be executed while a mouse button is down. This should only be used by UI commands, as performing undos or other actions could create very undesirable performance issues.

  • DEFER_INTERACTIVITY Commands that use arguments that can be represented as numeric edit fields or sliders can result in the command being called many times in quick succession. If the command requires a lot of processing (such as a script), it can significantly hamper interactivity. Although all efforts should be made to improve the performance of the command, this is sometimes unavoidable. DEFER_INTERACTIVITY tells the UI (such as attrs/forms) to not call the command until the user has stopped interacting with its controls (say, they released the mouse button). This can dramatically improve the apparent responsiveness of the application, although at the expense of real-time updates.

  • LXfCMD_QUIET

  • LXfCMD_POSTCMD

  • LXfCMD_MUSTSETARG

  • LXfCMD_EXTRA1

  • LXfCMD_EXTRA2

  • LXfCMD_SELECTIONLESS

  • LXfCMD_STICKYLESS

  • LXfCMD_INTERNAL

  • LXfCMD_MOUSEDOWNOK

  • LXfCMD_INIT_ONLY

  • LXfCMD_REPEAT

  • LXfCMD_DEFER_INTERACTIVITY

  • LXfCMD_UI

  • LXfCMD_MODEL

  • LXfCMD_UNDO

  • LXfCMD_UNDO_UI

  • LXfCMD_UNDOSPECIAL

  • LXfCMD_SANDBOXED

  • LXfCMD_UNDO_AFTER_EXEC

  • LXfCMD_NO_EXEC

  • LXfCMD_TYPES

  • LXxCMD_IS_SIDEEFFECT

  • LXfCMD_UNDO_INTERNAL


LXfCMDHINT_SUPPRESS_INFOS

Commands can also provide hints on how the command system should act after the command has executed. The most common use is to suppress the command’s own error dialogs if any sub-commands have already opened one of that type. This only affects dialogs that would be implicitly opened by the message object set by the command during its execution. Note that the “command disabled” dialog is considered an error code.

  • LXfCMDHINT_SUPPRESS_WARNINGS

  • LXfCMDHINT_SUPPRESS_ERRORS

  • LXmCMDHINT_SUPPRESS_DIALOGS


LXfCMD_ALERT_NONE

The execute function is used to fire a command using its current arguments. A client calls this to actually fire the command, while the command itself looks at its arguments and performs whatever operation it is going to do. Note that unlike most methods, the execute function does not return an LxResult. Instead, errors should be set and read with the ILxMessage interface of the command object.

The execution flags can be any combination of the following, including 0.

The ALERT flags are used to let the command system know how the user should be notified about errors, if at all.

SHOWERR causes errors during execution to be displayed in a modal dialog.

SHOWERR_FORCESUB will force sub-commands to use the SHOWERR flag, even if they do not specify it themselves. This implies the SHOERR flag on this command as well as its descendants.

SHOWERR_FORCESUB_OFF will force sub-commands to not use the SHOWERR flag, even if SHOWERR is specified. This disables SHOWERR on the parent as well.

SYNTAXERR causes syntax errors during argument parsing to be displayed in a dialog; if unset, they are silently ignored.

  • LXfCMD_ALERT_SHOWERR

  • LXfCMD_ALERT_SHOWERR_FORCESUB

  • LXfCMD_ALERT_SHOWERR_FORCESUB_OFF

  • LXfCMD_ALERT_SYNTAXERR

  • LXfCMD_ALERT_MASK


LXiCMD_EXEC_WITH_PARENTS_FLAGS

The EXEC flags are used purely during execution. When executing a command from another command’s Execute() method, the sub-command should be passed the same flags that were passed from the parent command. This ensures that dialog suppression and similar features are properly respected by child commands. So that’s what you should do. However, this can be inconvenient if the sub-command is executed from a helper function. Rather than forcing you to pass the execution flags through your helpers, you can use this method to obtain the flags from the currently executing command. If no commands are being executed, this returns the default execution flags, so youc an use this at any time.

As you can see, this is defined as -1. You can use -1 directly if you don’t want to type LXiCMD_EXEC_WITH_PARENTS_FLAGS all the time. This is gauranteed to not change in the future.

  • LXxCMD_EXEC_WITH_PARENTS_FLAGS


LXfCMD_EXEC_NONE

Here is an explination of the specific flags, which can be tested from your Execute() method or passed when executing sub-commands. In general, though, you hsould use LXmCMD_EXEC_WITH_PARENTS_FLAGS GETARGS will force the command system to open a dialog and ask for any missing required arguments; missing optional arguments will not trigger this behavior. GETARGS_FORCESUB will force sub-commands to use the GETARGS flag, even if they do not specify it themselves. This implies the GETARGS flag on this command as well as its descendants.

GETARGS_FORCESUB_OFF will force sub-commands to not use the GETARGS flag, even if GETARGS is specified. This disables GETARGS on the parent as well.

ALWAYSGETARGS will cause the command dialog to open even if all required arguments are set.

TOGGLED is used to indicate that the command is being executed as the result of a sticky key being released. This flag is not set when the command is fired on key. Sticky keys are defined as the user holding down a key mapped to a queried boolean or ToggleArg command (which in turn fires the command), clicking/dragging with the mouse, and then releasing the key (which fires the command again with the TOGGLED flag set). Commands can read this flag in there Execute() method to perform special behaviors when their sticky key is released.

NO_ABORT makes it so that progress monitors will not have abort buttons. This is useful for specialized tasks where you need to execute a series of commands and never want the user to be able to abort. It should only be used rarely, and only in scenarios where an abort is impossible.

Note that both GETARGS and ALWAYSGETARGS may result in the set arguments of a command changing, even if there is an error or the user aborts the dialog.

  • LXfCMD_EXEC_GETARGS

  • LXfCMD_EXEC_GETARGS_FORCESUB

  • LXfCMD_EXEC_GETARGS_FORCESUB_OFF

  • LXfCMD_EXEC_ALWAYSGETARGS

  • LXfCMD_EXEC_TOGGLED

  • LXfCMD_EXEC_NO_ABORT

  • LXfCMD_EXEC_MASK

  • LXxCMD_EXEC_MASK


LXxCMD_IS_USER_INTERACTION_OK(flags)

Various commands need to open dialogs or other user interface elements. However, this is not always desirable in all contexts, such as when the command is running from a script. Before trying to open any dialogs or otherwise interacting with the user the command should use the following macro with its execution flags to see if such interaction is allowed.


LXfCMD_EXEC_PARENT_FLAGS_PASSED_MARKER

DEFAULT is the default set of flags that should be used in most circumstances for execution, argument parsing, etc. The high bit is reserved for internal use. It is used to esnure that sub-command executions are passed their parent’s command flags. However, in rare cases it may be intentional to pass execution flags to a sub-command. In this case, the internal marker flag can be directly specified to suppress the errors that will otherwise be reported.

  • LXxCMD_EXEC_WERE_PARENT_FLAGS_PASSED


LXfCMD_ALERT_DEFAULT

These are the default execution and alert flags.

  • LXfCMD_EXEC_DEFAULT


LXfCMD_PARSED_FLAGS

We also hve one other special flag. If any of the GETARGS or SHOWERR flags were set by parsing the command string for leading +, ++, ! or !! flags, then PARSED_FLAGS will also be set.


LXfCMDARG_INIT_ONLY

Flags can be any combination of the following. If none of these are set, the argument is required, and must be set by the client/user when the command is fired. The bulk of these flags are set during initialization.

  • LXfCMDARG_OPTIONAL

  • LXfCMDARG_QUERY

  • LXfCMDARG_READONLY

  • LXfCMDARG_VARIABLE

  • LXfCMDARG_DYNAMICHINTS

  • LXfCMDARG_REQFORVARIABLE

  • LXfCMDARG_HIDDEN

  • LXfCMDARG_DYNAMIC_DEFAULTS

  • LXfCMDARG_DIALOG_ALWAYS_SETS

  • LXfCMDARG_CAN_QUERY_WHEN_DISABLED

  • LXfCMDARG_DIALOG_DIVIDER_AFTER_ARG

  • LXfCMDARG_STATE_ONLY

  • LXfCMDARG_VALUE_SET

  • LXfCMDARG_CHANGED

  • LXfCMDARG_REQFORVAR_SET

  • LXxCMDARG_ISREQFORVARIABLE

  • LXxCMDARG_ISVARIABLE

  • LXxCMDARG_ISREQUIRED

  • LXxCMDARG_ISNEEDED

  • LXxCMDARG_ISQUERY

  • LXxCMDARG_ISSET

ILxCommandDBHelp

class ILxCommandDBHelp

This optional interface is used to aid in setting up the documention. It is only implemented by commands that do their own custom help key lookup, such as item.channel. Most commands can skip it. Each line of the string returned commonly starts with “\n ” so that it’s nicely formatted.

Public Functions

LxResult DBHelp(LXtObjectID self, const char **dbhelp)
LxResult DBTooltip(LXtObjectID self, const char **dbtooltip)

Same idea, but for tooltips.

ILxUIHints

class ILxUIHints

Hints for the user interface can be provided through an ILxUIHints object passed to the ILxAttributes::UIHints() method. Different systems may implement different ILxUIHints for their own purposes, which may result in slightly different behavior depending who is calling the UIHints() method. See ILxAttributes in valet/umath.qq for more information on UIHints(). Note that systems generally expect an ILxMessage interface on the UI Hints object that is used to descide if the argument is enabled and to get a disable message.

Public Functions

LxResult Class(LXtObjectID self, const char *c)

Class changes the class of an attribute. The class change should be consistent with the argument type. Classes match those used by the old XPanels system (“iBoolean”, “integer”, “iPopChoice”, etc).

LxResult Label(LXtObjectID self, const char *label)

The argument’s user-readable label can be set with this method. The string should be translated into the user’s language.

LxResult MinInt(LXtObjectID self, int min)

These can be used to set the minimum and maximum for integer and float-based controls.

LxResult MaxInt(LXtObjectID self, int max)
LxResult MinFloat(LXtObjectID self, double min)
LxResult MaxFloat(LXtObjectID self, double max)
LxResult StepInt(LXtObjectID self, int step)

This controls the step size of a minislider.

LxResult StepFloat(LXtObjectID self, double step)
LxResult Track(LXtObjectID self, unsigned int state)

If tracking is turned on, drags on the minislider will cause instant updates.

LxResult StringList(LXtObjectID self, const char **strings)

Choice/Popup controls can take a simple string list if desired.

LxResult TextLines(LXtObjectID self, unsigned int lines)

String controls can have multiple lines, as set by this hint.

LxResult TextFixedWidthFont(LXtObjectID self, unsigned int state)

String controls can also be told to use a fixed width font.

LxResult TextPasswordMode(LXtObjectID self, unsigned int state)

Sometimes it is useful for string controls to obscure their text, such as when entering a password, which can be set with this method.

LxResult ValuePresetCookie(LXtObjectID self, const char *cookie)

Control types like numeric edit fields support “value presets”. This creates a popup containing a user-extensible list of common values for the argument. For example, rather than forcing the user to lookup or remember what the index of refraction is for glass, they can simply click on the popup and select glass from the list. Value presets are handled completely automatically by the attributes/forms system. All the client needs to do is provide a cookie, which is used to load and save the list of values from the config. The cookie can be shared by multiple controls if desired, and need not be unique.

LxResult ForceUpdate(LXtObjectID self)

Force update is a special flag; if set, this will force the UI to refresh even if the UI object hasn’t otherwise changed since the last time the UI object was requested. This is most useful if your popup functions changed their list of properties since the last time they we called, thus forcing a refresh.

LxResult BooleanStyle(LXtObjectID self, unsigned int style)
LxResult ChannelFlags(LXtObjectID self, unsigned int flags)

  • OUTPUT_ONLY If this is set on a channel, it is consider read-only, and cannot have an input. If set, in schematic, the connection dot is displayed ONLY on the right side of the node to indicate that it is an output only.

  • INPUT_ONLY If this is set on a channel, it is consider write-only, and cannot have an output. If set, in schematic, the connection dot is displayed ONLY on the left side of the node to indicate that it is an input only. The INPUT_ONLY & OUTPUT_ONLY flags are mutually exclusive.

  • SUGGESTED If this is set on a channel, this channel should be added by default in schematic.

  • HIDDEN If marked as hidden, this channel will not be visible in the channel list.

LxResult ButtonHasPopoverDecoration(LXtObjectID self, int state)

Most buttons perform actions or are toggles. Buttons that open dialogs usually have ellipsis in the label (like “Save…”), and ToolChoices have a small triangle in the lower-right corner. It is also useful to mark buttons that open popovers differently from the others. This flag can be set to indicate executing the command opens a popopover instead of performing an action, and will result in special decoration being added to the button’s face.

LxResult ClipChoiceSupportsGroups(LXtObjectID self, unsigned flags)

For ClipChoices (&clip datatype) the brower normally shows only clip items which can be evalauted for an actual image. Flags can be set with this method to allow other types of items as well.

  • FOLDERS Image folders, which are also clip item but have no composite image.

  • GROUPS Group items that contain images.

LxResult VertmapType(LXtObjectID self, LXtID4 type)

The type of vertex map. Default is UV map.

LxResult VertmapAllowNone(LXtObjectID self, int state)

Specifies when a value of (none) is allowed in the list. Default is TRUE.

LxResult VertmapItemMode(LXtObjectID self, int state)

Specifies that the list is only generated from the selected item. Default is FALSE.

LxResult InfoTextUseSmallFont(LXtObjectID self, int state)

Info text controls (usually queried read-only command arguments) can be set to draw with a small font instead of the default font.

LxResult FormFilterPriority(LXtObjectID self, int priority)

LXiBOOLEANSTYLE_DEFAULT

Boolean controls are normally represented as checkmarks in forms. The user can override this behavior from the From Editor to create a toggle-style button instead. This hint can be used by the client to state its preference for checkmarks vs. toggle-style buttons.

  • LXiBOOLEANSTYLE_CHECKMARK

  • LXiBOOLEANSTYLE_BUTTON


LXfUIHINTCHAN_OUTPUT_ONLY

There are also a few channel-specific flags. These are usually used in specific contexts, and are described in detail below:

  • LXfUIHINTCHAN_INPUT_ONLY

  • LXfUIHINTCHAN_SUGGESTED

  • LXfUIHINTCHAN_HIDDEN

  • LXfCLIPCHOICE_FOLDERS

  • LXfCLIPCHOICE_GROUPS


LXiCMD_FORMFILTERPRIORITY_NO_MATCH

Commands are often assigned to forms to decide if the form is visible or not. These command filters normallly just need to be enabled or have their queried state return true, and that’s that. However, certain forms like Item Properties show a series of vertical tabs, and forms attempts to intelligently determine which tab to automatically select if a previously selected tab is no longer visible due to filtering. Usuually the most recently selected item’s tab should be the one that is selected. Other forms may have other crieteria for deciding which tab is first based on their command filters. Usually all vtab forms in a form view use the same command filter, or at least commands that use the same criteria. The form filter priority is used to decide which tab best matches the current selection. The closer the priority is to 0, the more likely it is to have its tab chosen. Often this is just the index of the item in the selection that matches the filter’s criteria. If multiple filters returns the same priority, the first form in the list is chosen. Filters with priorities below LXiCMD_FORMFILTERPRIORITY_DEFAULT will always be chosen before legacy filters and unfiltered forms. If the priority is implemented, the command only needs to implement its UIHints method for the LXiATTRUI_ANY “argument”, to be a filter, and no other methods the enable state and query value will be ignored. A priority of LXiCMD_FORMFILTERPRIORITY_NO_MATCH indicates that the filter doesn’t match and the form should be hidden. The command flags should be set to LXfCMD_NO_EXEC as well.

Note that if a priority is set (including NO_MATCH), the enable function and queried argument values will not be tested only the priority will be used to decide if the form is filtered or not.

  • LXiCMD_FORMFILTERPRIORITY_LAST

  • LXiCMD_FORMFILTERPRIORITY_DEFAULT

ILxUIHintsRead

class ILxUIHintsRead

This sibling interface provides a way to read the values from an ILxUIHints object, if it implements the interface. The method names are the same, but they return values instead of setting them.

Public Functions

LxResult Class(LXtObjectID self, char *buf, int len)

The remainder of the methods match those in ILxUIHInts; see the ILxUIHInts docs for more information about how they are used and what values they return. The only method that is missing is StringList(), which is replaced with the enumeration methods StringListCount() and StringListByIndex(). If a properly wasn’t set in the ILxUIHInts, the associated method will return LXe_NOTAVAILABLE. Be sure to check the return code before using the returned value.

LxResult Label(LXtObjectID self, char *buf, int len)
LxResult MinInt(LXtObjectID self, int *min)
LxResult MaxInt(LXtObjectID self, int *max)
LxResult MinFloat(LXtObjectID self, double *min)
LxResult MaxFloat(LXtObjectID self, double *max)
LxResult StepInt(LXtObjectID self, int *step)
LxResult StepFloat(LXtObjectID self, double *step)
LxResult Track(LXtObjectID self, unsigned int *state)
LxResult StringListCount(LXtObjectID self, int *count)
LxResult StringListByIndex(LXtObjectID self, int index, char *buf, int len)
LxResult TextLines(LXtObjectID self, unsigned int *lines)
LxResult TextFixedWidthFont(LXtObjectID self, unsigned int *state)
LxResult TextPasswordMode(LXtObjectID self, unsigned int *state)
LxResult ValuePresetCookie(LXtObjectID self, char *buf, int len)
LxResult ForceUpdate(LXtObjectID self, int *state)
LxResult BooleanStyle(LXtObjectID self, unsigned int *style)
LxResult ChannelFlags(LXtObjectID self, unsigned int *flags)
LxResult ButtonHasPopoverDecoration(LXtObjectID self, int *state)
LxResult ClipChoiceSupportsGroups(LXtObjectID self, unsigned *flags)
LxResult VertmapType(LXtObjectID self, LXtID4 *type)
LxResult VertmapAllowNone(LXtObjectID self, int *state)
LxResult VertmapItemMode(LXtObjectID self, int *state)
LxResult InfoTextUseSmallFont(LXtObjectID self, int *state)
LxResult FormFilterPriority(LXtObjectID self, int *priority)

LXfVALHINT_POPUPS

The flags method determines which properties of the ILxUIValueHints object are valid. The appropriate flags must be set if you want the associated methods to be called.

  • POPUPS The attribute has a popup to select possible settings. The Pop…() functions will only be called if this is set.

  • POPUP_DIRECT This is a hint about how to construct the popup. If this is a string attribute then the user will be able to type in a string directly into an edit field, as well as selecting from a list of existing choices in the popup.

  • POPUP_ALPHA_SORT This causes the popup’s contents to be sorted alphabetically.

  • ITEMS The attribute is an item type (“&item” exoType), and the hint object provides a filter.

  • ITEMS_NONE The item popup can support a “(none)” option.

  • FORMS_COMMAND_LIST The forms command list functions are implemented. See below for more information.

  • POPUPS_NO_FILTER Disables the string filter on long lists.

  • LXfVALHINT_POPUP_DIRECT

  • LXfVALHINT_POPUP_ALPHA_SORT

  • LXfVALHINT_ITEMS

  • LXfVALHINT_ITEMS_NONE

  • LXfVALHINT_FORM_COMMAND_LIST

  • LXfVALHINT_POPUPS_NO_FILTER

ILxUIValueHints

class ILxUIValueHints

An ILxUIValueHints object can be allocated for an argument, and can be queried for more complex state.

Public Functions

unsigned Flags(LXtObjectID self)
unsigned PopCount(LXtObjectID self)

Popups are flat lists, and can be represented by integer or, preferably, string stirng-based arguments. Strings are prefereed because they are more scriptable and the order can be changed more easily without affecting legacy use. PopCount() returns the number of items in a popup. PopUserName() returns a human-readable string for display in the popup. PopInternalName() returns an untranslated, internal string that uniquely identifies theis item. It is only required when PopCategory() is used or when using a string-based argument.

const char *PopUserName(LXtObjectID self, unsigned index)
const char *PopInternalName(LXtObjectID self, unsigned index)
const char *PopToolTip(LXtObjectID self, unsigned index)

Tooltips strings can be returned by individual entries in the popup.

unsigned PopIconSize(LXtObjectID self, int *w, int *h)

Each entry in a poup can have an icon or image associated with it, which will appear to the left of the entry’s name. This method returns the amount of space reserved for the icons. If not implemented, no space is reserved.

LxResult PopIconImage(LXtObjectID self, int index, void **ppvObj)

These return an icon for a specific entry. If both fail, no icon will be drawn for that entry. The icon can be the name of an icon resource from a config file, or a custom ILxImageID, which will be released by the popup system.

LxResult PopIconResource(LXtObjectID self, int index, const char **iconResource)
LxResult PopFlags(LXtObjectID self, unsigned index, int *flags)
LxResult PopCategory(LXtObjectID self, const char **category)

This returns the name of a category. Combined with the popup functions defined above, this can be used to create a hierarchical popup based on categorization defined through the config. Each entry is assigned to a part of the hierarchy by adding named entries to the appropriate portion of the config file, and are easily extensible by third parties by simply adding new config entries. An example of category use is Add Layer popup in the Shader Tree. There is no flag matching this method; it will always be called for string-style controls, but you can return LXe_NOTIMPL if you do not want to use categories in your popup.

LxResult ItemTest(LXtObjectID self, LXtObjectID item)

The ItemTest() method is used to decide if a particular item should appear in an ItemChoice popup or not. This allows you to limit an ItemChoice to only the specific items that are releveant to you, rather than all items or all items of a given item type. Returning LXe_TRUE means that you want the item in the list, and LXe_FALSE means that it should not be in the list.

LxResult ColorPickerCommands(LXtObjectID self, char *rgb, char *alpha, char *rgbAlt, char *alphaAlt, char *useAlt, unsigned bufLens)

Commands with arguments using the “color” datatype are available for use in the color picker. This happens automatically when the user clicks on a color control in a form, which calls select.color to add the queried command to the color selection. Any command with a queriable “color”-datatype argument can be selected for the color picker through select.color. The limitation of the color controls adding the command that created them is that it can only add a single command representing the RGB component of the color. Sometimes there is a related command that implements the alpha component. Other times there is an alternate color, such as the FG and BG colors used by the paint tools. This method allows a command to override what commands are placed in the color picker selection when a control created from this command’s queried “color” argument is clicked on by the user A command can implement this method to return one or more command queries that should be used in place of the command itself. Note that the alpha commands are separate from the RGB commands. The useAlt command is used to decide if the main or alternate RGB and alpha are displayed in the color picker, and is used to swap them. RGB commands should have “color”-datatype arguments being queried. For example, “item.channel diffCol ?”. The queried argument is used both to get the current value and to change the value when the user picks a new color. Similarly, alpha commands should have a “percent”-datatype argument queried, and the useAlt command should have a “boolean” argument queried. All of these command are optional, and can be set to empty strings (first char ‘\0’) to skip them. If the method is not implemented, the current color selection will be used. If the RGB command string is empty, then the command itself will be used for that. If the alpha command is empty, then the alpha control in the color picker will be disabled. If rgbAlt is not empty, then the alternate color swatch and the swap icon will appear in the color picker. If the useAlt command is empty, “color.useAlt ?” will automatically be used instead. It is important to note that some clients may not want all the strings, in which case some of the pointers may be NULL.

LxResult NotifierCount(LXtObjectID self, int *count)

ILxUIValueHints is also used by tools attributes, item channels and other clients to allow them to specify notifiers so that their representations in the user interface can refresh when their values change. This first method returns the number of notifiers supported.

LxResult NotifierByIndex(LXtObjectID self, int index, const char **name, const char **args)

This second method returns the name of the notifier and its arguments as strings given a notifier index.

LxResult FormCommandListCount(LXtObjectID self, int *count)

The Form Command List (FCL) is a special feature used by very few commands. It is a powerful mechanism that allows a command to effectively dynamically insert controls in a form by providing them as a list of command strings. In this context, the “owning” command itself will not be execute, but rather those in the Form Command List may. Here’s how it works: when a command is in a form and an argument is queried, the attrs/forms system will first check for the LXfVALHINT_FORM_COMMAND_LIST flag. If not found, the command appears as normal. If the flag is found, however, the command itself will not appear in the form. Instead, each command represented by the strings returned by the Form Command List will be displayed in instead. If the command string starts with a dash and a space (“- “), then a divider will be inserted into the form using whatever follows the space as the label (and which is hopefully a translated, user-readable string). Ganging is also supported through its own special syntax. Ganging is started by prefixing a command string with an open curly brace and a space (“{ “). All controls after that will be ganged until a command prefixed with a closing curly brace and a space (“} “) is found. Note that even though the brace is closed before the command string, the command is still considered part of the gang. Viewports can be embedded in forms as well. This can be done through presets and viewport types. Viewport presets can be embedded with “+vpPreset presetHash”, where “presetHash” is the hash of the preset as stored in the config. A viewport type is added with “+vpType viewportType”. Arguments can then be set on the instanced viewport by immediately following the “+vpType” line with one or more “> argName argDataType argValue” lines, where “argName” is the internal name of the viewport’s argument, “argDataType” the internal name of the dargument’s datatype, and and everything after that space is the argument’s value. Any number of arguments can be added this way. Viewport types also have a special entry, “> =hash:”. This allows viewport types to save their state to the config with a custom hash, which immediately follows the colon. This is not supported for viewport presets, only for types. Since UI hints are defined per argument, the argument must be marked as queriable, even if the query method fails. When commands exist solely for the purposes of creating an FCL (item.channelsAsFormControls, for example), the LXfCMD_NO_EXEC command flag should be set to indicate that it is not executable, after which the Execute() method does not need to be implemented. It also also suggested to providing the NoExecReason cmdhelp atom to tell the user why the command does not support execution.

LxResult FormCommandListByIndex(LXtObjectID self, int index, const char **command)
LxResult CueText(LXtObjectID self, char *buf, unsigned len)

For strings, this is shown when the field contains no value and is otherwise completely empty. It is drawn dimmed, and disappears as soon as the user clicks in the field. Cue text is also used as the default value for read-only string controls when the string is empty so that we don’t leave a hole in the interface.

LxResult TextValidate(LXtObjectID self, const char *value, char *buf, unsigned len)

For strings, this function will be called to validate the text value. It allows the client to modify the string, performing operations such as removing invalid characters, changing case, or clipping the length of the string.


LXmPOPFLAGS_GROUP_MASK

This method allows flags to be returned on a per-entry basis. It need not be implemented, in which case the default behavior occurs. The low bits are used to defined a “group mask”, casuing a divider to be inserted if two elements do not share the same group. Checkmarks can be added with the SELECTED flag, while a mixed state can be shown by using both SELECTED and UNSELECTED (UNSELECTED doesn’t need to be used by itself, as it is implied). Entries can be drawn ghosted with the DISABLED flag. Note that implement PopFlags() means that you are responsible for marking your currently selected item, if applicable.

  • LXfPOPFLAGS_SELECTED

  • LXfPOPFLAGS_UNSELECTED

  • LXfPOPFLAGS_MIXED

  • LXfPOPFLAGS_DISABLED

ILxUIValueHints3

class ILxUIValueHints3

This interface was retired in modo 13, and was replaced with an updated one that adds a few more methods.

Public Functions

unsigned Flags(LXtObjectID self)
unsigned PopCount(LXtObjectID self)
const char *PopUserName(LXtObjectID self, unsigned index)
const char *PopInternalName(LXtObjectID self, unsigned index)
const char *PopToolTip(LXtObjectID self, unsigned index)
unsigned PopIconSize(LXtObjectID self, int *w, int *h)
LxResult PopIconImage(LXtObjectID self, int index, void **ppvObj)
LxResult PopIconResource(LXtObjectID self, int index, const char **iconResource)
LxResult PopFlags(LXtObjectID self, unsigned index, int *flags)
LxResult PopCategory(LXtObjectID self, const char **category)
LxResult ItemTest(LXtObjectID self, LXtObjectID item)
LxResult ColorPickerCommands(LXtObjectID self, char *rgb, char *alpha, char *rgbAlt, char *alphaAlt, char *useAlt, unsigned bufLens)
LxResult NotifierCount(LXtObjectID self, int *count)
LxResult NotifierByIndex(LXtObjectID self, int index, const char **name, const char **args)
LxResult FormCommandListCount(LXtObjectID self, int *count)
LxResult FormCommandListByIndex(LXtObjectID self, int index, const char **command)
LxResult CueText(LXtObjectID self, char *buf, unsigned len)

ILxUIValueHints2

class ILxUIValueHints2

This interface was retired in modo 10.2, and was replaced with an updated one that adds a few more methods.

Public Functions

unsigned Flags(LXtObjectID self)
unsigned PopCount(LXtObjectID self)
const char *PopUserName(LXtObjectID self, unsigned index)
const char *PopInternalName(LXtObjectID self, unsigned index)
unsigned PopIconSize(LXtObjectID self, int *w, int *h)
LxResult PopIconImage(LXtObjectID self, int index, void **ppvObj)
LxResult PopIconResource(LXtObjectID self, int index, const char **iconResource)
LxResult PopFlags(LXtObjectID self, unsigned index, int *flags)
LxResult PopCategory(LXtObjectID self, const char **category)
LxResult ItemTest(LXtObjectID self, LXtObjectID item)
LxResult ColorPickerCommands(LXtObjectID self, char *rgb, char *alpha, char *rgbAlt, char *alphaAlt, char *useAlt, unsigned bufLens)
LxResult NotifierCount(LXtObjectID self, int *count)
LxResult NotifierByIndex(LXtObjectID self, int index, const char **name, const char **args)
LxResult FormCommandListCount(LXtObjectID self, int *count)
LxResult FormCommandListByIndex(LXtObjectID self, int index, const char **command)

ILxUIValueHints1

class ILxUIValueHints1

This interface was retired in modo 601, and was replaced with an updated one that adds a few more methods.

Public Functions

unsigned Flags(LXtObjectID self)
unsigned PopCount(LXtObjectID self)
const char *PopUserName(LXtObjectID self, unsigned index)
const char *PopInternalName(LXtObjectID self, unsigned index)
LxResult PopFlags(LXtObjectID self, unsigned index, int *flags)
LxResult PopCategory(LXtObjectID self, const char **category)
LxResult ItemTest(LXtObjectID self, LXtObjectID item)
LxResult ColorPickerCommands(LXtObjectID self, char *rgb, char *alpha, char *rgbAlt, char *alphaAlt, char *useAlt, unsigned bufLens)
LxResult NotifierCount(LXtObjectID self, int *count)
LxResult NotifierByIndex(LXtObjectID self, const char **name, const char **args)
LxResult FormCommandListCount(LXtObjectID self, int *count)
LxResult FormCommandListByIndex(LXtObjectID self, int index, const char **command)

LXiATTRUI_ANY

The UIHints() method is called to fill in an ILxUIHints object given an attribute index, thus providing it with a graphical user interface. Note that an index of LXiATTRUI_ANY may be passed in cases where information is being requested for the entire command (usually when the command is represented as a button in form, for example, or when used as a form command filter), instead of for a specific argument.

ILxAttributesUI

class ILxAttributesUI

It is not uncommon for clients sporting an ILxAttributes interface to need to present some kind of UI. Thus we have this sibling interface, ILxAttributesUI, which provides UI-specific additions. The ILxAttributes::Count() method is used to get the number of attributes as normal, with those indices being passed to the ILxAttributesUI methods to get information about a specific attribute.

Public Functions

LxResult UIHints(LXtObjectID self, unsigned int index, LXtObjectID hints)
LxResult UIValueHints(LXtObjectID self, unsigned int index, void **ppvObj)

This will allocate a value hints object for the given attribute, provided it has any hints that need to be queried. If index is LXiATTRUI_ANY, then the object should represent hints for the entire command, tool, etc. This is most commonly used to obtain notifiers for a command when used as a button in a form.

LxResult DisableMsg(LXtObjectID self, unsigned int index, LXtObjectID message)

This returns an attribute-specific disabled message if the argument is disabled by filling in an ILxMessageID. If the attribute is enabled, the code is set to LXe_OK; disabled attributes use the code LXe_DISABLED and may set a disabled string as well. The value returned from the method itself should match the code set in the ILxMessageID. For example, a boolean attribute may control an overall setting, while its sub-attributes are only valid if the boolean is true. If the boolean is false, then this function could return a message saying that the boolean needs to be set true for all the sub-attributes.


LXfCMDNOTIFY_VALUE

When the notifier wants to send an event to its clients, it uses this function. The notifier simply has to provide that kind of refresh that’s required (value, label, disable or datatype), and this function will take care of notifying all the clients.

  • LXfCMDNOTIFY_LABEL

  • LXfCMDNOTIFY_DISABLE

  • LXfCMDNOTIFY_DATATYPE

  • LXfCMDNOTIFY_CHANGE_ALL

ILxCommandEvent

class ILxCommandEvent

This is used to send the event (meaning, the changed flags) to a client as a result of CmdNotify() being called.

Public Functions

LxResult Event(LXtObjectID self, unsigned int flags)

ILxCommand1

class ILxCommand1

This interface was retired in modo 701, and was replaced with an updated one that adds new methods.

Public Functions

LxResult Tag(LXtObjectID self, LXtCommandTag *tag)
LxResult Name(LXtObjectID self, const char **name)
LxResult UserName(LXtObjectID self, const char **userName)
LxResult ButtonName(LXtObjectID self, const char **buttonName)
LxResult Desc(LXtObjectID self, const char **desc)
LxResult Tooltip(LXtObjectID self, const char **tooltip)
LxResult Help(LXtObjectID self, const char **help)
LxResult Example(LXtObjectID self, const char **example)
LxResult Icon(LXtObjectID self, const char **iconNames)
LxResult Flags(LXtObjectID self, unsigned int *flags)
LxResult PostExecFlags(LXtObjectID self, unsigned int *flags)
LxResult PostExecBehaviorFlags(LXtObjectID self, unsigned int *flags)
LxResult PostExecHints(LXtObjectID self, unsigned int *hints)
LxResult SandboxGUID(LXtObjectID self, const LXtGUID **guid)
LxResult Message(LXtObjectID self, void **ppvObj)
LxResult Enable(LXtObjectID self, LXtObjectID msg)
LxResult ContainedEnable(LXtObjectID self, LXtID4 *types)
void Interact(LXtObjectID self)
void PreExecute(LXtObjectID self)
void Execute(LXtObjectID self, unsigned int flags)
LxResult ToggleArg(LXtObjectID self, unsigned int *index, void **ppvObj, unsigned int *typeID, const char **typeName)
LxResult ArgFlags(LXtObjectID self, unsigned int index, unsigned int *flags)
LxResult ArgClear(LXtObjectID self, unsigned int index)
LxResult ArgResetAll(LXtObjectID self)
LxResult ArgSetDatatypes(LXtObjectID self)
LxResult ArgUserName(LXtObjectID self, unsigned int index, const char **userName)
LxResult ArgDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgExample(LXtObjectID self, unsigned int index, const char **example)
LxResult ArgType(LXtObjectID self, unsigned int index, const char **type)
LxResult ArgTypeUserName(LXtObjectID self, unsigned int index, const char **userName)
LxResult ArgTypeDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgOptionUserName(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **userName)
LxResult ArgOptionDesc(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **desc)
LxResult DialogInit(LXtObjectID self)
LxResult DialogArgChange(LXtObjectID self, unsigned int arg)
LxResult ArgEnable(LXtObjectID self, unsigned int arg)
LxResult ArgParseString(LXtObjectID self, unsigned int argIndex, const char *argString)
LxResult Copy(LXtObjectID self, LXtObjectID sourceCommand)
LxResult Query(LXtObjectID self, unsigned int index, LXtObjectID vaQuery)
LxResult NotifyAddClient(LXtObjectID self, int argument, LXtObjectID object)
LxResult NotifyRemoveClient(LXtObjectID self, LXtObjectID object)

ILxCommand2

class ILxCommand2

This interface was retired in modo 801, and was replaced with an updated one that adds new methods.

Public Functions

LxResult Tag(LXtObjectID self, LXtCommandTag *tag)
LxResult Name(LXtObjectID self, const char **name)
LxResult UserName(LXtObjectID self, const char **userName)
LxResult ButtonName(LXtObjectID self, const char **buttonName)
LxResult Desc(LXtObjectID self, const char **desc)
LxResult Tooltip(LXtObjectID self, const char **tooltip)
LxResult Help(LXtObjectID self, const char **help)
LxResult Example(LXtObjectID self, const char **example)
LxResult Icon(LXtObjectID self, const char **iconNames)
LxResult Flags(LXtObjectID self, unsigned int *flags)
LxResult PostExecFlags(LXtObjectID self, unsigned int *flags)
LxResult PostExecBehaviorFlags(LXtObjectID self, unsigned int *flags)
LxResult PostExecHints(LXtObjectID self, unsigned int *hints)
LxResult SandboxGUID(LXtObjectID self, const LXtGUID **guid)
LxResult Message(LXtObjectID self, void **ppvObj)
LxResult Enable(LXtObjectID self, LXtObjectID msg)
LxResult ContainedEnable(LXtObjectID self, LXtID4 *types)
void Interact(LXtObjectID self)
void PreExecute(LXtObjectID self)
void Execute(LXtObjectID self, unsigned int flags)
LxResult ToggleArg(LXtObjectID self, unsigned int *index, void **ppvObj, unsigned int *typeID, const char **typeName)
LxResult ArgFlags(LXtObjectID self, unsigned int index, unsigned int *flags)
LxResult ArgClear(LXtObjectID self, unsigned int index)
LxResult ArgResetAll(LXtObjectID self)
LxResult ArgSetDatatypes(LXtObjectID self)
LxResult ArgUserName(LXtObjectID self, unsigned int index, const char **userName)
LxResult ArgDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgExample(LXtObjectID self, unsigned int index, const char **example)
LxResult ArgType(LXtObjectID self, unsigned int index, const char **type)
LxResult ArgTypeUserName(LXtObjectID self, unsigned int index, const char **userName)
LxResult ArgTypeDesc(LXtObjectID self, unsigned int index, const char **desc)
LxResult ArgOptionUserName(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **userName)
LxResult ArgOptionDesc(LXtObjectID self, unsigned int index, unsigned int optIndex, const char **desc)
LxResult DialogInit(LXtObjectID self)
LxResult DialogArgChange(LXtObjectID self, unsigned int arg)
LxResult ArgEnable(LXtObjectID self, unsigned int arg)
LxResult ArgParseString(LXtObjectID self, unsigned int argIndex, const char *argString)
LxResult Copy(LXtObjectID self, LXtObjectID sourceCommand)
LxResult Query(LXtObjectID self, unsigned int index, LXtObjectID vaQuery)
LxResult NotifyAddClient(LXtObjectID self, int argument, LXtObjectID object)
LxResult NotifyRemoveClient(LXtObjectID self, LXtObjectID object)
LxResult DialogFormatting(LXtObjectID self, const char **formatting)

ILxCommandBlock

class ILxCommandBlock

The command block interface is used to provide some basic information about the current command block.

Public Functions

LxResult Name(LXtObjectID self, const char **name)

This returns the block’s name.

LxResult Flags(LXtObjectID self, unsigned int *flags)

This returns the flags it was created with.

LxResult SubExecs(LXtObjectID self, unsigned int *execs)

This number of commands executed within the block can be read with this function. This is mainly used by CHist to discard empty blocks.

LxResult PostExecFlags(LXtObjectID self, unsigned int *flags)

After commands in the block have been executed, the flags of the block itself may have changed. Normally, blocks are undoable, but firing non-undoable blocks can change that. Note that these flags are the same as the execution flags used by the commands, not the flags used to create a command block.

ILxCommandService

class ILxCommandService

The global service provides high-level access to the command system itself. This includes operations such as walking the list of available commands and instancing commands for querying and firing.

Public Functions

LxResult ScriptQuery(LXtObjectID self, void **ppvObj)

As with all globals, the first method gets the ILxScriptQueryID interface for the system.

LxResult MasterStatus(LXtObjectID self, unsigned int *status)
LxResult GetNameSep(LXtObjectID self, unsigned int *sep)
LxResult SetNameSep(LXtObjectID self, unsigned int sep)
LxResult Proto(LXtObjectID self, LXtCommandTag tag, const char *name, void **ppvObj)

This returns the ILxCommand interface of the prototype command, thus allowing basic non-editable data to be read out, such as the command’s name, tag and attributes. The object must be released when no longer needed. Note that it is legal to pass in a full command argument string with name, and only the part up to the first space will be treated as a name (the arguments are ignored).

LxResult ProtoFromCommand(LXtObjectID self, LXtObjectID cmd, void **ppvObj)

This returns the prototype of a command from an alreadly instanced one.

LxResult Lookup(LXtObjectID self, const char *name, LXtCommandTag *tag)

Should you want to, this returns a command’s tag, which can be used to create an instance of a command instead of using its name.

LxResult Spawn(LXtObjectID self, LXtCommandTag tag, const char *name, void **ppvObj)

This spawns a new command object given its name or tag, which means it creates a fully functional command object whose args can be set for firing and querying. The object needs to be released with XObjectRelease() when no longer needed.

LxResult SpawnFromCommand(LXtObjectID self, LXtObjectID cmd, void **ppvObj)

This spawns a new command object given another command object. Note that the spawned command will include any aliasing that was applied, even if the original command was create with SpawnUnaliased().

LxResult SpawnFromString(LXtObjectID self, const char *args, unsigned int *execFlags, int *queryArgIndex, void **ppvObj)

This super-wrapper spawns a command from an argument string and sets all the arguments found. It will also return the index of the query argument, if one was set in the argument string; the query argument will be -1 if no query argument is set. Also, execution flags passed in will be modified based on the leading characters of the command string (!, +, ?, etc). Note that the execFlags should be iniitalized to some useful execution flags, such as LXfCMD_EXEC_DEFAULT, as this will also be used to present parsing errors. Once the command has been spawned in this way, it is ready for execution or querying.

LxResult ExecuteArgString(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args)

This is a high-level function that parses arguments and fires the command all in one go. If the tag is CTAG_NULL, it is assumed that the command name begins the argument string. If the tag is CTAG_NULL, then there are some special characters that can be used to modify the execution state. These flags are insereted at the very beginning of the arugment string, before the command name. A single exclamation point “!” can be used to turn off the SHOWERR and GETARGS flags for this command only. An opposite effect can be achieved by using a single leading plus “+”. This adds SHOWERR and GETARGS to the command. Note that the above only affect this specific command. All sub-commands can be affected be using double exclamation points “!!” or double pluses “++” where appropriate. These will add SHOWERR_FORCESUB_OFF and GETARGS_FORCESUB_OFF or SHOWERR_FORCESUB and GETARGS_FORCESUB to the execFlags. This function also handles special UI-level behaviors. For example, if a required argument is missing, the command dialog will open. Similarly, if a query operator is specified for an argument, it will be applied. This includes using a question mark by itself on an argument that can be represented by a popup, thereby forcing it to open a menu at the current mouse position, or in the case of a boolean argument, causing it toggle it on or off.

LxResult ExecuteToggleArgString(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args, int newState)

Similar, but also allows a toggle arg to be flipped. -1 can be used to invert the current state.

LxResult IsToggleArgString(LXtObjectID self, const char *string)

This processes a command string (name and args) and returns LXe_TRUE if it is a toggle arg command, and LXe_FALSE if not. If true, this means the command can be executed with ExecuteToggleArgString() to toggle argument.

LxResult IsBooleanArgString(LXtObjectID self, const char *string)

Commands with queried boolean arguments can also be somewhat tedious to test, toggle and execute, especially considering the multiple ways that a boolean argument can be specified. This function takes a command string, and if the boolean argument contains any query operators (including a question mark alone), this returns true.

LxResult ExecuteBooleanArgString(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args)

This allows the boolean argument’s value to be easily changed to an alternate state. As above, the boolean argument is expected to be marked with a query operator, and the argument’s value will be toggled based on the argument’s currently queried value before being executed..

LxResult ExecuteSpecial(LXtObjectID self, unsigned int execFlags, LXtObjectID cmd, int specialArgIndex)

This executes a command object, but also takes a special argument index. If the index is not -1, then special behaviors specific to that argument may be taken (i.e., opening a popup), or the command may be executed normal or a command dialog may appear as normal. This same behavior is taken automatically when executing a command from a string using ExecuteArgString().

LxResult ExecuteAttribObject(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *cmdName, LXtObjectID attribArgs)

Finally, we support using an ILxAttributes interface to provide the arguments to the command. The Name(), Count(), Value(), GetString(), GetInt() and GetFloat() arguments are used, but the Type() argument is not used. It works like this: First the Count() and Name() methods are called to see which argument this is. Then one of Value(), GetInt(), GetFloat() or GetString() is called depending on the datatype of the argument (note that the Type() method is not usd). If the method fails, the GetString() method is used as an encoded string. If that fails, then the execution fails.

LxResult ProcessStringFlags(LXtObjectID self, unsigned int flags, const char *string, unsigned int *newFlags, const char **afterFlags)

This function can be used to parse the special prefix characters mentioned above out the string, and combine them with other execution flags. This is useful when you are directly creating an ILxCommand object from a user-entered string. The function takes the original execution and/or alert flags and the source string. It returns new flags and a pointer to the first character after the flags characters in the source string. Either newFlags or afterFlags may be NULL if desired.

LxResult ExecFlagsAsPrefixString(LXtObjectID self, unsigned int flags, char *buf, unsigned int len)

This inverse function takes the exec flags and converts them back into a prefix string.

LxResult SetToggleArgState(LXtObjectID self, LXtObjectID cmd, int state)

These functions makes it easy to flip the toggle of a Toggle Argument command, and to tell if the state is on or off. 1 is on, 0 is off, and -1 inverts the current state.

LxResult GetToggleArgState(LXtObjectID self, LXtObjectID cmd, int *state, void **ppvObj)

When getting the value, both a simple on/off state and the current value of the arg can be provided, or either can be NULL.

LxResult IsImplicitScript(LXtObjectID self, const char *definition)

Scripts can be more easily executed using this function. Before looking up any commands, this should be called to see if it starts with the script marker (the @ symbol). Note that the definition string should include entire command like, not just the @ and script name; if If it does, the next function will create the implicit script command and and set the script name and arg string arguments automatically. Scripts cannot be queried, so the command returned is only useful for execution. The command can otherwise be treated a a normal command object after it is created. See if the command is an implicit script execution.

LxResult SpawnImplicitScript(LXtObjectID self, const char *definition, void **ppvObj)

Spawn a command to launch the script. This “definition” string should include any arguments to pass to the script.

LxResult ExecuteImplicitScript(LXtObjectID self, const char *definition, unsigned int execFlags)

Execute an implicit script directly.

LxResult RefireBegin(LXtObjectID self)

Some commands are fired many times over and over again as the user changes a value. An example of this is the the Move Tool; each time the users drags the mouse, the Move Tool fires a new AddPosition (or whatever) command. This clutters up the command histroy quite a bit. Instead, the Move Tool should fire the AddPosition command effectively once with the final value, thus resulting in a single entry in the command history. This process has been dubbed “Refiring”. On mouse down, a tool calls CmdRefireBegin(), and on mouse up calls CmdRefireEnd(). In between it fires commands using CmdEntryFireArgs() or CmdEntryFireTag() to fire a command. When a command is refired, the previous execution is undone just before the command is re-executed. Each successive time CmdEntryFire…() is called within a refire block, the previously fired command is undone. IT IS REQUIRED THAT THE COMMAND BEING FIRED IS UNDOABLE! Large annoying requesters will pop up if you try to use any non-undoable commands. Only a single command can be executed inside a refire block, although that command may execute others. Attempting to execute more than one will cause those later commands to fail. If you need to fire multiple commands, you can wrap them in a command block via BlockBegin()/BlockEnd(), in which case the name of the block is used to identify it. RefireBegin() does not nest, and cannot be called while any commands are executing. It will return false if a previous RefireBegin() hasn’t been ended yet via RefireEnd() or if it is called while any command is being executed. Beginning refiring can take a tag, name or an ILxCommandID if you have one handy.

LxResult RefireEnd(LXtObjectID self)
LxResult RefireState(LXtObjectID self, unsigned int *state)
LxResult RefireCmd(LXtObjectID self, void **ppvObj)

These can be used to get the prototype of the command or the name of the block being refired. NOTE: this is returned without being add-refed! That needs to be fixed.

LxResult RefireBlock(LXtObjectID self, const char **name)
LxResult PostModeBegin(LXtObjectID self, LXtObjectID cmd, LXtCommandTag tag, const char *name, const char *args, LXtObjectID postEndObj)

The being and end functions. In begin, any of cmd, tag or args can be provided. If all are NULL, it is assumed that the command name prefixes the arguments.\ Otherwise, the argument list is optional.

LxResult PostModeEnd(LXtObjectID self)
LxResult PostModeState(LXtObjectID self)

This fetches the current post-mode state (i.e., on or off).

LxResult PostModeRestart(LXtObjectID self)

This resets all undoable states since the PostModeBegin() call. An example usage is ToolRefluxRestart() in tools.qq.

LxResult CurrentExecDepth(LXtObjectID self, int *depth)

This returns the current command execution depth. -1 means no commands are currently executing. This information is useful in rare situations. Note that this count includes both commands and command blocks.

LxResult BlockBegin(LXtObjectID self, const char *name, unsigned int flags)

It is sometimes desirable to have multiple commands executed as a single undoable event. This can be done by creating command blocks. Blocks can be nested as needed. Each block can be given a name that will be sent in the block create event and undo data and be displayed in the command history. Block names should be localized, and can take the form of “@table@message@”

LxResult BlockEnd(LXtObjectID self)

  • PRESERVE_SELECTION The PRESERVE_SELECTION flag will keep a copy of the entire selection list. This copy will be restored after the block is closed. This allows the command to change the selection in any way it wishes without damaging it later.

  • UI If present, the block can be triggered during refiring events without disrupting them. This should only be used with commands supporting LXfCMD_UI or with side effect commands.

  • UNDO_UI If present, the block is expected to contain undoable UI blocks.

  • UNDO_AFTER_EXEC If applied to an UNDO (default) or UNDO_UI block, the undo actions are undone on completion.

  • SANDBOXED Should be set if the block is in a sandbox.

  • POSTMODE Command block is being used as part of a post command execution.

  • STEPUNDO Taz, any idea what this is for?

  • TOP_OF_CYCLE_SAFE This is a special behavior used only in rare circumstances. Normally, a command block is not allwoed to remain open at the top of the input cycle. This flag allows that condition to be ignored. This is used by tree panes to allow the user to click and drag down a column to change a series of checkmarks without releasing the mouse, while having all of the commands contained within a single command block. Each block must be closed with this function. Bad things will happen if you miss one so don’t forget.

LxResult BlockCurrent(LXtObjectID self, void **block)

The current block can be obtained with this function, if one is on the execution stack. This mainly allows the flags and name of the block to be read. Note that this is a “peek”, and the object should not be released by the caller. NOTE: should be returned as the main return value.

LxResult SandboxFlags(LXtObjectID self, unsigned int *flags)
LxResult SandboxAddObject(LXtObjectID self, LXtObjectID object)

This method adds an object to a sandbox. The object is AddRef()’ed when added, and released when the sandbox is destroyed.

LxResult SandboxObjectCount(LXtObjectID self, unsigned int *count)

A list of objects can be read with these functions.

LxResult SandboxObjectByIndex(LXtObjectID self, unsigned int index, void **ppvObj)
LxResult SandboxObjectLookup(LXtObjectID self, const LXtGUID *guid, void **ppvObj)

An object can be looked up by the interfaces it supports. The first object with the GUID will be returned, or the method fails. Since this method caches interface queries, it is recommended instead of walking the object list directly.

LxResult SandboxObjectByCommand(LXtObjectID self, LXtObjectID cmd, void **ppvObj)

More commonly, this method would be used to get the object associated with the command’s SandboxGUID() method.

LxResult SandboxBegin(LXtObjectID self, unsigned int flags)

Command sandboxes can be started through this method. Flags are any combination of LXfCMDSANDBOX_ flags, and cannot be changed once the sandbox is created.

LxResult SandboxState(LXtObjectID self)

This method returns LXe_CMD_SANDBOX_GLOBAL if there are no sandboxes on the stack, and LXe_CMD_SANDBOXED if there is at least one. Any other return code is a failure.

LxResult SandboxEnd(LXtObjectID self)

When the sandbox is no longer needed, it must be popped off the stack with this method.

LxResult ParseArgString(LXtObjectID self, LXtObjectID cmd, int alertFlags, const char *args)

This is similar to CmdEntryFireTag(), and takes a string representing the arguments.

LxResult ParseAttribObject(LXtObjectID self, LXtObjectID cmd, unsigned int alertFlags, LXtObjectID attribArgs)

This function uses an ILxAttributesID to fill in the arguments. See ExecuteAttribObj() for more information about how this works.

LxResult Usage(LXtObjectID self, LXtObjectID cmd, const char **buffer)

This function composes and returns a string describing the arguments of the command in a user-readable format. This string is dynamically generated from the command’s own argument list, and includes the command name.

LxResult ArgsAsString(LXtObjectID self, LXtObjectID cmd, char *buf, unsigned int len, unsigned int includeCmd)

This function returns the argument list as a string which would result in the same arguments for the command if parsed. This is mainly used for recording the command in an executable history. If includeCmd is true, the internal command name will prefix the argument portion.

LxResult Query(LXtObjectID self, LXtObjectID cmd, unsigned int index, void **ppvObj)

This queries a command for its values, providing a new ILxValueArray that must be released by the client.

LxResult QueryArgString(LXtObjectID self, LXtObjectID cmd, unsigned int alertFlags, const char *args, void **ppvObj, unsigned int *queryIndex, unsigned int includesCmdName)

This is similar, but takes an argument string instead of an index. One argument may be marked with a ?, and that one will be queried. The index of that argument can be obtained through the queryIndex argument, or NULL can be passed NULL if you don’t want it back. Similarly, the ILxValueArrayID argument can be NULL if only the queryIndex itself is desired but not the actual queried values. If includesCmdName is true, the first part of the argument string is assumed to be the command name and will be skipped. The alertFlags (LXfCMD_ALERT_ defines) are used to decide how to present errors to the user during parsing; passing 0 will suppress any error dialogs. If successful parsed, the command object provided will be populated with the arguments present in the args string.

LxResult CreateQueryObject(LXtObjectID self, const char *typeName, void **ppvObj)

This creates a new ILxValueArray interface given an ExoType name.

LxResult AliasCreate(LXtObjectID self, const char *name, LXtObjectID targetCmd, LXtCommandTag targetTag, const char *targetName, const char *args)

Commands can be aliased. This allows one command to replace another, and to create shortcut commands that have arguments preset. Aliases themselves cannot be aliased. When creating or deleting aliases, any one of cmd, tag or name may be set. The argument string used during creation will be used to provide default values for the command. The arguments set in the cmd (if provided) are ignored. Note that using aliased arguments is only completely supported for commands that do not use dynamic datatypes. The issue is that if the user changes the the REQFORVARIABLE argument, the other arguments will need to be reset, thus overriding the aliased defaults. This shouldn’t pose any issues in most situations.

LxResult AliasDelete(LXtObjectID self, LXtObjectID alias, LXtCommandTag tag, const char *name)
LxResult IsContainer(LXtObjectID self, LXtObjectID cmd)

There are currently three types of commands: normal commands, containers and aliases. This functions can be used to tell if the command is a container.

LxResult IsAliased(LXtObjectID self, LXtObjectID cmd)

This succeeds if the command is aliased. Note that a command can be both a container and aliased.

LxResult CommandCount(LXtObjectID self, unsigned int *count)

The command list can be walked with these functions, returning the prototype. Commands are sorted by internal name. Note that commands will be loaded from plug-ins if necessary as the list is walked.

LxResult CommandByIndex(LXtObjectID self, unsigned int index, void **ppvObj)
LxResult ExecEntryType(LXtObjectID self, int index, int *type)
LxResult ExecEntryUserName(LXtObjectID self, int index, const char **userName)

The username can be obtained for both commands and blocks.

LxResult ExecEntryName(LXtObjectID self, int index, const char **name)
LxResult ExecEntryAsArgString(LXtObjectID self, int index, char *buf, int len)

For commands, an argument string suitable for executing it can be read with this function.

LxResult IsGlobalInteractionOK(LXtObjectID self)

This returns LXe_TRUE if a command is executing and the interaction flags are set. This means that if this returns LXe_FALSE, the client should not open any dialogs and instead should perform its default behavior. The interaction flags are often unset when running from a script or when in headless mode, during which time modo’s own dialogs (such as ILxMessage-based dialogs) will be automatically suppressed, acting as though the user had hit cancel/abort/no. By testing IsGlobalInteractionOK(), clients can skip the message and perform a reasonable default action instead of failing. This method is only intended to be used by non-command clients. Commands themselves should check their exec flags (as passed to the Execute() methods) via LXxCMD_IS_USER_INTERACTION_OK() instead.

LxResult ArgsAsStringLen(LXtObjectID self, LXtObjectID cmd, char *buf, unsigned int len, unsigned int includeCmd)

This is identical to ArgsAsString, but is a safer function that takes a buffer length to reduce the chance of a buffer overflow. ArgAsString() was updated a long time ago to include a len argument, making it identical to this function. Before nexus 12, there was a bug in ArgAsString() that kept it from working properly, but as of 12 both are identical.

LxResult SpawnUnaliased(LXtObjectID self, LXtCommandTag tag, const char *name, void **ppvObj)

Commands can be aliased such that they replace an existing command. This is useful when you want an alias to be able to completely replace built-in functionality. This method can be used to spawn an instance of the original, unaliased command, thus allowing the alias to call the original command’s methods.

LxResult SetIsGlobalInteractionOK(LXtObjectID self, int isOK)

It is sometimes useful to be able to lock out interaction on a global level. A common case is Slave mode, where we don’t want any dialogs opening as these machines are usually unattended. This state can only be set from within a command, and is automatically cleared when the stack is emptied. It cannot be manually cleared if it was not set by the client.

LxResult ExecuteArgString2(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args, void **ppvObj)

These functions are identical to their non-‘2’ counterparts, but will indirectly return a COM object representing the command object. This allows you to read post-execution flags and messages from the executed command, without having to manually spawn the command, set the argumetns, and do everything else you have to do to set up and execute a command manually. It’s important to note that this object may be NULL if the command could not be spawned. If the object returned is non-NULL, it must be released by the caller when no longer needed.

LxResult ExecuteToggleArgString2(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args, int newState, void **ppvObj)
LxResult ExecuteBooleanArgString2(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *args, void **ppvObj)
LxResult ExecuteAttribObject2(LXtObjectID self, unsigned int execFlags, LXtCommandTag tag, const char *cmdName, LXtObjectID attribArgs, void **ppvObj)
LxResult ExecuteImplicitScript2(LXtObjectID self, const char *definition, unsigned int execFlags, void **ppvObj)
LxResult AllocateUIHintsFromCommand(LXtObjectID self, LXtObjectID cmd, int argIndex, void **ppvObj)

This allocates an ILxUIHints object, has the provided command populate it, and returns it. The obejct can be cast to an ILxUIHintsRead interface to read the values of the hints. Since a new object is allocated, the returned hints object can also be modified by the caller and returned by their own commands if so desired. The argument index can be a specific arguments for hints for that argument, or LXiATTRUI_ANY for command-level hints, as is common for the form filter priority.

LxResult DoAtEndOfRootLevelUndoableCommand(LXtObjectID self, LXtObjectID visitor)

Sometimes a large undoable operation occurs that causes a lot of events to come in, and you want to do one undoable operation once everything else is done. You could use ScriptService::DoWhenUserIsIdle(), which is general useful for deferred and lazy operations, but if you want to perform an undoable operation you’ll have have to fire a command, and that means the user will have to do an extra undo to go back, which isn’t ideal and makes the undos feel broken. This method can only be called while an undoable command is being fired, and will fail otherwise. It registers a visitor that will be called after the root-level undoable command or block is about to return, but the undo block is still open. Calling this method twice with the same object pointer does nothing; the object is only registered once. The cancel method can be used to remove the registration, but the object passed in must be exactly the same as the one passed for registration, as this does a pointer compare. When doing this from Python, this means that you must pass the exact same visitor COM object (not Python object). This is also necessary when removing listeners and canceling timers, as discussed here: http://modo.sdk.thefoundry.co.uk/wiki/FAQ#Q:_How_do_I_remove_a_listener_object_in_Python.3F Note that unlike user idle, these functions are not thread-safe. This is because they are usually called in response to listeners from an actively-firing command, both of which happen from the main thread. If the command is aborted or fails, these actions are not executed, since the effects of the operation were all undo and it’s as though the operation never happened. This also does nothing if the root command’s eventual state wasn’t either model or model-undoable (UI undos are not supported).

LxResult CancelDoAtEndOfRootLevelUndoableCommand(LXtObjectID self, LXtObjectID visitor)
bool GetProto(LXtCommandTag tag, const char *name, CLxLoc_Command &cmd)

User Class Only:

bool GetProtoFromCommand(LXtCommandTag tag, const char *name, CLxLoc_Command &cmd)

User Class Only:

LXtCommandTag GetTag(const char *name)

User Class Only:

bool NewCommand(CLxLoc_Command &cmd, LXtCommandTag tag)

User Class Only:

bool NewCommand(CLxLoc_Command &cmd, const char *name)
bool NewCommandFromCommand(CLxLoc_Command &cmd, CLxLoc_Command &source)

User Class Only:

bool NewCommandFromString(CLxLoc_Command &cmd, const char *args, unsigned int &execFlags, int &queryArgIndex)

User Class Only:

bool CommandGetToggleArgState(CLxLoc_Command &cmd, int &state)

User Class Only:

bool CommandGetToggleArgState(CLxLoc_Command &cmd, CLxLoc_Value &value)
bool CommandGetToggleArgState(CLxLoc_Command &cmd, int &state, CLxLoc_Value &value)
bool NewCommandImplicitScript(const char *definition, CLxLoc_Command &cmd)

User Class Only:

bool QueryIndex(CLxLoc_Command &cmd, unsigned int index, CLxLoc_ValueArray &vaQuery)

User Class Only:

LxResult CommandQueryArgString(CLxLoc_Command &cmd, unsigned int alertFlags, const char *args, CLxLoc_ValueArray &vaQuery, unsigned int &queryIndex, bool includesCmdName = false)

User Class Only:

bool NewQueryObject(CLxLoc_ValueArray &valueArray, const char *typeName)

User Class Only:


LXiCMDSTATUS_INITIALIZING

This method allows clients to check the current status of the command system.

  • INITIALIZING When initially started, the command system is effectively disabled while it initialized. This is when many internal commands are set up and added to containers and initial aliases are set up. Commands cannot be executed during initialization.

  • NORMAL The system is active and running as normal. Commands can now be executed.

  • EXECUTING_STARTUP_COMMANDS This is a temporary state set when startup commands are being executed. This is most commonly used by commands that cannot run at startup, thus allowing them to return a meaningful error from their enable method instead of doing something bad like crashing. Once startup commands have finished, the state resets to LXiCMDSTATUS_NORMAL.

  • LXiCMDSTATUS_NORMAL

  • LXiCMDSTATUS_EXECUTING_STARTUP_COMMANDS


LXiCMD_SEP_DOT

These set and get the command separator, which determines how command names returned by ILxCommand::Name() are returned. The set function returns false if the separator ID entered isn’t one of the following.

  • LXiCMD_SEP_BACKSLASH

  • LXiCMD_SEP_SLASH

  • LXiCMD_SEP_COLON


LXiCMDREFIRE_NONE

The current refiring state can be tested with this function, which will return if this the system is idle, if a command is being refired, or if a block is being refired. PENDING means that refiring has just begun, but no commands or blocks have yet been fired.

  • LXiCMDREFIRE_PENDING

  • LXiCMDREFIRE_COMMAND

  • LXiCMDREFIRE_BLOCK

ILxCommandPostEnd

class ILxCommandPostEnd

This is a mode to use “non-persistent refiring”. The post command mode is started by calling CmdPostModeBegin. In this mode, CmdPostModeEnd() must be called when “post command” mode is complete. Alternatively, the block can be implicitly closed throught he use of an endObj. The endObj is an ILxCommandPostEnd interface containing only one function, which is called when the block is implicitly closed.

Public Functions

LxResult End(LXtObjectID self)

LXsCMD_CONTAINER_NAME

Command containers allow multiple similar commands that operate on different contexts to be logically grouped together. A prime example is a Delete container, which can be mapped to a single key/button and be used to delete whatever the current selection is, as long as the container has a matching command for it. Containers are used just like normal commands, but are implicitly created by server tags attached to the command. Containers have no arguments and no significant user interface. This server tags specify which container a command belongs, what arguments. it should have set when executed from the container, and the selection types it acts on. A command can belong to multiple containers by space-delimiting the container names, although the same execution arguments and selection types will apply equally to both containers. The selection type is set of four- character strings that define types in the selection system. Multiple types can be provided by separating them with spaces.

  • LXsCMD_CONTAINER_ARGS

  • LXsCMD_CONTAINER_TYPES


LXfCMDBLOCK_PRESERVE_SELECTION

Flags can be any of the following. When used in a sandbox, the flags should be set to LXfCMDBLOCK_SANDBOX. If UI or UNDO_UI are not specified, the block is assumed to be UNOD (aka an undoable model command).

  • LXfCMDBLOCK_UI

  • LXfCMDBLOCK_UNDO_UI

  • LXfCMDBLOCK_SANDBOXED

  • LXfCMDBLOCK_UNDO_AFTER_EXEC

  • LXfCMDBLOCK_POSTMODE

  • LXfCMDBLOCK_STEPUNDO

  • LXfCMDBLOCK_TOP_OF_CYCLE_SAFE


LXfCMDSANDBOX_ALLOW_UI

Some commands can only be executed in certain contexts. These contexts are known as “sandboxes”. There is a special global sandbox through with general, high-level commands are executed, such as loading and saving, toggling tools, etc. Other commands can be executed only within supported sandboxes. The way this works is simple enough: A sandbox is created and filled with objects that the commands operate on. Once the sandbox is activated, only commands that can operate on the objects within the sandbox can be executed. These are commands with the LXfCMD_SANDBOXED flag set and a sandbox GUID that matches one of the objects in the sandbox (see UI command exceptions below). Attempting to execute any other command will fail with LXe_CMD_SANDBOX_NOT_COMPATIBLE. Although only commands compatible with the sandbox can be executed, global commands can be queried. A flag can also be set to allow global UI and Side Effect commands to be executed from within a sandbox.

The following flags are supported by the sandboxes.

  • ALLOW_UI If set, UI and Side Effect commands can be executed from within the sandbox.


LXiCMDENTRYTYPE_INVALID

Together with CurrentExecDepth(), these methods allow indirect access to the commands that are currently being executed. The username, internal name and argument string representing the commands on the stack can be obtained with these functions, as well as the name of a command block, and if the entry is a block or command. Index must be between 0 and the value returned by CurrentExecDepth() inclusive. The type of the entry on the stack will be either a command or a command block.

  • LXiCMDENTRYTYPE_COMMAND

  • LXiCMDENTRYTYPE_BLOCK

ILxCmdSysListener

class ILxCmdSysListener

The command system listener can be used to listen for various events.

Public Functions

void SystemReady(LXtObjectID self)

This is called once the system has entered master enable, meaning that everything has been started and commands can be executed when safe.

void UndoLockout(LXtObjectID self, int isLockedOut)

This indicates that the undo lockout state has changed. When locked out, no MODEL or MODEL|UNDO commands can be executed, and an error will be reported if attempted.

void CommandAdded(LXtObjectID self, const char *name)

This is called when a new command has been added to the system.

void AliasAdded(LXtObjectID self, const char *name, int isOverride)

These are called when an alias is added or removed. If isOverride is set, the alias replaces an existing alias. Note that isOverride is not set if it a command with that name already exists (unless it is already aliased); in that case, the command is replaced with the alias.

void AliasRemoved(LXtObjectID self, const char *name, int isOverride)

Similarly, the isOverride flag is set if the alias is being removed because a new alias is replacing it.

void ExecutePre(LXtObjectID self, LXtObjectID cmd, int type, int isSandboxed, int isPostCmd)
void ExecuteResult(LXtObjectID self, LXtObjectID cmd, int type, int isSandboxed, int isPostCmd, int wasSuccessful)
void ExecutePost(LXtObjectID self, LXtObjectID cmd, int isSandboxed, int isPostCmd)
void BlockBegin(LXtObjectID self, LXtObjectID block, int isSandboxed)

This indicates that a command block was opened. The event data is an ILxCommandBlockID representing the block.

void BlockEnd(LXtObjectID self, LXtObjectID block, int isSandboxed, int wasDiscarded)

This is called when a command block is closed. If wasDiscarded is true, the block didn’t contain any commands and is a no-op,, and does not appear in the history.

void BlockEndedPostMode(LXtObjectID self, const char *name, int isSandboxed)

This is sent if the last closed block ended post mode.

void RefireBegin(LXtObjectID self)

These let the client know when refiring has started or stopped. RefireNext() indicates that the next command executed matches the refiring criteria and will trigger refiring, undoing the previously-executed command.

void RefireEnd(LXtObjectID self)
void RefiringNext(LXtObjectID self)
void PostModeBegin(LXtObjectID self)

These indicate when the post mode state has changed.

void PostModeEnd(LXtObjectID self)
void PostModeRestart(LXtObjectID self)
void PostModeUndoNext(LXtObjectID self)
void UserUndo(LXtObjectID self)

These indicate that the user performed an undo or redo.

void UserRedo(LXtObjectID self)

LXiCMDSYSEVENT_TYPE_QUIET

These are called for the different stages of command execution. The ExecutePre() event is called before the command is actually executed, and ExecuteResult() is called with a true/false indicating if the execution was successful. ExecutePost() is called just before a command is cleaned up and removed from the execution stack. In all cases the ILxCommandID should be considered read-only, and messing with it will probably do bad things to the system. The isSandboxed flag is set if the command is executed in a sandbox, but since sandboxes are currently used this will always be 0. The type flag (included for all but ExecutePost()) indicates the how the command was executed relative to other commands. QUIET means the command does not show up in the command history. ROOT means this was a root-level command from the point of view of the history, and will be set all root-level commands and children of QUIET commands. SUB means that this command was executed as a child of another non-QUIET command.

ExecutePre(), ExecuteResult() and ExecutePost() are all always called for any given command execution, and always in this order. However, more Pre()/Result()/Post() calls may occur between other Pre() and Result() calls as sub-commands are executed.

  • LXiCMDSYSEVENT_TYPE_ROOT