Command: Server basics

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

Commands are central to how the nexus system functions, and are potentially quite complex objects. Not only do they perform all the essential state changes, they also constitute the greater part of the nexus UI through their detailed behaviors and hints. As result it's not really possible to go into any great depth when discussing the basics of command servers, and it's hard to untangle the core of the implementation from the wrappers that are intended to hide its complexities. Let's start with the very basics.

Overview

Any button in a form corresponds to a command. The command provides an Enable() method which is used to compare the state of the system with the state required for the command to run, and those that can't are greyed out. When the user presses the button there may be a dialog created automatically from command arguments. Once arguments are filled in the command's Execute() is called to perform the action.

Headers

Samples

At the very least a command server derives from CLxImpl_Command, and exports an ILxCommand interface. Don't be daunted by the number of method on the command object; many of them are implemented for you. The object you get from spawning a command from the system is actually different from the one that you implement in your server plug-in. The command system wraps your core command and adds the extra support methods.

However, there is a minimal set of required methods.

Command::Flags()

Your command flags tell the system what your command expects to do, and in which context it's valid. For example a command that expects to make undoable changes is a MODEL and UNDO command.

        LxResult
cmd_Flags (
        unsigned int          *flags)            LXx_OVERRIDE
{
        flags[0] = LXfCMD_MODEL | LXfCMD_UNDO;
        return LXe_OK;
}
Command::Execute()

The Execute() method does the actual work of the command, so you have to have that. Note that it cannot return an error code. This is done instead using a Message Object and is beyond the scope of this simple example.

        void
cmd_Execute (
        unsigned int           flags)            LXx_OVERRIDE
{
        ...
}

Helper Classes

All commands in the sample code are created by deriving from the CLxBasicCommand class which -- as its name implies -- provides a framework for creating basic commands. Command derived this way export the ILxCommand, ILxAttributes and ILxAttributesUI interfaces (the latter two for arguments). The class also provides a template for defining an appropriate server.

class CMyCommand : public CLxBasicCommand
{
    public:
                static void
        initialize ()
        {
                CLxExport_BasicCommand<CMyCommand> ("myCommandName");
        }

        ...
};
BasicCommand::basic_CmdFlags()

Flags have the same meaning in the basic command, but with a simpler method.

        int
basic_CmdFlags ()            LXx_OVERRIDE
{
        return LXfCMD_MODEL | LXfCMD_UNDO;
}
Command::Execute()

The execute method is exactly the same and derives from the CLxImpl_Command class. The main difference is that the basic command class provides an accessor to the message for errors.

        void
cmd_Execute (
        unsigned int           flags)            LXx_OVERRIDE
{
        if (do_the_thing ())
                return;

        CLxUser_Message       &msg = basic_Message ();
        msg.SetCode (LXe_FAILED);
}
BasicCommand::constructor

One critical aspect of commands not yet described is arguments. The basic command class also inherits from CLxDynamicAttributes which provides the Attributes Interface that defines the command's arguments. The set of arguments and their order are defined in the constructor.

CMyCommand ()
{
        dyna_Add ("component", LXsTYPE_INTEGER);
        dyna_Add ("value",     LXsTYPE_FLOAT);
        dyna_Add ("type",      LXsTYPE_STRING);
}
BasicCommand::basic_Enable()

Commands can be disabled when the circumstances make them impossible to run. This method can just return false for a generic "command disabled" message, or it can use the message object for more detailed information.

        bool
basic_Enable (
        CLxUser_Message        &msg)            LXx_OVERRIDE
{
        ...
}

BasicCommand::basic_Notifiers()

If a command can be disabled, it can also change between enabled and disabled. In order for buttons to change the command must provide notifiers that will send the appropriate update codes for events that might change the enable state. For example this method adds a single notifier that signals a change in the disable state of the command based on any change in item selection. Standard notifiers are provided for common cases or custom notifiers can be created.

        void
basic_Notifiers ()            LXx_OVERRIDE
{
        basic_AddNotify (LXsNOTIFIER_SELECT, "item +d");
}