Start a new topic

Adding UNDO REDO Function

Original Post by: Wed Dec 10 09:00:39 2014


Hi,


After making the plugin i found that undo and redo functions are not defined. I went through the sample undotest plugin sample but I am not able to figure out how it works, sorry to say but even after. I'll paste the code but can someone suggest where and how to add undo and redo.


This is the sample code for which i want to add Undo Redo function, By default Plugin Wizard added few lines for Undo Redo function but I am not that much expertise in it.



#define _CRT_SECURE_NO_WARNINGS


#include <string.h>

#include <mgapiall.h>

#include "resource.h"


typedef struct undorec_t {

mgbool undoFunc;

int something;

} undorec;


typedef struct toolrec_t {

mgrec* db;

mgplugintool pluginTool;

mgresource resource;

undorec* undoRec;

mggui dialog;

mgeditorcontext editorContext;

} toolrec;


static void ToolNotifier (mgnotifier notifier, mgnotifierevent event,

mgrec* db, mgrec* rec, void* userData)

{

toolrec* toolRec = (toolrec*) userData;

switch (event)

{

case MNOTIFY_CURRENTPRIMARYCOLORCHANGED:

break;

case MNOTIFY_CURRENTMATERIALCHANGED:

break;

}

}


static void LoadToolPreferences (toolrec* toolRec)

{

}


static void SaveToolPreferences (toolrec* toolRec)

{

}


static void UndoCleanupFunc (mgrec* db, mgundocleanupreason cleanupReason, void* userData)

{

undorec* undoRec = (undorec*) userData;


switch (cleanupReason)

{

case MUCR_AFTERUNDO: /* UndoFunc was called before cleanup */

break;

case MUCR_NOUNDO: /* UndoFunc was NOT called before cleanup */

break;

}

mgFree (undoRec);

}


static void UndoFunc (mgrec* db, void* userData);


static void RedoFunc (mgrec* db, void* userData)

{

undorec* undoRec = (undorec*) userData;

mgEditorAddUndoForRedo (UndoFunc, UndoCleanupFunc, undoRec);

}


static void UndoFunc (mgrec* db, void* userData)

{

undorec* undoRec = (undorec*) userData;

mgEditorAddRedo (RedoFunc, UndoCleanupFunc, undoRec);

}


static void ButtonFunc (mgeditorcontext editorContext, int whichButton, void* toolData)

{

toolrec* toolRec = (toolrec*) toolData;

//mgrec* poly;

short texture = 1;

short material = 1;


switch (whichButton)

{

case MBT_CANCEL:

mgSendStatus (toolRec->pluginTool, "Closed");

break;

case MBT_DONE:

mgSendStatus (toolRec->pluginTool, "Done");

break;

}

}


//Define Effect Data 8

static mgbool eDataApply (mgrec* db, mgrec* parent, mgrec* rec, void* edata)

{

toolrec* toolRec = (toolrec*)edata;

short edata8;

if (mgGetCode(rec) == fltPolygon)

{

mgGetAttList(rec,fltLayerTexture1, &edata8;, MG_NULL);

if (edata8 >=0)

{

mgSetAttList(rec,fltLayerData1,8, MG_NULL);

mgSetModelingMode(db, fltPolygon);

}

}

return MG_TRUE;

}


//CALLBACK FUNTIONS----------------------------------------------------------


//Effect Data Apply callback

static mgstatus eDataCallback (mggui gui, mgcontrolid controlId,

mgguicallbackreason callbackReason,

void* userData, void* callData)

{

toolrec* toolRec = (toolrec*) userData;


switch (callbackReason)

{


case MGCB_ACTIVATE:

mgDeselectAll (toolRec->db);

mgWalk (toolRec->db, eDataApply, NULL, toolRec, 0);

mgSendStatus (toolRec->pluginTool, "Effect Data Applied");

break;

case MGCB_REFRESH:

break;

}

return (MSTAT_OK);

}


//Here Control Assignments Happens------------------------------------------------------------------------------

static void InitializeGuiCallbacks (toolrec* toolRec)

