Undo Manager

Overview

The HUndoManager class manages a history of actions in order to enable undo/redo functionality. It comes with the ability to keep track of camera and matrix changes, and can be further enhancedto accept user defined undo actions.

Using the HUndoManager

HBaseView is initialized with an HUndoManager class already set up. In addition to this, MVO already keeps track of various camera and matrix changes (via the operators).

Traversing the History List

To undo or redo operations, first retrieve a pointer to the HUndoManager class:

HUndoManager *hmanager = m_pHView->GetUndoManager();

Once you have the HUndoManager class, you can call its Undo() and Redo() methods to get the desired result.

Enhancing the Undo Manager

The undo manager can also accept user defined undo items. In order to do so, the HUndoItem class must subclassed. The HUndoItemCamera subclass will be used as an example.

Subclassing HUndoItem

The constructor should contain all of the necessary information for undoing (and possibly redoing) an action. For HUndoItemCamera, the state of the (the “before” state,as in the state of the camera right before we change it) is stored. Example:

HUndoItemCamera::HUndoItemCamera(HBaseView *view)
{
m_pView = view;
view->GetCamera(&m_Camera);
}

The Undo() and function must perform everything needed to undo or redo. In the caseof HUndoItemCamera, undo will show the camera state before an undo, and transition the camerato the stored camera state. Afterwards, it will update the stored camera state to be the state ofthe camera BEFORE the undo, so that the Redo operation will work. Example:

void HUndoItemCamera::Undo(bool setuponly)
{
HCamera oldcamera;
m_pView->GetCamera(&oldcamera);

if(!setuponly)
{
        if (m_pView->GetSmoothTransition())
        {
                HC_Open_Segment_By_Key(m_pView->GetSceneKey());
                HUtility::SmoothTransition(oldcamera, m_Camera, m_pView);
                HC_Close_Segment();
        }
}

m_pView->SetCamera(m_Camera);
m_Camera = oldcamera;
}

The Redo() function is similar to the Undo() function, except it operates in reverse.

Note: Both the Undo() and Redo() functions accept a boolean “setuponly” argument. This argument is a flag to indicate whether or not we want to visually display the undo operation. In “setup only” mode, an undo/redo should do everything as usual EXCEPT for updating the screen. This “setuponly” flag is necessary for some of the other HUndoManager’s features to operate nicely,and allows you to traverse the history list “behind the scenes”, if need be. It is, however, mainly used for aesthetics, so not accounting for it should not break the undo manager.

It is also a good idea to override the GetName() function, so that you can identify what sort of UndoItem you are looking at:

virtual const char * GetName() { return "HUndoItemCamera"; };

Adding Items to the HUndoManager

Now that you have an HUndoItem all ready to go, you need to add it into the HUndoManager’s history list. If you are at the end of the history list, the item will be appended. If you had previously performed some undos, the item will be inserted at the location, and the rest of history will be discarded. Example:

hmanager->AddUndoItem(undoitem);