AddNodeToCalculationTable fails in R16



  • On 12/09/2015 at 10:31, xxxxxxxx wrote:

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

    ---------
    Hi,

    I have an Xpresso node that worked just fine in R13-R15. Now I have recompiled it with the R16 SDK and it stopped working.

    The node has several inports. One of them is a static port taking an integer. Now, if that port has no connection AddNodeToCalculationTable returns true and the Calculate function is correspondingly called. BUT as soon as I make a connection there (integer is coming from a C4D iterator output) AddNodeToCalculationTable fails and Calculate is never called subsequently.

    Any idea what it could be? Any help is highly appreciated.
    Here is the base code of the node:

    node.h

      
    class XParticleEditNode : public GvOperatorData  
    {  
      // Defines super  
      INSTANCEOF(XParticleEditNode, GvOperatorData)  
    public:  
      virtual Bool AddToCalculationTable    (GvNode *bn, GvRun *r);  
      virtual Bool iCreateOperator        (GvNode *bn);  
      
      virtual Bool iGetPortDescription    (GvNode* bn, GvPortIO port, Int32_C4D id, GvPortDescription* pd);  
      virtual Bool GetDDescription        (GeListNode *node, Description *description, DESCFLAGS_DESC &flags);  
      
      Bool InitCalculation(GvNode *bn, GvCalc *c, GvRun *r);  
      Bool Calculate(GvNode *bn, GvPort *port, GvRun *run, GvCalc *calc);  
      void FreeCalculation(GvNode *bn, GvCalc *c);  
        
      static NodeData* Alloc(void)  
      {  
          return new_c4d(XParticleEditNode);  
      }  
      
    private:  
      GvValuesInfo ports;  
    };
    

    node.cpp

      
    Bool XParticleEditNode::iCreateOperator(GvNode *bn)  
    {  
      BaseContainer* data = bn->GetOpContainerInstance();  
      if (!data) return FALSE;  
      
      data->SetInt64 (XPARTICLE_EDIT_INDEX,0);  
      return SUPER::iCreateOperator(bn);  
    }  
    Bool XParticleEditNode::AddToCalculationTable(GvNode *bn, GvRun *r)  
    {  
      Bool res = r->AddNodeToCalculationTable(bn); //RETURNS 0 if there is a connection at static port  
      return res;  
    }  
      
    Bool XParticleEditNode::Calculate(GvNode *bn, GvPort *port, GvRun *run, GvCalc *calc)  
    {  
      //NEVER GETS HERE WHEN THERE IS A CONNECTION AT THE STATIC PORT  
      
      return TRUE;  
    }  
      
    Bool XParticleEditNode::iGetPortDescription(GvNode* bn, GvPortIO port, Int32_C4D id, GvPortDescription* pd)  
    {  
      if(!SUPER::iGetPortDescription(bn,port,id,pd)) return false;  
      
      return true;  
    }  
      
    Bool XParticleEditNode::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)  
    {   
      if (!description || !node) return FALSE;   
      if (!description->LoadDescription(node->GetType())) return FALSE;  
      flags |= DESCFLAGS_DESC_LOADED;  
      return SUPER::GetDDescription(node, description, flags);  
    }  
      
    Bool XParticleEditNode::InitCalculation(GvNode *bn, GvCalc *c, GvRun *r)  
    {  
      return GvBuildInValuesTable(bn, ports, c, r, GV_DEFINED_PORTS); //ALWAYS WORKS. VERIFIED VIA DEBUGGING  
    }  
      
    void XParticleEditNode::FreeCalculation(GvNode *bn, GvCalc *c)  
    {  
      GvFreeValuesTable(bn, ports);  
    }
    

    node.res

    CONTAINER fx_xpresso_particleedit  
    {  
       NAME fx_xpresso_particleedit;  
       INCLUDE GVbase;  
      
       GROUP ID_GVPROPERTIES  
       {      
       }  
       GROUP ID_GVPORTS  
       {  
      LONG    XPARTICLE_EDIT_INDEX    {MIN 0; INPORT; STATICPORT; CREATEPORT; }  
      
      VECTOR  XPARTICLE_EDIT_POS    {INPORT; EDITPORT; CREATEPORT;PORTONLY;}  
      
      BOOL    XPARTICLE_EDIT_ALIVE    {INPORT; EDITPORT; PORTONLY;}  
      BOOL    XPARTICLE_EDIT_COLLISION{INPORT; EDITPORT; PORTONLY;}  
      BOOL    XPARTICLE_EDIT_SPRAY    {INPORT; EDITPORT; PORTONLY;}  
      BOOL    XPARTICLE_EDIT_BUBBLE    {INPORT; EDITPORT; PORTONLY;}  
      BOOL    XPARTICLE_EDIT_TEMP    {INPORT; EDITPORT; PORTONLY;}  
        
      REAL    XPARTICLE_EDIT_PROP_SCALAR    {INPORT; MULTIPLE; PORTONLY; NOTMOVABLE;}  
      VECTOR    XPARTICLE_EDIT_PROP_VECTOR    {INPORT; MULTIPLE; PORTONLY; NOTMOVABLE;}  
      BOOL    XPARTICLE_EDIT_PROP_STATE    {INPORT; MULTIPLE; PORTONLY; NOTMOVABLE;}  
       }  
    }
    


  • On 14/09/2015 at 05:00, xxxxxxxx wrote:

    btw. it doesn't matter if the port is static or not. Also no difference if I take all the other elements out (of resources) and have that one port only.



  • On 14/09/2015 at 05:51, xxxxxxxx wrote:

    Adding a hidden dummy outport also doesn't help (was just a thought even if it was unlikely as the docs say AddToCalculationTable should be used if you want non-requesting output port behavior).



  • On 14/09/2015 at 06:05, xxxxxxxx wrote:

    However, it DOES work if I have an outport and that one is connected to another node!
     
    So the question then is, how do I get it back that I don't need an outport (because this node is not supposed to output anything). Can I somehow set the outport to think it is connected (actually this is functionality AddToCalculationTable() should provide me with right)?

    But I would assume the node would do this automatically if there was no outport at all (guess that's what it did prior to R16?)



  • On 14/09/2015 at 06:36, xxxxxxxx wrote:

    I overloaded SetRecalculate now as well adding the node the ctable there. It works in there!
    But the AddToCalculationTable() call still doesn't (setting force = true will result in true evaluation BUT now all nodes are called twice, so double the iteration count available...clearly this is not right and the docs also suggest not to use it. Now I know why).

    Using the efficiency display in the Xpresso editor tells me that my node is evaluated once less than the iterator (meaning one iteration is missing...which surely can be traced back to the non-working AddToCalculationTable() call). Is this supposed to be the case (that the iterator is called once more?)



  • On 15/09/2015 at 05:43, xxxxxxxx wrote:

    Hi,

    I have some problems reproducing your issue.
    I took your code, added an Xpresso tag to a cube, created your Xpresso node. it doesn't matter if I connect anything to index, AddNodeToCalculationTable() returns true and Calculate() is called. I tried this in R16 (16.051) and R17. I also checked the code in C4D and did not find any obvious changes to the code.
    Now the only thing I can think of, that may be different between my and your version is the registration of the node. I used the following:

    GvRegisterOperatorPlugin(MY_ID, String("AddToCalculationTable Test"), GV_OPERATORFLAG_NONE, XParticleEditNode::Alloc, "fx_xpresso_particleedit", 0, ID_GV_OPCLASS_TYPE_GENERAL, ID_GV_OPGROUP_TYPE_GENERAL, 0, nullptr);
    

    Which version of C4D are you using?
    Or is it my test scenario, that's making the difference?



  • On 15/09/2015 at 05:52, xxxxxxxx wrote:

    Hi Andreas,

    thanks for the answer. I am in R16.051.

    1. Did you try to connect a c4d iterator node to the index? Still no issue?
    2. I register it the same way except that I have my own node classes:
    GvRegisterOperatorPlugin(plugin_id, node_name, 0, XParticleEditNode::Alloc, "fx_xpresso_particleedit", 0, MY_OPCLASS, MY_OPGROUP, 0, icon);

    However, I have a few other nodes that do work just fine so it cannot be the custom op class/group (which shouldn't have an effect on the execution anyway as it's just a RMB menu description handler).

    I try the general groups just to be sure.



  • On 15/09/2015 at 05:54, xxxxxxxx wrote:

    I don't think, you need to test different groups. I agree with you, these won't have any influence.



  • On 15/09/2015 at 05:57, xxxxxxxx wrote:

    Got it, the iterator makes the difference. Sorry, I missed that part in your first post.



  • On 15/09/2015 at 06:00, xxxxxxxx wrote:

    Nope, makes no difference here if I use general op class/group ids instead. Also I don't think it's your scenario. I am on a null object and have the iterator and my node only. Still, when I move on 1 frame the iterator is called once (though I have set 4 iterations) and my node is called 0 times (AddNodeToCalculationTable always returning false). I used no extra code beside the one I posted above (I took all the implementation details out just to be sure)



  • On 15/09/2015 at 06:01, xxxxxxxx wrote:

    Oh gosh, thanks for confirming. I thought I was getting crazy! :)



  • On 15/09/2015 at 06:08, xxxxxxxx wrote:

    ok, so I guess that means SetRecalculate is indeed required for supporting iterator node inputs in R16+ and that the missing iteration I mentioned is supposed to be that way.

    With caution I would say you can mark this as resolved (if I encounter unusual behavior through this I will report back for completeness).

    Thanks Andreas


Log in to reply