{

mggui gui = MG_NULL;


// assign the callback to the button


if (gui = mgFindGuiById (toolRec->dialog, BTN_SDATA))

mgSetGuiCallback (gui, MGCB_ACTIVATE|MGCB_REFRESH, eDataCallback, toolRec);

}


static mgstatus DialogProc (mggui dialog, mgdialogid dialogId,

mgguicallbackreason callbackReason,

void* userData, void* callData)

{

toolrec* toolRec = (toolrec*) userData;


switch (callbackReason)

{

case MGCB_INIT:

{

mgeditorcontext editorContext = mgEditorGetContext (dialog);

toolRec->dialog = dialog;

toolRec->editorContext = editorContext;

InitializeGuiCallbacks (toolRec);


// Select the mouse input handling routine to make active

mgEditorSelectMouseInput (editorContext, MMSI_NOINPUT);


// Register the notifiers of interest

mgRegisterNotifier (toolRec->pluginTool, MNOTIFY_CURRENTPRIMARYCOLORCHANGED,

toolRec->db, MG_NULL, ToolNotifier, toolRec);

mgRegisterNotifier (toolRec->pluginTool, MNOTIFY_CURRENTMATERIALCHANGED,

toolRec->db, MG_NULL, ToolNotifier, toolRec);

}

break;

case MGCB_SHOW:

break;

case MGCB_HIDE:

break;

case MGCB_DESTROY:

mgUnregisterAllNotifiers (toolRec->pluginTool);

mgFree (toolRec);

break;

}

return (MSTAT_OK);

}


static mggui CreateDialogFunc (mgplugintool pluginTool, void* toolData)

{

toolrec* toolRec = (toolrec*) toolData;

mggui dialog;

dialog = mgResourceGetDialog (MG_NULL, toolRec->resource, REMOTEV2DIALOG,

MGCB_INIT|MGCB_SHOW|MGCB_HIDE|MGCB_DESTROY,

DialogProc, toolRec);

return (dialog);

}


static mgstatus StartRemoteV2 (mgplugintool pluginTool, void* userData, void* callData)

{

mgeditorcallbackrec* cbData = (mgeditorcallbackrec*) callData;

mgresource resource = (mgresource) userData;

mgrec* db = mgGetActivationDb (cbData->toolActivation);

toolrec* toolRec;


toolRec = (toolrec*) mgMalloc (sizeof(toolrec));

toolRec->db = db;

toolRec->resource = resource;

toolRec->pluginTool = pluginTool;

toolRec->editorContext = cbData->editorContext;


cbData->dialogRequired = MG_TRUE;

cbData->toolData = toolRec;


return (MSTAT_OK);

}


mgbool InitRemoteV2 (mgplugin plugin, mgresource resource, int* argc, char* argv [])

{

mgplugintool pluginTool;

mgpixmap pixmap = mgResourceGetPixmap (resource, REMOTEV2_BMP);


pluginTool = mgRegisterEditor (

plugin, "Remote V2",

StartRemoteV2, resource,

MTA_VERSION, "2.0",

MTA_PALETTELOCATION, MPAL_FACETOOLS,

MTA_PALETTEICON, pixmap,

MTA_TOOLTIP, "Remote V2",

MG_NULL

);


if (pluginTool)

{

mgEditorSetButtonFunc (pluginTool, ButtonFunc);

mgEditorSetCreateDialogFunc (pluginTool, CreateDialogFunc);

}

return (pluginTool ? MG_TRUE : MG_FALSE);

}


void ExitRemoteV2 (mgplugin plugin)

{

}



1 Comment

Original Post by: SteveThompson Wed Dec 10 15:39:10 2014


Ok this is a huge topic. But the main things you need to do is:


1) In your tool "save" any data you need to undo the thing you did


2) In your UndoFunc, add code that accesses this "saved" data and does whatever is needed to undo the thing you did. And save any additional data you might need to "redo" what you just "undid".


3) Similarly in your RedoFunc, add code that accesses this "saved" redo-data and does whatever is needed to redo the thing you original did.


It is that simple but the code is something each different tool has to figure out... what to save, how to "undo" what the tool did and how to "redo" what was originally done after the user undoes.


This is explained in very much detail in Volume 2 of the User Guide. There each part of the undo/redo work flow is described.

Login to post a comment