Why PluginTag? How to load XGroups?



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

    On 20/02/2006 at 09:48, xxxxxxxx wrote:

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

    ---------

    I want to write a Tag that, after being applied,
    adds an XPresso-Tag to the same object.

    Now I got a bunch of question:

    - Writing a TagData Plugin (like lookatcamera) works. Why do I need
      a class derived from PluginTag anyways? The concept is unclear to me.

    - Where can I get the BaseObject(s), to which the Tag
      is (are) connected? Execute(*tag, *doc, *op, ...) :
      op delivers NULL. I need it for adding the XPresso.

    - What's the best way to add an XPresso-Tag?
      Build it in the Init()-call of my TagData-class like:
      XPressoTag *xpTag = XPressoTag::Alloc();
      GvNodeMaster *nodeMaster = xpTag->GetNodeMaster();
      GvNode *node = nodeMaster->CreateNode(nodeMaster->GetRoot(),
      ID_OPERATOR_OBJECT, NULL, -1, -1);
      Or create a class derived from XPressoTag?
      I would like to hide that XPresso from the OM with PLUGINFLAG_HIDE
      so I can modify object positions with an invisible hand.

    - Is it possible to load an XGroup for my XPresso at once (instead of building
      the graph dynamically) when I create the Tag?

    And last: Is there another more complex example of a TagPlugin (TagData?)
    than lookatcamera? I found a topic "How to get TagData from PluginTag".
    I'm afraid I need even more to handle this.

    For any help, hints or links
    Thanks in advance,
    Sascha



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

    On 20/02/2006 at 11:23, xxxxxxxx wrote:

    - Actually, you are deriving a class from TagData and the PluginTag is automatically created for the data node. Think of how C++ uses class inheritance. You are inheriting all of the members and methods of TagData and PluginTag (which inherit from NodeData and BaseTag and so forth). This is how you utilize existing functionality without having to recode it from scratch yourself. The sad thing is that you cannot derive classes from existing built-in types, like VariableTag or TextureTag for instance.

    - BaseTag->GetObject(). No need to cast to BaseTag as base class casting is automatic. (class PluginTag : BaseTag)

    I'll leave the XPresso explanations for the gurus in that area. I have not used them yet.

    - There is so much that can be done with tags (and anything else with NodeData) it will depend on what your intentions are. For instance, I have a tag that collects certain tags in a hierarchy and displays their BaseContainer values as sliders using dynamic descriptions. But that is just one situation. There are also situations where you want an Expression tag and others where it is unnecessary.

    Figure out what you need and what the tag is to accomplish and ask questions.



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

    On 21/02/2006 at 05:55, xxxxxxxx wrote:

    Thank you very much for your help. I tried to get the Object and print it's name. But again I missed something. Is one of both Init()'s the right way? I created a cube called "Cube" and want to see that string in the console.

    Bool MyTag::Init(GeListNode *node)
    {
    BaseTag     *tag = (BaseTag* ) node;
    BaseObject *obj = tag->GetObject();
    GePrint("obj: "+obj->GetName());
    }
    -> gets an empty string (but obj is not null)

    Bool MyTag::Init(GeListNode *node)
    {
    BaseObject *obj = (BaseObject* ) node;
    GePrint("obj: -"+obj->GetName()+"-");
    }
    -> prints the name of the tag, not the object

    class MyTag : public TagData
    {
    public:
         virtual Bool Init(GeListNode *node);
         virtual LONG Execute(PluginTag *tag, BaseDocument *doc, BaseObject *op,
              BaseThread *bt, LONG priority, LONG flags);
         virtual Bool AddToExecution(PluginTag* tag, PriorityList* list);
         virtual Bool GetDDescription(GeListNode *node, Description *description,
              LONG &flags;);

    static NodeData *Alloc(void) { return gNew MyTag ; }
    };



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

    On 21/02/2006 at 08:54, xxxxxxxx wrote:

    The problem seems to come from the description.
    Something doesn't init correctly and C4D is not
    telling.



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

    On 21/02/2006 at 09:07, xxxxxxxx wrote:

    I don't think that the tag's object is available yet in Init(). I just tried and no print, but I do get the tag's object in GetDDescription() and Message() and it works in those.

    If you need to initialize something on the tag based upon the object, best to use Message() and check for which messages are called initially (usually MSG_DESCRIPTION_CHECKUPDATE or MSG_UPDATE).

    ETA: Also, make sure that your tag is indeed attached to an object in the document.



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

    On 21/02/2006 at 10:25, xxxxxxxx wrote:

    The type of the TagData is described in the description file. I changed that unintentionally from Tbase to Texpression without recognizing the importance of that line. What did you use as INCLUDE?

    CONTAINER TMyTag
    {
         NAME TMyTag;
         INCLUDE Tbase;

    GROUP ID_TAGPROPERTIES     { }
    }

    Bool MyTag::GetDDescription(GeListNode *node, Description *description,
          LONG &flags;)
    {
      if (!description->LoadDescription(ID_MYTAG))
      {
        GePrint("Loading failed!");
        return FALSE;
      }
      BaseTag    *tag    = (BaseTag* ) node;
      BaseObject *attObj = tag->getObject();

    String str = "none";
      if (attObj) str = attObj->GetName();
      GePrint("name of attObj: -"+str+"-");
    }

    "attObj->GetName()" crashes C4D. I attach the tag in the OM. Tomorrow I will try out Message().
    Thanks!



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

    On 21/02/2006 at 10:45, xxxxxxxx wrote:

    You can use either Tbase or Texpression for INCLUDE, but use the latter only if you are making an expression tag. That is, if you have TAG_EXPRESSION added in your RegisterTagPlugin() call.

    Try this:

    //*---------------------------------------------------------------------------*  
    Bool MyTag::GetDDescription(GeListNode* node, Description* description, LONG& flags)  
    //*---------------------------------------------------------------------------*  
    {  
         if (!node || !description) return FALSE;  
         if (!description->LoadDescription(node->GetType())) return FALSE;  
      
         BaseObject*          attObj;  
      
         // Get Object containing Dials  
         attObj = ((BaseTag* )node)->GetObject();  
         String str;  
         if (attObj) str = attObj->GetName();  
         else               str = "none";  
         GePrint("name of attObj: -"+str+"-");  
      
         ...  
      
         // For GetDDescription(), you must do this!  
         flags |= DESCFLAGS_DESC_LOADED;  
         return SUPER::GetDDescription(node,description,flags);  
    }
    


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

    On 30/03/2006 at 17:18, xxxxxxxx wrote:

    - What's the best way to add an XPresso-Tag?
    Build it in the Init()-call of my TagData-class like:
    XPressoTag *xpTag = XPressoTag::Alloc();
    GvNodeMaster *nodeMaster = xpTag- >GetNodeMaster();
    GvNode *node = nodeMaster->CreateNode(nodeMaster->GetRoot(),
    ID_OPERATOR_OBJECT, NULL, -1, -1);
    Or create a class derived from XPressoTag?
    I would like to hide that XPresso from the OM with PLUGINFLAG_HIDE
    so I can modify object positions with an invisible hand.

    Yes that code is about what I'm doing. Have you been able to successfully either load an XGroup or Add and Connect ports yet? I have this code for Adding Ports (much more complex than people are want to believe) :

    // PortList for finding available ports on node  
    AutoAlloc<GvPortList>     portList;  
    if (!portList)               return ErrorException::Throw(GeLoadString(ERROR_MEMORY_TEXT), "IPPDial.ResolveMasterDials.portList");  
    XPressoTag*                    xtag;  
    GvNodeMaster*               nodeMaster;  
    GvNode*                         root;  
    // Driver  
    GvNode*                         snode;  
    GvPort*                         sport;  
    // Port-related  
    GvPortListEntry*          portLE;  
    GvPortDescription          portDesc;  
      
    // ... Add your XPresso tag, get GvNodeMaster, add GvNodes  
      
    // - Add Ports  
    // -- Source (Master) Node  
    portList->FlushAll();  
    snode->GetPortList(GV_PORT_OUTPUT, *portList);  
    portCount =               portList->GetCount();  
    for (i = 0; i < portCount; i++)  
    {  
         portLE =     portList->GetIndex(i);  
         snode->GetPortDescription(GV_PORT_OUTPUT, portLE->id, &portDesc;);  
         if (portDesc.name == md->dialName) break;  
    }  
    if (i == portCount)     return ErrorException::Throw("Master Node Port not found!");  
    if (!snode->AddPortIsOK(GV_PORT_OUTPUT, portLE->id))          return ErrorException::Throw(GeLoadString(ERROR_MEMORY_TEXT), "IPPDial.ResolveMasterDials.sport.NotOK");  
    sport =                    snode->AddPort(GV_PORT_OUTPUT, portLE->id);  
    if (!sport)               return ErrorException::Throw(GeLoadString(ERROR_MEMORY_TEXT), "IPPDial.ResolveMasterDials.sport");  
    

    Note that I'm qualifying the desired port by name. The portLE->id's are not the same as description ids (how surprising...).


Log in to reply