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

    my expresso-node example, and questions

    SDK Help
    0
    4
    831
    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 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";
      }

      */

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

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

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