Hi.
I am working on a tag plugin that will have a user drag & dropping another tag onto it, the dragged tag will then be set into a link field for use later. I successfully have the drag and drop working, my issue comes in when I try to implement undo functionality for the drag and drop.
With the code below (from the sdk) I have the tag only accepting tags of the same type as the plugin itself. After the drag and drop it takes two separate undos to successfully revert the link field to its previous state. I've tried the code below with the StartUndo/EndUndo and it always takes the two undos.
#include "c4d.h"
#include "c4d_symbols.h"
#include "lib_hair.h"
#include "main.h"
#include <customgui_descproperty.h>
#include "thairsdkrendering.h"
#define TESTPLUGIN_ID 9000
//////////////////////////////////////////////////////////////////////////
class HairRenderingTag : public TagData
{
INSTANCEOF(HairRenderingTag, TagData)
public:
virtual Bool Init(GeListNode* node);
virtual void Free(GeListNode* node);
virtual Bool Message(GeListNode* node, Int32 type, void* data);
virtual Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags);
static NodeData* Alloc() { return NewObjClear(HairRenderingTag); }
};
//////////////////////////////////////////////////////////////////////////
Bool HairRenderingTag::Init(GeListNode* node)
{
BaseContainer* bc = ((BaseList2D*)node)->GetDataInstance();
return true;
}
void HairRenderingTag::Free(GeListNode* node)
{
}
Bool HairRenderingTag::GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags)
{
if (!description->LoadDescription(node->GetType()))
{
}
const DescID* singleid = description->GetSingleDescID();
BaseContainer *dataInstance = ((BaseList2D*)node)->GetDataInstance(); // Get the container for the tag
DescID cid = DescLevel(1000, DTYPE_GROUP, 0);
if (!singleid || cid.IsPartOf(*singleid, nullptr)) // important to check for speedup c4d!
{
BaseContainer maingroup = GetCustomDataTypeDefault(DTYPE_GROUP);
maingroup.SetString(DESC_NAME, "Links"_s);
maingroup.SetInt32(DESC_DEFAULT, 1);
if (!description->SetParameter(cid, maingroup, DescLevel(TESTPLUGIN_ID)))
return true;
}
cid = DescLevel(1001, DTYPE_BASELISTLINK, 0);
if (!singleid || cid.IsPartOf(*singleid, NULL)) // important to check for speedup c4d!
{
BaseContainer bc;
bc = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);
BaseContainer acceptedObjects;
acceptedObjects.InsData(TESTPLUGIN_ID, String()); // matrix
bc.SetContainer(DESC_ACCEPT, acceptedObjects);
bc.SetBool(DESC_SCALEH, true);
bc.SetString(DESC_NAME, "Link Field"_s);
if (!description->SetParameter(cid, bc, 1000))
return TRUE;
}
flags |= DESCFLAGS_DESC::LOADED;
return SUPER::GetDDescription(node, description, flags);
}
Bool HairRenderingTag::Message(GeListNode* node, Int32 type, void* data)
{
BaseDocument* doc = node->GetDocument();
if (!doc)
return TRUE;
BaseContainer* dataInstance;
BaseTag* tag = static_cast<BaseTag*> (node);
if (tag == nullptr)
return TRUE;
dataInstance = tag->GetDataInstance();
if (!dataInstance)
return TRUE;
if (type == MSG_DRAGANDDROP)
{
DragAndDrop* dnd = static_cast<DragAndDrop*>(data);
if (!dnd)
return TRUE;
// Drag & drop will only accept tags of the plugin type
if (dnd->type == DRAGTYPE_ATOMARRAY)
{
AtomArray* dndid = static_cast<AtomArray*>(dnd->data);
AutoAlloc<AtomArray> dndidarr;
dndid->CopyTo(dndidarr);
if (dndidarr->GetCount() <= 0)
return TRUE;
if (dndidarr->GetIndex(0) != nullptr)
{
if (dndidarr->GetIndex(0)->GetType() != TESTPLUGIN_ID)
return TRUE;
}
else
{
return TRUE;
}
BaseObject* tagsobject = tag->GetObject();
BaseContainer state;
if (!GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, state))
return TRUE;
// Only run when the mouse is released
if (state.GetInt32(BFM_INPUT_VALUE) == 0)
{
BaseTag *attachedTag = (BaseTag*)dndidarr->GetIndex(0);
doc->AddUndo(UNDOTYPE::CHANGE, tag);
dataInstance->SetLink(1001, attachedTag);
return TRUE;
}
}
}
return SUPER::Message(node, type, data);
}
Bool RegisterRenderingTag()
{
return RegisterTagPlugin(TESTPLUGIN_ID, "Link Test"_s, TAG_MULTIPLE | TAG_VISIBLE, HairRenderingTag::Alloc, "Thairsdkrendering"_s, AutoBitmap("hairrendering.tif"_s), 0);
}
I'm not sure if I am doing something fundementally wrong with the undos since I have had undos of other types working in other plugins.
Any help would be greatly appreciated.
John Terenece