my expresso-node example, and questions

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

On 16/12/2002 at 03:43, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   8.012 
Platform:      Mac OSX  ; 
Language(s) :     C++  ;  XPRESSO  ;

---------
I made an Expresso node based on Mikael Sterner's example in "Topic: Nodes that Iterate",
and some of his other examples.

(my node is not suppose to iterate).
It works, but I have no idea if I did it right...
Also, it has one problem: When nothing is connected to the inport,
i want to get the value directly from the inport, but the ...->Calculate(bn,r,c) returns NULL!

So, how do I get the import values without having to connect them to something?

BTW: Life would be easier if all of Maxon's own nodes where available in source.

Thanks!
kris

Complete source code follows: (with some more questions).
////////////////////////////////////////////////////
////////////////////////////////////////////////////
#include "c4d.h"
#include "c4d_operatordata.h"

#include "Kaaref1.h"

// forward declarations for functions from Mikael Sterner's post in "Topic: from port->SetData".
// I use these because port->GetData and ->SetData cause Cinema to crash.
GeData GvGetPortGeData(GvNode* node, GvPort* port, GvRun* run);
Bool GvSetPortGeData(const GeData& ge_data, GvNode* node, GvPort* port, GvRun* run);

const GvOperatorID KAAGETTAG1_ID = 10983430; // just random
static LONG input_ids[] = { 0 };

class KaaGvRef1 : public GvOperatorData
{
private:
     GvCalcTable* table; // not used... What is it for?
public:
     LONG mode;
     LONG steps;

KaaGvRef1(void) : table(NULL) {}
     
     Bool Init(GeListNode *node)
     {          
          // Use iCreateOperator instead!
          return TRUE;
     }
          
     virtual Bool iCreateOperator(GvNode *bn)
     {
          BaseContainer* data = bn->GetOpContainerInstance();
          if (!data) return FALSE;
          data->SetLong(STEPS, 3);
          //return SUPER::iCreateOperator(bn); // SUPER undefined...
          return GvOperatorData::iCreateOperator(bn);
     }

Bool InitCalculation(GvNode *bn, GvCalc *c, GvRun *r)
     {
          BaseContainer *data = bn->GetOpContainerInstance();
          steps = data->GetLong(STEPS);
          mode = data->GetLong(MODE_ID);
          return TRUE;          
     }

void FreeCalculation(GvNode *bn, GvCalc *c)
     {
     }

Bool Calculate(GvNode *bn, GvPort *port, GvRun *r, GvCalc *c)
     {
          if (!port) return TRUE;
          
          // Calculate inport
          GvPort* inport = bn->GetInPortFirstMainID(INPORT_LINK);
          if (!inport) return FALSE; // never happens?
          inport = inport->Calculate(bn, r, c); // link
          if (!inport) return FALSE; // hapens when the inport is not connected
          // this is where I want to get data from the node itself!

// Get the data from the inport
          BaseList2D * mylist2D = NULL; // can't use AutoAlloc
          
          GeData linkdata = GvGetPortGeData(bn, inport, r);
          BaseLink* test = linkdata.GetBaseLink();
          if (test && test->GetLink(bn->GetNodeMaster()->GetDocument()))
          {
               mylist2D = test->GetLink(bn->GetNodeMaster()->GetDocument());
               GePrint(mylist2D->GetName());
          }
          else {
               GePrint("no link");
          }

// do I have to get the inport data for each outport i wish to calculate?
          // or is it a bette way?

switch(port->GetMainID()) // maby not needet for one outport?
          {
               // is this the right way, when you have many outports? What is most efficient?
               case OUTPORT_LINK:
               {
                    BaseObject * b = (BaseObject* )mylist2D;                    
     
                    for (LONG i = 0; i<steps; i++){
                         switch(mode){
                              case GETDOWN:
                                   b = b->GetDown(); break;
                              case GETUP:
                                   b = b->GetUp(); break;
                              case GETPRED:
                                   b = b->GetPred(); break;
                              case GETNEXT:
                                   b = b->GetNext(); break;
                         }     
                         if (!b) break;
                    }
                    AutoAlloc<BaseLink> bl;
                    bl->SetLink(b);
                    GvSetPortGeData(GeData(bl), bn, port, r); // returns bool
                    break;
               }
          }

return TRUE;
     }

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

Bool RegisterKaaref1()
{
     return GvRegisterOperatorPlugin(
          KAAGETTAG1_ID, "Kaaref1", 0,
          KaaGvRef1::Alloc, "Kaaref1", 0,
          ID_GV_OPCLASS_TYPE_GENERAL, ID_GV_OPGROUP_TYPE_GENERAL, 0, NULL);
}

/*

// Kaaref1.res
CONTAINER Kaaref1
{
     NAME Kaaref1;
     INCLUDE GVbase;
     GROUP ID_GVPROPERTIES
     {
          LONG MODE_ID
          {
               CYCLE
               {
                    GETDOWN;
                    GETUP;
                    GETPRED;
                    GETNEXT;
               }
          }
          LONG STEPS { MIN 0; }
     }
     GROUP ID_GVPORTS
     {
          LINK INPORT_LINK {INPORT; STATICPORT; CREATEPORT;}
          LINK OUTPORT_LINK {OUTPORT; STATICPORT; CREATEPORT;}
     }
}

// Kaaref1.h
#ifndef _Kaaref1_H_
#define _Kaaref1_H_
enum
{
     MODE_ID               = 1000,
          GETDOWN          = 0,
          GETUP,
          GETPRED,
          GETNEXT,

STEPS = 2000,
     INPORT_LINK = 3000,
     OUTPORT_LINK = 4000
};
#endif

// Kaaref1.str
STRINGTABLE Kaaref1
{
     Kaaref1 "Kaaref1";
     MODE_ID               "Mode";
          GETDOWN          "GetDown()";
          GETUP          "GetUp()";
          GETPRED          "GetPrev()";
          GETNEXT          "GetNext()";
     STEPS "Steps";
     INPORT_LINK "in";
     OUTPORT_LINK "out";
}

*/

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

On 17/12/2002 at 02:19, xxxxxxxx wrote:

Well, first of all the Xpresso API isn't officially supported at the moment. But that being said here's a better example using some convenience functions I learned along the way:

    
    
