Creating a CommandData plugin

Note: applicable to R19 and earlier versions. Some code may be applicable to later versions of C4D.

The plugin source code has been updated to build with VS 2015 and the C4D R19 SDK. It is possible to use earlier SDKs but you may need to alter some function and variable names/definitions.

In this tutorial we will build a CommandData plugin. These are usually thought of as ‘menu’ plugins, since they appear in the C4D Plugins menu and selecting them carries out some kind of command. Often, the command is to open a dialog box with various parameters the user can set before finally clicking a button to make something happen, and this is what we will do here.

The plugin won’t do anything of much use. It will just duplicate some of the functions of the object manager – it will let the user rename the object and set its editor and render visibility (the colored dots next to the object name). But it will demonstrate how to load a dialog resource and interact with the gadgets in the dialog.

Interface

The first thing then is to build the dialog box. To do this I used the ResEdit plugin which you can download from Plugin Cafe, but you also can build it by hand as you would a description. I won’t show the resource files here, but the dialog we want will look like this:

ResEdit will save three files – the .res file containing the description of the dialog, a .str file which holds the text strings for the various gadgets, and the file c4d_symbols.h, which holds the ID values of the gadgets. (Note the difference from a description resource where the ID values are held in a separate header file.) I have also edited c4d_symbols.h to give the ID value of a string in the global string table c4d_strings.str, which I created by hand, and which contains the name of the plugin that we want to appear in the Plugins menu in C4D.

The resource files are contained in the archive file which can be downloaded from the link at the end of the tutorial. This contains all the resources and source code used in the plugin.

Having built the resource, we can now create the header file for the plugin. Here it is in full:

// Dialog Example - dialogex.h

// plugin ID
#ifndef ID_DIALOGEX
#define ID_DIALOGEX 1000006 // non-unique ID value for test purposes only
#endif

// dialog class declaration
class DialogExample : public GeDialog // the dialog box will be derived from the C4D GeDialog base class
{
private:
    BaseObject *op; // pointer to the active object in the document

public:
    DialogExample(void); // constructor
    virtual ~DialogExample(void); // destructor
    // virtual C4D functions we should override
    virtual Bool CreateLayout(void); // called to create the dialog box
    virtual Bool InitValues(void); // called to initialise local variables
    virtual Bool Command(Int32 id, const BaseContainer& msg); // called to handle user interaction
    virtual Bool AskClose(void); // called when the dialog is closed
};

// command plugin class declaration
class MenuPlug : public CommandData // the actual plugin class is derived from C4D's CommandData class
{
private:
    DialogExample dlg; // an instance of the dialog class - the plugin could have multiple dialogs instantiated here

public:
    // virtual C4D functions we should override
    virtual Bool Execute(BaseDocument *doc); // called when the user invokes the plugin from the Plugins menu
    virtual Int32 GetState(BaseDocument *doc); // called by C4D to determine how to display the plugin name in the Plugins menu
};

As you can see, we have the usual plugin ID, which in this case is just one of the IDs reserved for testing purposes. If you compile this plugin, make sure that the ID doesn’t clash with any other test plugin you may have, or it may not load.

Then we have two class declarations. We need a declaration for the dialog box, which is derived from the C4D class GeDialog, and one for the actual plugin class itself, which is derived from the CommandData class.

In the dialog box class, there are several virtual functions we should override. We must override the CreateLayout() function, because that will be called by C4D whenever the dialog is to be displayed. If we don’t do this, nothing will appear on screen. We must also override the Command() function, because that will be called whenever the user interacts with the dialog box – including, for example, clicking the ‘OK’ button we must respond to if we want action to be taken.

It can also be useful to override InitValues(), which lets us set up any local variables the plugin might use, and AskClose(), which is called when the user tries to close the dialog. In some circumstances you might not want the user to be able to do that – for example, if the user hits the OK button but hasn’t supplied all necessary information to allow action to be taken.

The class derived from CommandData is simpler. It contains a private member variable which is an instance of the dialog box class, so that the plugin can open the dialog when required. It must also override at least one virtual function – Execute(), which is called by C4D whenever the user clicks the plugin name in the Plugins menu. In this case we also override GetState(), which is explained later.

On the next page we’ll look at the code for the class derived from CommandData, and how the plugin is registered with C4D.

Page last updated June 23rd 2021