How to get TagData from PluginTag

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 06/09/2004 at 11:15, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   8.503 
Platform:   Windows  ;   
Language(s) :     C++  ;

---------
Sorry for all the questions about plugin tags, but I'm very confused about this at the moment (and Tlookatcamera doesn't answer 1% of my questions).

How does one get at the TagData store in a PluginTag after allocating one?

I have two classes (basically shown here) :

class AVMTag : public PluginTag
{
GetTagData();
SetTagData();
};

class AVMTagData : public TagData
{
//member variables needing to be set and get (see above)
// They are here so that Read(), Write(), CopyTo() can be
// implemented for saving/loading this data
};

Examples of how this all works would be highly appreciated since there are exactly none. I can't find a single instance here, online, in the sdk source, in the Resource source. Very frustrating working blind, deaf, dumb, and with burnt fingertips.

Thanks,
Robert

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/09/2004 at 13:36, xxxxxxxx wrote:

Hi Robert,
If you use the BaseContainer (and related SDk functions) to store your variables, you don't have to worry about Read()/Write() at all... your tags and thier data will be stored and re-read by C4D in the .c4d file.
Here's my simple GroupTag...

    
    
    
    
    #define GROUP_COUNT 1000  
    #define GROUP_NAME 1001  
    
    
    
    
    
    class GroupTag : public TagData  
    {  
     public:  
      virtual Bool Init(GeListNode *node);
    
    
    
    
      virtual Bool Message(GeListNode* node, LONG type, void* data);
    
    
    
    
      static NodeData *Alloc(void) { return gNew GroupTag; }  
    };
    
    
    
    
    Bool GroupTag::Init(GeListNode *node)  
    {  
     BaseTag    *tag  = (BaseTag* )node;  
     BaseContainer *data = tag->GetDataInstance();
    
    
    
    
     data->SetBool(GROUP_COUNT,0);
    
    
    
    
     return TRUE;  
    }
    
    
    
    
      
    Bool GroupTag::Message(GeListNode* node, LONG type, void* data)  
    {  
       
     if( type == MSG_EDIT )  
     {  
      if( node )  
      {  
       BaseTag   *tag  = (BaseTag* )node;  
       BaseContainer *tagdata = tag->GetDataInstance();  
       if( tagdata )  
       {  
        GroupTagDialog dlg(tagdata);
    
    
    
    
        if (!dlg.Open()) return FALSE;  
        return TRUE;  
       }  
      }  
     }  
       
     return false;  
    }  
    
    
    
    

