Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How to get TagData from PluginTag

    SDK Help
    0
    6
    423
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      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

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        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

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          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).

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            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.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              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

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                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!

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post