Possible bug in MathNode [SOLVED]

On 02/06/2015 at 03:29, xxxxxxxx wrote:

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


I'm creating an object data plugin with some Xpresso files in it.
I have an Xpresso file where one object's rotation is driven by another object's rotation.
(Cube1 RotP x -1 = Cube2 RotP)
The problem is, it doesn't initially work. It only works if I go to my Xpresso file and reset the -1 value to -1 (in the math node). Only then it is working :s

Here is my code:

#include "c4d.h"  
#include "c4d_symbols.h"  
#include "omyplugin.h"  
#include "main.h"  
#include "c4d_basedocument.h"  
#include "c4d_graphview.h"  
#include "gvmath.h"  
#include "customgui_priority.h"  
#include "c4d_operatorplugin.h"  
// Used to calculate the proper ID of a nodeport  
#define GvCall(op,fnc)  (((GvOperatorData* )op)->*((OPERATORPLUGIN* )C4DOS.Bl->RetrieveTableX((NodeData* )op, 1))->fnc)  
class MyPluginData : public ObjectData  
  INSTANCEOF(MyPluginData, ObjectData)  
  virtual Bool Init(GeListNode* node);  
  virtual Bool Message                (GeListNode* node, Int32 type, void* data);  
  virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh);  
  static NodeData* Alloc(void) { return NewObjClear(CharacterData); }  
BaseObject* GetNextObject(BaseObject* op)  
  if (!op)  
      return nullptr;  
  if (op->GetDown())  
      return op->GetDown();  
  while (!op->GetNext() && op->GetUp())  
      op = op->GetUp();  
  return op->GetNext();  
BaseObject* GetObjectWithName(BaseObject* op, String name)  
  while (op)  
      if (op->GetName() == name)  
          return op;  
          op = GetNextObject(op);  
      if (!op)  
          return nullptr;  
Bool CharacterData::Message(GeListNode* node, Int32 type, void* data)  
      GePrint("A button has been pressed");  
      DescriptionCommand* dc = (DescriptionCommand* )data;  
      if (dc->id[0].id == MY_BUTTON)  
          GePrint("The button has been pressed");  
          BaseDocument* doc = ((BaseObject* )node)->GetDocument();  
          if (!doc)  
              return false;  
          BaseObject* op = (BaseObject* )node;  
          if (!op)  
              return false;  
          ModelingCommandData cdNull;  
          cdNull.doc = doc;  
          cdNull.op = op;  
          if (SendModelingCommand(MCOMMAND_CURRENTSTATETOOBJECT, cdNull))  
              BaseObject* null = static_cast<BaseObject*>(cdNull.result->GetIndex(0));  
              doc->InsertObject(null, nullptr, op);  
              if (null)  
                  BaseObject* firstCube = GetObjectWithName(null, "First_Cube");  
                  if (!firstCube) return false;  
                  BaseObject* secondCube = GetObjectWithName(null, "Second_Cube");  
                  if (!secondCube) return false;  
                  // Create the Xpresso Tag  
                  XPressoTag* myXPressoTag = static_cast<XPressoTag*>(null->MakeTag(Texpresso, NULL));  
                  if (!myXPressoTag) return false;  
                  GeData myXPressoData;  
                  if (myXPressoTag->GetParameter(DescLevel(EXPRESSION_PRIORITY), myXPressoData, DESCFLAGS_GET_0))  
                      PriorityData* pd = (PriorityData* )myXPressoData.GetCustomDataType(CUSTOMGUI_PRIORITY_DATA);  
                      if (pd) pd->SetPriorityValue(PRIORITYVALUE_PRIORITY, GeData(10));  
                      myXPressoTag->SetParameter(DescLevel(EXPRESSION_PRIORITY), myXPressoData, DESCFLAGS_SET_0);  
                  GvNodeMaster* myNodeMaster = myXPressoTag->GetNodeMaster();  
                  if (myNodeMaster)  
                      GvNode* firstCubeNode = myNodeMaster->CreateNode(myNodeMaster->GetRoot(), ID_OPERATOR_OBJECT);  
                      if (!firstCubeNode) return false;  
                      firstCubeNode->OperatorSetData(GV_ATOM, firstCube, GV_OP_DROP_IN_BODY);  
                      GvOperatorData* firstCubeData = firstCubeNode->GetOperatorData();  
                      DescID firstCubeDescID = DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Z));  
                      Int32 firstCubeOutID = GvCall(firstCubeData, GetMainID) (firstCubeNode, GV_PORT_OUTPUT, firstCubeDescID);  
                      GvPort* firstCubeOutPort = firstCubeNode->AddPort(GV_PORT_OUTPUT, firstCubeOutID);  
                      if (firstCubeOutPort == nullptr) return false;  
                      GvNode* mathNode = myNodeMaster->CreateNode(myNodeMaster->GetRoot(), ID_OPERATOR_MATH, nullptr, 100, 0);  
                      if (!mathNode) return false;  
                      mathNode->SetParameter(GV_DYNAMIC_DATATYPE, ID_GV_DATA_TYPE_REAL, DESCFLAGS_SET_0);  
                      mathNode->SetParameter(GV_MATH_FUNCTION_ID, GV_MUL_NODE_FUNCTION, DESCFLAGS_SET_0);  
                      GvPort* mathFirstInPort = mathNode->GetPort(1000);  
                      GvPort* mathSecondInPort = mathNode->GetPort(1001);  
                      GvPort* mathOutPort = mathNode->GetOutPort(0);  
                      const DescID mathSecondInPortValueID = DescID(DescLevel(GV_MATH_INPUT, DTYPE_SUBCONTAINER, 0), DescLevel(1001, DTYPE_REAL, 0));  
                      mathNode->SetParameter(mathSecondInPortValueID, Int32(-1), DESCFLAGS_SET_0);  
                      GvNode* secondCubeNode = myNodeMaster->CreateNode(myNodeMaster->GetRoot(), ID_OPERATOR_OBJECT, nullptr, 220, 0);  
                      if (!secondCubeNode) return false;  
                      secondCubeNode->OperatorSetData(GV_ATOM, secondCube, GV_OP_DROP_IN_BODY);  
                      GvOperatorData* secondCubeData = secondCubeNode->GetOperatorData();  
                      DescID secondCubeDescID = DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Z));  
                      Int32 secondCubeInID = GvCall(secondCubeData, GetMainID) (secondCubeNode, GV_PORT_INPUT, secondCubeDescID);  
                      GvPort* secondCubeInPort = secondCubeNode->AddPort(GV_PORT_INPUT, secondCubeInID);  
                      if (secondCubeInPort == nullptr) return false;  
                      if (myNodeMaster->IsConnectionValid(firstCubeNode, firstCubeOutPort, mathNode, mathFirstInPort, firstCubeNode, firstCubeOutPort, mathNode, mathFirstInPort))  
                          mathNode->AddConnection(firstCubeNode, firstCubeOutPort, mathNode, mathFirstInPort);  
                      if (myNodeMaster->IsConnectionValid(mathNode, mathOutPort, secondCubeNode, secondCubeInPort, mathNode, mathOutPort, secondCubeNode, secondCubeInPort))  
                          secondCubeNode->AddConnection(mathNode, mathOutPort, secondCubeNode, secondCubeInPort);  