    #include "c4d.h"  
    #include "c4d_operatordata.h"
    
    
    
    
    #include "Kaaref1.h"
    
    
    
    
    // Updated versions:
    
    
    
    
    GeData GvGetPortGeData(GvNode* node, GvPort* port, GvRun* run)  
    {   
      if (!node || !port) return GeData();
    
    
    
    
      GvPortDescription pd;  
      if (!node->GetPortDescription(port->GetIO(), port->GetMainID(), &pd)) return GeData();  
        
      GvDataInfo* info = GvGetWorld()->GetDataTypeInfo(pd.data_id);  
      if (!info) return GeData();  
        
      GvDynamicData data;  
      GvAllocDynamicData(node, data, info);  
        
      if (!port->GetData(data.data, data.info->value_handler->value_id, run)) return GeData();  
        
      CUSTOMDATATYPEPLUGIN* pl =   
        FindCustomDataTypePlugin(data.info->data_handler->data_id);   
      if (!pl) return GeData();  
        
      GeData ge_data;   
      if (!CallCustomDataType(pl, ConvertGvToGeData)(data.data, 0, ge_data)) return GeData();  
        
      return ge_data;  
    }
    
    
    
    
    Bool GvSetPortGeData(const GeData& ge_data, GvNode* node, GvPort* port, GvRun* run)  
    {   
      if (!node || !port || !run) return FALSE;  
        
      GvPortDescription pd;  
      if (!node->GetPortDescription(port->GetIO(), port->GetMainID(), &pd)) return FALSE;
    
    
    
    
      GvDataInfo* info = GvGetWorld()->GetDataTypeInfo(pd.data_id);  
      if (!info) return FALSE;  
        
      GvDynamicData data;  
      GvAllocDynamicData(node, data, info);  
        
      CUSTOMDATATYPEPLUGIN* pl =   
        FindCustomDataTypePlugin(data.info->data_handler->data_id);   
      if (!pl) return FALSE;  
        
      if (!CallCustomDataType(pl, ConvertGeDataToGv)(ge_data, data.data, 0)) return FALSE;  
        
      if (!port->SetData(data.data, data.info->value_handler->value_id, run)) return FALSE;  
        
      return TRUE;  
    }
    
    
    
    
    const GvOperatorID KAAGETTAG1_ID = 1010893; // From PluginCafe!
    
    
    
    
    static LONG input_ids[] = { INPORT_LINK, 0 }; // Use this for the input ports!  
    enum { INPORT_LINK_INDEX };
    
    
    
    
    class KaaGvRef1 : public GvOperatorData  
    {  
    // Defines super  
    INSTANCEOF(KaaGvRef1, GvOperatorData)  
    public:
    
    
    
    
        
      virtual Bool iCreateOperator(GvNode *bn)  
      {  
        BaseContainer* data = bn->GetOpContainerInstance();   
        if (!data) return FALSE;
    
    
    
    
        data->SetLong(STEPS, 3);
    
    
    
    
        return SUPER::iCreateOperator(bn);  
      }  
        
        
        
      Bool InitCalculation(GvNode *bn, GvCalc *c, GvRun *r)  
      {  
        return GvBuildInValuesTable(bn, ports, c, r, input_ids);      
      }  
        
        
      void FreeCalculation(GvNode *bn, GvCalc *c)  
      {  
        GvFreeValuesTable(bn, ports);  
      }  
        
