On 27/08/2014 at 12:58, xxxxxxxx wrote:
User Information:
Cinema 4D Version: R15
Platform: Windows ; Mac OSX ;
Language(s) : C++ ;
---------
Hello forum,
I'm creating a plugin that keeps track of point selection order and re-draws the selected points with different colors according to each points selection order. All of this is working fine. I would like to add undo functionality to the selection process.
After reading many posts and asking for advice(thank you), I have went down the road of implementing a SceneHook to store the selection data so modifications to that data can be put on the Undo Stack. I have implemented FindPlugin() and a static_cast(UndoHookClass) to get a pointer to it. I have also implemented a pointer of type UndoHookClass as a member of MyToolClass. I can access all of the members of UndoHookClass through this pointer, but when I try to AddUndo() with the pointer, I get crashes. Below is a quick explanation of what I have tried in code:
// partial code for simplicity and quicker understanding
class UndoHook : public SceneHookData
{
public:
virtual Bool CopyTo( NodeData* dest, GeListNode* snode, GeListNode* dnode, COPYFLAGS flags, AliasTrans* trn )
{
GePrint( String::IntToString( _sel_pts.GetCount() ) );
for ( Int32 i = 0; i < _sel_pts.GetCount(); i++ )
{
static_cast<BPLup2UndoHook*>( dest )->_sel_pts.Append( _sel_pts[i] );
}
return NodeData::CopyTo( dest, snode, dnode, flags, trn );
}
void Append( Int32 v )
{
_sel_pts.Append( v );
}
void Erase( Int32 idx )
{
_sel_pts.Erase( idx );
}
// used for a test in MyTool
// this does not work
// void _AddUndo( BaseDocument* doc )
// {
// doc->AddUndo( UNDOTYPE_CHANGE_SMALL, this );
// }
virtual Bool MouseInput( BaseSceneHook* node, BaseDocument* doc, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg )
{
/*
// testing
// do not register MyTool in main.cpp and uncomment this out.
// works like a charm.
switch (msg.GetInt32(BFM_INPUT_QUALIFIER))
{
case QSHIFT:
doc->StartUndo();
doc->AddUndo(UNDOTYPE_CHANGE_SMALL, node);
Append(_sel_pts.GetCount());
doc->EndUndo();
return SceneHookData::MouseInput(node, doc, bd, win, msg);
break;
case QCTRL:
if (_sel_pts.GetCount() > 0)
{
doc->StartUndo();
doc->AddUndo(UNDOTYPE_CHANGE_SMALL, node);
Erase(_sel_pts.GetCount() - 1);
doc->EndUndo();
}
else
{
GeOutString("array is at begining", GEMB_OK);
}
return SceneHookData::MouseInput(node, doc, bd, win, msg);
break;
default:
PrintArray();
return SceneHookData::MouseInput(node, doc, bd, win, msg);
break;
}
*/
return SceneHookData::MouseInput( node, doc, bd, win, msg );
}
// tried making BlockArray public and private
maxon::BlockArray<Int32> _sel_pts;
};
class MyTool : public DescriptionToolData
{
public:
Bool InitUndoHook( BaseDocument* doc )
{
BasePlugin* base_plugin = FindPlugin( PID_UNDOHOOK, PLUGINTYPE_SCENEHOOK );
_undo_hook = static_cast<UndoHook*>( base_plugin->GetPluginStructure() );
return true;
}
void ModifyUndoHook( Int32 p, BaseDocument* doc )
{
// assume we have called InitUndoHook and all other members of UndoHook work fine when called inside MyTool class.
doc->AddUndo( UNDOTYPE_CHANGE_SMALL, _undo_hook ); // crash! Xcode: Thread 1: EXC_BAD_ACCESS(code=1, address-0x0)
// tried this:
doc->AddUndo( UNDOTYPE_CHANGE_SMALL, ( BaseSceneHook* )_undo_hook ); // crash! Xcode: Thread 1: EXC_BAD_ACCESS(code=1, address-0x0)
// tried this:
doc->AddUndo( UNDOTYPE_CHANGE_SMALL, static_cast<BaseSceneHook*>( _undo_hook ) ); // This and other casts will not compile.
// tried this:
// uncomment out _AddUndo in UndoHook
_undo_hook->_AddUndo( doc ); // crash! Xcode: Thread 1: EXC_BAD_ACCESS(code=1, address-0x0)
// tried this:
BaseSceneHook* base_scene_hook = doc->FindSceneHook( PID_UNDOHOOK );
doc->AddUndo( UNDOTYPE_CHANGE_SMALL, base_scene_hook ); // this does NOT crash.
// UndoHook::CopyTo() is called right after this, but when checking the array count in UndoHook::CopyTo() with GePrint(),
// a count of zero is always returned even when _undo_hook->_sel_pts->GetCount() is not zero.
_undo_hook->Append( p ); // this and other modifications to the BlockArray through member functions work fine.
}
private:
// tried making _undo_hook private and public
UndoHook* _undo_hook;
};
Any suggestions on how to add an undo with a SceneHookData class would be greatly appreciated.
Thank you,
Joe Buck