BaseObject* MyPluginData::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh)  
  BaseObject* null = BaseObject::Alloc(Onull);  
  BaseObject* firstCube = BaseObject::Alloc(Ocube);  
  if (!firstCube)  
      return nullptr;  
  firstCube->SetRelPos(Vector(-200, 0, 0));  
  BaseObject* secondCube = BaseObject::Alloc(Ocube);  
  if (!secondCube)  
      return nullptr;  
  secondCube->SetRelPos(Vector(200, 0, 0));  
  return character;  
Bool MyPluginData::Init(GeListNode* node)  
  BaseObject*         op = (BaseObject* )node;  
  BaseContainer* data = op->GetDataInstance();  
  if (!data)  
      return false;  
  return true;  
// be sure to use a unique ID obtained from www.plugincafe.com  
#define ID_MYPLUGINOBJECT 1000008  
Bool RegisterMyPlugin(void)  
  return RegisterObjectPlugin(ID_MYPLUGINOBJECT, GeLoadString(IDS_MYPLUGIN), OBJECT_GENERATOR | OBJECT_ISSPLINE, MyPluginData::Alloc, "omyplugin", AutoBitmap("circle.tif"), 0);  

Does anybody see the problem here?
Could this be a bug?

Thanks in advance for your help and time!
Casimir Smets

On 02/06/2015 at 07:35, xxxxxxxx wrote:


you are setting the dynamic datatype to real ( ID_GV_DATA_TYPE_REAL ), but then you set the actual value to an integer ( Int32(-1) ). You have to set the value to a float value.

Best wishes,

On 02/06/2015 at 07:46, xxxxxxxx wrote:


Hmm, I feel stupid now -_-
But, I'm still not fully getting it.
I've tried the same thing with INTEGER and Int32 yesterday, which didn't work.
Now with the REAL and the Float it does work.
What is the difference between integer and real, in this case? Especially because I have no decimals?

Thanks for your help and time!

Casimir Smets

On 02/06/2015 at 10:16, xxxxxxxx wrote:


integer and float are different datatypes. I guess that the node tries to access a float value if the datatype is set to real. But when you define a integer value this value may not be converted automatically.

Best wishes,

On 02/06/2015 at 10:30, xxxxxxxx wrote:

Hi Sebastian,

Thanks for your answer!
And I guess that was the struggle for me.
You can mark this post as solved!

Casimir Smets