      Bool Calculate(GvNode *bn, GvPort *port, GvRun *run, GvCalc *calc)  
      {  
        if (!port) return FALSE;  
          
        BaseContainer *data = bn->GetOpContainerInstance();  
        if (!data) return FALSE;
    
    
    
    
        LONG steps = data->GetLong(STEPS);  
        LONG mode = data->GetLong(MODE_ID);
    
    
    
    
        GvValue* vinport = ports.in_values[INPORT_LINK_INDEX];  
        if (!vinport) return FALSE; // Doesn't matter that it never happens; always check pointers!
    
    
    
    
        if (!vinport->Calculate(bn, GV_PORT_INPUT, run, calc, 0)) return FALSE;  
          
        GvPort* inport = vinport->GetPort();  
        GeData inportdata = GvGetPortGeData(bn, inport, run);
    
    
    
    
        BaseDocument* doc = bn->GetNodeMaster()->GetDocument();  
        if (!doc) return FALSE;
    
    
    
    
        BaseLink* link = inportdata.GetBaseLink();  
        if (!link) return FALSE;
    
    
    
    
        BaseList2D* list = link->GetLink(doc);  
        if (!list) return FALSE;  
          
        switch(port->GetMainID())   
        {  
        case OUTPORT_LINK:  
          {  
            BaseObject* obj = static_cast<BaseObject*>(list);  
            for (LONG i = 0; list && i < steps; ++i)  
            {  
              switch(mode)  
              {  
              case GETDOWN: obj = obj->GetDown(); break;  
              case GETUP: obj = obj->GetUp(); break;  
              case GETPRED: obj = obj->GetPred(); break;  
              case GETNEXT: obj = obj->GetNext(); break;  
              }       
            } 
    
    
    
    
            AutoAlloc<BaseLink> bl;  
            if (!bl) return FALSE;  
            bl->SetLink(obj);
    
    
    
    
            return GvSetPortGeData(GeData(bl), bn, port, run);  
          }  
        }  
          
        return FALSE;  
      }  
          
      static NodeData* Alloc(void) { return gNew KaaGvRef1; }
    
    
    
    
    private:  
      GvValuesInfo ports;  
    };
    
    
    
    
    const LONG ID_GV_OPGROUP_MY = 1010850;  
    const LONG ID_GV_OPCLASS_MY = 1010851;
    
    
    
    
    static const String* GetMyGroupName()  
    {  
      static String mygroup("My Group");  
      return &mygroup;  
    }
    
    
    
    
    static BaseBitmap* GetMyGroupIcon()  
    {  
      // Never used  
      static AutoAlloc<BaseBitmap> icon;  
      if (!icon) return NULL;  
      if (icon->GetBw() == 0)  
      {  
        icon->Init(24, 24);  
        icon->Clear(200, 0, 0);  
      }  
      return icon;  
    }
    
    
    
    
    static const String* GetMyClassName()  
    {  
      static String mygroup("My Class");  
      return &mygroup;  
    }
    
    
    
    
    static BaseBitmap* GetMyClassIcon()  
    {  
      // Never used  
      static AutoAlloc<BaseBitmap> icon;  
      if (!icon) return NULL;  
      if (icon->GetBw() == 0)  
      {  
        icon->Init(24, 24);  
        icon->Clear(0, 0, 200);  
      }  
      return icon;  
    }
    
    
    
    
     
    
    
    
    
    Bool RegisterKaaref1()  
    {  
      static AutoAlloc<BaseBitmap> icon;  
      if (!icon) return NULL;  
      if (icon->GetBw() == 0)  
      {  
        icon->Init(24, 24);  
        icon->Clear(100,200, 0);  
      }
    
    
    
    
      static GV_OPCLASS_HANDLER myclass;  
      myclass.class_id = ID_GV_OPCLASS_MY;  
      myclass.GetName = GetMyClassName;  
      myclass.GetIcon = GetMyClassIcon;
    
    
    
    
      if (!GvRegisterOpClassType(&myclass, sizeof(myclass))) return FALSE;
    
    
    
    
      static GV_OPGROUP_HANDLER mygroup;  
      mygroup.group_id = ID_GV_OPGROUP_MY;  
      mygroup.GetName = GetMyGroupName;  
      mygroup.GetIcon = GetMyGroupIcon;
    
    
    
    
      if (!GvRegisterOpGroupType(&mygroup, sizeof(mygroup))) return FALSE;;
    
    
    
    
      return GvRegisterOperatorPlugin(  
        KAAGETTAG1_ID, "Kaaref1", 0,   
        KaaGvRef1::Alloc, "Kaaref1", 0,   
        ID_GV_OPCLASS_MY, ID_GV_OPGROUP_MY, ID_GV_IGNORE_OWNER, icon);  
    }

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

On 17/12/2002 at 05:00, xxxxxxxx wrote:

I compiled it, and it works!
Had to change "list" in "for (LONG i = 0; list && i < steps; ++i)" to "obj"

Nice to have a custom class and group (GvRegisterOpClassType, GvRegisterOpGroupType)
Did you just give them random IDs?

Thank you.

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

On 17/12/2002 at 11:49, xxxxxxxx wrote:

Quote: Originally posted by kris on 17  December 2002
>
> * * *
>
>
> Nice to have a custom class and group (GvRegisterOpClassType, GvRegisterOpGroupType)
> Did you just give them random IDs?
No, they must be unique IDs from plugincafe. (Every time you see a seemingly random number it's a good bet that it's a unique ID.)