The CommandData plugin class

The code for the plugin class, derived from the C4D class CommandData, is very simple. Here it is in full:

Bool MenuPlug::Execute(BaseDocument *doc)
{
    // this function is caled whenever the user clicks the name of the plugin in the Plugins menu
    // all we do here is open the dialog modally

    return dlg.Open(DLG_TYPE_MODAL, ID_DIALOGEX, -1, -1, 300, 150, 0); // the first parameter will open the dialog modally
}

Int32 MenuPlug::GetState(BaseDocument *doc)
{
    // return how the plugin name is to be displayed in the Plugins menu:
    // if there is an object currently selected we want to enable the command,
    // but we want it to be disabled if there is no active object

    if(doc->GetActiveObject() != nullptr)
        return CMD_ENABLED;
    else
        return 0;
}

The Execute() function is called when the user clicks the plugin name in the Plugins menu. All it does is call the Open() function of the dialog class instance. The first parameter determines the type of dialog, especially if it is modal or non-modal. If it is modal, then the user can only interact with the dialog; no other action in C4D is possible until the dialog is closed. We’ll make this dialog modal, because this plugin will only work on the currently-selected object in the object manager. If the dialog was non-modal, the user could select an object, open the dialog, change the current object, and then might expect any changes to be applied to the newly-selected object when the ‘OK’ button is hit. We could code for this, but in this demonstration it’s much easier if the user can’t change the selected object once the dialog is open.

The second function we have overridden is GetState(). We need to return a value which will tell C4D how to show the plugin name in the Plugins menu. In this case we want the plugin to be available only if there is at least one object selected in the object manager. If there is no selected object, we don’t want the user to be able to execute the plugin. So, we return the value CMD_ENABLED only if there is a selected object. If there isn’t, we return zero, which will cause the plugin name to be greyed out in the Plugins menu, and the user won’t be able to access the plugin.

That’s it for the plugin class; all the rest of the work is done within the dialog box class.

Plugin registration

The only other thing we need to look at is the registration of the plugin with C4D. As with every other type of plugin, C4D will call the function PluginStart(), which is in a separate file (main.cpp). I won’t show this here – it’s very simple and is similar to the other such files in previous tutorials. PluginStart() calls the function RegisterDialogExample(), which we supply. The code for this is as follows:

Bool RegisterDialogExample(void)
{
    // decide by name if the plugin shall be registered - just for user convenience
    String sName, sHelp;

    sName = GeLoadString(IDS_DIALOGEX); // load the plugin name from the global string table - this will appear in the Plugins menu
    sHelp = "Example CommandData plugin with a dialog box"; // this string appears in the status bar when the user hovers over the plugin name in the menu (could be loaded from the string table, of course)

    // register the plugin - note that we supplied the name of the icon to appear in the Plugins menu (C4D will substitute a white question mark if we don't provide one)
    return RegisterCommandPlugin(ID_DIALOGEX, sName, 0, AutoBitmap("dialogex.tif"), sHelp, NewObjClear(MenuPlug));
}

The function first loads a string for the plugin name (which appears in the Plugins menu) from the global string table. CommandData plugins also have another string, which will appear in the C4D status bar when the user hovers over the plugin name in the Plugins menu. This could also be loaded from the global string table (in fact, it should be!) but I’ve chosen to hard-code it here to show that either method will work.

Menu plugins also have an icon next to their name in the Plugins menu. This should be a 32x32 .TIF file with an alpha channel and the file should be placed in the .res folder within the plugin folder. Having done all that, we simply call the function RegisterCommandPlugin() with the parameters filled in. Note that the plugin ID is, as usual, the first parameter, and that the final parameter creates a new instance of the class we derived from the CommandData class.

On the next page we will look at the code for the dialog box class.

Page last updated June 23rd 2021