...in this case "GROUP_COUNT" is a variable, telling me how many names are in the lst and "GROUP_NAME" is the variable of the 'first' name in the list (in this case, those are the only two variables, and it's a variable length list of names, so the rest of the names can be found at "GROUP_NAME+i").  Of course you can store any data you want in the BaseContainer (there may be some size-limit though), using the various SetBool()/SetReal()/etc.
In the above code, the Edit function is handled by a dialog that gets passed the BaseContainer so it can fill it in.  Here's a snippet of soome other (separate plugin) code that accesses this tag later on...

    
    
    
    
    void ObjSaver::BuildGroupList(BaseObject *op, CHAR *mName)  
    {  
    ...snip...  
     PluginTag *ptag = NULL;  
    ...snip...
    
    
    
    
     while( ptag = (PluginTag* )(op->GetTag(Tplugin, ptagi++)) )  
     {  
    #ifdef _V7SDK_  
      if( ptag->GetPluginID() == GTAG_PLUGID )  
    #else  
      if( ptag->GetType() == GTAG_PLUGID )  
    #endif  
      {  
       groups = ptag->GetData(); // get BaseContainer  
       gCnt = groups.GetLong(GROUP_COUNT);  
       break;  
      }  
     }
    
    
    
    
     if( gCnt )  
     {  
      //-------- try to find the associated selection tags...  
      while( stag = (SelectionTag* )(op->GetTag(Tpolygonselection, stagi++)) )  
      {  
    #ifdef _V7SDK_  
       String selName = stag->GetData().GetString(POLYSELECTIONTAG_NAME);  
    #else  
       String selName = stag->GetName();  
    #endif  
       for(ig=0; ig<gCnt; ig++)  
       {  
        String gName = groups.GetString(GROUP_NAME+ig);
    
    
    
    
        if( selName == gName )  
        {  
    ...yadda...yadda...
    
    
    

Does that help any?
- Keith

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/09/2004 at 13:42, xxxxxxxx wrote:

..I guess I should clarify that my 'GroupTag' is basically a list of SelectionTag names (which is why the code above walks the SelectionTag list).

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/09/2004 at 16:44, xxxxxxxx wrote:

I've been working through similar issues. The problem with the base container is that you can't store something like an array. For my plug-in I would like to store 1 to N vertex arrays of varrying length. I'm still trying to figure out a way to do it so that C4D will handle serialization...but I haven't come up with much yet.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/09/2004 at 17:38, xxxxxxxx wrote:

I'm using BaseContainers for anything already existing (LONG, Vector, Matrix), but for the arrays, the only approach seems to be to store it as a 'member variable' in the TagData extension class for the PluginTag and implement Write(), Read(), and CopyTo() so that the information is stored, retrieved, and copied properly. Here's the meat of it:

  
// METHODS: AVMTagData  
// Constructor  
AVMTagData::AVMTagData()  
{  
     set = FALSE;  
     vCount = 0;  
     vSelection = NULL;  
     vweights = NULL;  
     weights1 = NULL;  
     baseSelect = NULL;  
     boneObj = NULL;  
}  
// Destructor  
AVMTagData::~AVMTagData()  
{  
     if (baseSelect) BaseSelect::Free(baseSelect);  
     if (weights1) GeFree(weights1);  
     if (vSelection) GeFree(vSelection);  
}  
// Called when a new instance of the node plugin has been allocated.  
// You can use this function to, for example, fill the BaseContainer of the connected node with default values.  
// You can also allocate and initialize member variables of your node data class here.  
Bool AVMTagData::Init(GeListNode *node)  
{  
     if (!(baseSelect = BaseSelect::Alloc())) throw ErrorException(ERROR_MEMORY, "AVMTagData.Init.baseSelect");  
     GeData d;  
     if (node->GetParameter(DescLevel(EXPRESSION_PRIORITY),d,0))  
     {  
          PriorityData *pd = (PriorityData* )d.GetCustomDataType(CUSTOMGUI_PRIORITY_DATA);  
          if (pd) pd->SetPriorityValue(PRIORITYVALUE_PRIORITY,GeData(-499));  
          node->SetParameter(DescLevel(EXPRESSION_PRIORITY),d,0);  
     }  
     return TRUE;  
}  
// Called at the point in the priority pipeline specified by AddToExecution(), or the lack thereof.  
LONG AVMTagData::Execute(PluginTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, LONG flags)  
{  
     return EXECUTION_RESULT_OK;  
}  
// By default this function returns FALSE. Then C4D will call Execute()  
// at the priority specified by the user in the EXPRESSION_PRIORITY parameter of the container.  
Bool AVMTagData::AddToExecution(PluginTag* tag, PriorityList* list)  
{  
     return FALSE;  
}  
// Message  
Bool AVMTagData::Message(GeListNode* node, LONG type, void* data)  
{  
     if (type == MSG_CHANGE)  
     {  
          if (!data) return FALSE;  
          struct tData *ptData;  
          ptData = (struct tData* )data;  
          vCount = ptData->vCount;  
          vweights = (Real* )ptData->vMap->GetDataAddress();  
          vSelection = ptData->vSelection;  
          weights1 = ptData->weights1;  
          weights2 = weights1+vCount;  
          weights3 = weights2+vCount;  
          boneObj = ptData->boneObj;  
          bDelta = boneObj->GetRot();  
          // Quick access to valid vertices  
          baseSelect->FromArray(vSelection, vCount);  
  
          BaseContainer *bc = ((BaseTag* )node)->GetDataInstance();  
          // Persistent Link to Vertex Count  
          bc->SetLong(AVMTAG_VCOUNT_LONG, vCount);  
          // Persistent Link to VertexMap Tag  
          bc->SetLink(AVMTAG_TVERTEXMAP_LINK, ptData->vMap);  
          // Persistent Link to Obone BaseObject  
          bc->SetLink(AVMTAG_OBONE_LINK, boneObj);  
          set = TRUE;  
  
          // Initial Body Part / Parent weighting  
          seg = 0;  
          while (baseSelect->GetRange(seg++,&a;,&b;))  
          {  
               for (i=a; i<=b; ++i)  
               {  
                    *(vweights+i) = 1.0;  
               }  
          }  
     }  
     return TRUE;  
}  
// Read data from HyperFile  
Bool AVMTagData::Read(GeListNode* node, HyperFile* hf, LONG level)  
{  
     if (level >= 0)  
     {  
          LONG size;  
  
          BaseContainer *data = ((BaseTag* )node)->GetDataInstance();  
          vCount = data->GetLong(AVMTAG_VCOUNT_LONG);  
          if (!(vSelection = (UCHAR* )GeAlloc(sizeof(UCHAR)*vCount))) throw ErrorException(ERROR_MEMORY, "AVMTagData.Read.vSelection");  
          if (!(weights1 = (Real* )GeAlloc(sizeof(Real)*vCount*3))) throw ErrorException(ERROR_MEMORY, "AVMTagData.Read.weights1");  
          hf->ReadMemory((void** )&vSelection;, &size;);  
          hf->ReadMemory((void** )&weights1;, &size;);  
          weights2 = weights1+vCount;  
          weights3 = weights2+vCount;  
          baseSelect->FromArray(vSelection, vCount);  
     }  
     return TRUE;  
}  
// Write data to HyperFile  
Bool AVMTagData::Write(GeListNode* node, HyperFile* hf)  
{  
     // Level 0  
     hf->WriteMemory(vSelection, sizeof(UCHAR)*vCount);  
     hf->WriteMemory(weights1, sizeof(Real)*vCount*3);  
     // Level 1  
     return TRUE;  
}  
// Copy data to copied PluginTag  
Bool AVMTagData::CopyTo(NodeData* dest, GeListNode* snode, GeListNode* dnode, LONG flags, AliasTrans* trn)  
{  
     AVMTagData* adest = (AVMTagData* )dest;  
     adest->vCount = vCount;  
     if (!(adest->vSelection = (UCHAR* )GeAlloc(sizeof(UCHAR)*vCount))) throw ErrorException(ERROR_MEMORY, "AVMTagData.CopyTo.adest->vSelection");  
     if (!(adest->weights1 = (Real* )GeAlloc(sizeof(Real)*vCount*3))) throw ErrorException(ERROR_MEMORY, "AVMTagData.CopyTo.adest->weights1");  
     CopyMem(vSelection, adest->vSelection, sizeof(UCHAR)*vCount);  
     CopyMem(weights1, adest->weights1, sizeof(Real)*vCount*3);  
     adest->weights2 = adest->weights1+vCount;  
     adest->weights3 = adest->weights2+vCount;  
     adest->baseSelect->FromArray(vSelection, vCount);  
  
     return TRUE;  
}  
  
  
// Global Registrant Method for AVMTag plugin  
Bool RegisterAVMTag(void)  
{  
     return RegisterTagPlugin(ID_AVMTAG, "Axial VertexMap", TAG_EXPRESSION|TAG_MULTIPLE|TAG_VISIBLE, AVMTagData::Alloc, "Tavmtag", "avmtag.tif", 0);  
}  

Robert

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/09/2004 at 22:10, xxxxxxxx wrote:

This is very generous of you. Thanks so much!