Skip to content

Undo Redo module

Stanislav Vasilev edited this page Jul 4, 2024 · 16 revisions

The undo/redo module provides support for undo/redo operations.

Enabling the module

To enable the plotting module, update your uvproj.yaml so that the undo_redo key under enabled-modules is set to true like this:

name: "MyProject"
version: "1.0.0.0"
engine-version: "1.0.0.0"
enabled-modules:
  undo_redo: true

Then, regenerate the modules cache by running the following command:

user $ ./UVKBuildTool --generate <project directory>

After that, refresh your CMake project with cmake ..!


Next, in your source file, include the Modules.hpp header in your components like this:

#include <Modules/Modules.hpp>

Event safety

The entire module is flagged as event safe at Post-begin.

Using the Undo/Redo module

The module stores data in the Transaction data type, as can be seen below:

struct UIMGUI_PUBLIC_API Transaction
{
    std::function<void(TransactionPayload&)> undofunc;
    std::function<void(TransactionPayload&)> redofunc;
    TransactionPayload payload;
};

The 2 functions are the events to be called on undo and redo, respectively.

The payload member is of type TransactionPayload which is a simple struct storing a void* for a buffer and its size like this:

struct UIMGUI_PUBLIC_API TransactionPayload
{
    void* payload;
    size_t size;
};

So to push a transaction create a transaction, initialise the events and the payload and push it as an argument to the push function like this:

Transaction transaction = 
{
    .undofunc = [](TransactionPayload&){ Logger::log("Undo", UVKLog::UVK_LOG_TYPE_NOTE); },
    .redofunc = [](TransactionPayload&){ Logger::log("Redo", UVKLog::UVK_LOG_TYPE_NOTE); },
    .payload = 
    { 
        .payload = nullptr,
        .size = 0,
    }
};

UImGui::StateTracker::push(transaction);

And now you have added an action that can be undone.

By default, push also accepts a bool bRedoIsInit default argument, which is set to false. When set to true it will execute the redo function after the transaction is added to the state tracker. This is made to allow emulating the command pattern more closely.


To undo or redo an action, simply call the undo or redo member functions of the StateTracker class like this:

UImGui::StateTracker::undo();
UImGui::StateTracker::redo();

and you should get the appropriate output logged to the console.

Checking for the module

To check for the module at compile time, use the UIMGUI_UNDO_MODULE_ENABLED macro.

Runtime checking can be done using the undo_redo member of the ModuleSettings struct. More info can be found here.

C API

The undo module contains a C API, which uses the standard C API development principles, as defined here. Here is how they differ:

  1. TransactionPayload is renamed to UImGui_TransactionPayload - same content
  2. push, undo and redo functions are prefixed with UImGui_StateTracker_
  3. push takes UImGui_CTransaction instead of Transaction
  4. UImGui_CTransaction instead of Transaction. It looks like this:
    typedef struct UIMGUI_PUBLIC_API UImGui_CTransaction
    {
        UImGui_CTransactionCallbackFun undoFunc;
        UImGui_CTransactionCallbackFun redoFunc;
        UImGui_TransactionPayload payload;
    } UImGui_CTransaction;

where UImGui_CTransactionCallbackFun is a C function pointer of type void(UImGui_TransactionPayload*).

Clone this wiki locally