Overview

An example C++ extension that can be used as a reference/template for creating new extensions.

Demonstrates how to create commands in C++ that can then be executed from either C++ or Python.

See the omni.kit.commands extension for extensive documentation about commands themselves.

C++ Usage Examples

Defining Commands

using namespace omni::kit::commands;

class ExampleCppCommand : public Command
{
public:
    static carb::ObjectPtr<ICommand> create(const char* extensionId,
                                            const char* commandName,
                                            const carb::dictionary::Item* kwargs)
    {
        return carb::stealObject<ICommand>(new ExampleCppCommand(extensionId, commandName, kwargs));
    }

    static void populateKeywordArgs(carb::dictionary::Item* defaultKwargs,
                                    carb::dictionary::Item* optionalKwargs,
                                    carb::dictionary::Item* requiredKwargs)
    {
        if (carb::dictionary::IDictionary* iDictionary = carb::getCachedInterface<carb::dictionary::IDictionary>())
        {
            iDictionary->makeAtPath(defaultKwargs, "x", 9);
            iDictionary->makeAtPath(defaultKwargs, "y", -1);
        }
    }

    ExampleCppCommand(const char* extensionId, const char* commandName, const carb::dictionary::Item* kwargs)
        : Command(extensionId, commandName)
    {
        if (carb::dictionary::IDictionary* iDictionary = carb::getCachedInterface<carb::dictionary::IDictionary>())
        {
            m_x = iDictionary->get<int32_t>(kwargs, "x");
            m_y = iDictionary->get<int32_t>(kwargs, "y");
        }
    }

    void doCommand() override
    {
        printf("Executing command '%s' with params 'x=%d' and 'y=%d'.\n", getName(), m_x, m_y);
    }

    void undoCommand() override
    {
        printf("Undoing command '%s' with params 'x=%d' and 'y=%d'.\n", getName(), m_x, m_y);
    }

private:
    int32_t m_x = 0;
    int32_t m_y = 0;
};

Registering Commands

auto commandBridge = carb::getCachedInterface<omni::kit::commands::ICommandBridge>());
commandBridge->registerCommand(
    "omni.example.cpp.commands", "ExampleCppCommand", ExampleCppCommand::create, ExampleCppCommand::populateKeywordArgs);
// Note that the command name (in this case "ExampleCppCommand") is arbitrary and does not need to match the C++ class

Executing Commands

auto commandBridge = carb::getCachedInterface<omni::kit::commands::ICommandBridge>());

// Create the kwargs dictionary.
auto iDictionary = carb::getCachedInterface<carb::dictionary::IDictionary>();
carb::dictionary::Item* kwargs = iDictionary->createItem(nullptr, "", carb::dictionary::ItemType::eDictionary);
iDictionary->makeIntAtPath(kwargs, "x", 7);
iDictionary->makeIntAtPath(kwargs, "y", 9);

// Execute the command using its name...
commandBridge->executeCommand("ExampleCppCommand", kwargs);
// or without the 'Command' postfix just like Python commands...
commandBridge->executeCommand("ExampleCpp", kwargs);
// or fully qualified if needed to disambiguate (works with or without the 'Command)' postfix.
commandBridge->executeCommand("omni.example.cpp.commands", "ExampleCppCommand", kwargs);

// Destroy the kwargs dictionary.
iDictionary->destroyItem(kwargs);

// The C++ command can be executed from Python exactly like any Python command,
// and we can also execute Python commands from C++ in the same ways as above:
commandBridge->executeCommand("SomePythonCommand", kwargs);
// etc.

Undo/Redo/Repeat Commands

auto commandBridge = carb::getCachedInterface<omni::kit::commands::ICommandBridge>());

// It doesn't matter whether the command stack contains Python commands, C++ commands,
// or a mix of both, and the same stands for when undoing/redoing commands from Python.
commandBridge->undoCommand();
commandBridge->redoCommand();
commandBridge->repeatCommand();

Deregistering Commands

auto commandBridge = carb::getCachedInterface<omni::kit::commands::ICommandBridge>());
commandBridge->deregisterCommand("omni.example.cpp.commands", "ExampleCppCommand");