jujut

Hi,
I am creating custom suite of Node which used custom MPxData.
When i load the plugin in maya and check the plug-in information, i get the correct dependency Nodes: "customNode" and the correct dependency graph data types: "customData".
This data are correctly register in the maya plugin and also in the initialize custom node.

1- In the pluginMain.cpp:
initializePlugin()

Code:

status = plugin.registerData("customData", customData::id, customData::creator);
if (!status) {status.perror("Failed to register 'customData'");return status;}
status = plugin.registerNode("customNode", customNode::id, customNode::creator, customNode::initialize);
if (!status) {status.perror("customNode");return status;}

uninitializePlugin():

Code:

status = plugin.deregisterNode(customNode::id);if (!status) {status.perror("customNode");return status;}
status = plugin.deregisterData(customData::id);
if (!status) {status.perror("Failed to deregister 'customData'");return status;}

2- In the customNode.cpp:
initialize():

Code:

MFnTypedAttribute tAttr;

floatValue = nAttr.create("floatValue", "floatValue", MFnNumericData::kFloat, 1.0f);
nAttr.setMin(0.0f);
nAttr.setSoftMax(10.0f);
nAttr.setStorable(true);
nAttr.setKeyable(true);
addAttribute(floatValue);

p_outData = tAttr.create("outData", "outData", customData::id, MObject::kNullObj, &status);
tAttr.setStorable(false);
tAttr.setKeyable(false);
tAttr.setReadable(true);
tAttr.setWritable(false);
addAttribute(p_outData);

attributeAffects(floatValue, p_outData);

At this point everything seem to working fine, except in the compute() of the customNode.

compute():

Code:

MStatus customNode::compute(const MPlug& plug, MDataBlock& data){
if (plug == p_outData )
{
.....

The line "if (plug == p_outData )", don't return the correct value, it's always false. The p_outData (is connected to an other node)
"plug == p_outData" retrun correct value only when i unplug the p_outData....
I don't understand why, if i replace p_outData in the initialize by an other maya built-in DG data types it's working fine.
I try with MPxData and MPxGeometryData but i have the same issue.
If somehone have an idea it will be very helpfull, it's hard to find some example on internet about the MPxData.

Thanks

Quote 0 0
pshipkov
The info you provide is not enough for me to understand good enough what is happening and try give you and answer.

I used MPxData a long time ago only once and never again. Too much for too little.

If i need to load/save data i do it through Python or MPxCommand accessing data on the node or public members of the class instance storing it.

If i have to stream data in/out i implement it myself. It is more or less the same amount of work.

It sounds to me that you are streaming, correct ?
Quote 0 0
jujut

Hi,
Thanks for the reply.

Yes i am trying to add new dependency graph data, for streamming data between node.

Below a capture of the custom plugin info:
plugInfo.png 

Below an example on the nodeEditor:
nodeAandB.PNG 

Like you can see on the picture :
customNodeA->out_customData is connected to in_customData<-customNodeB.
customNodeB->out_floatData is connected to in_floatData<-customNodeB.

The issue is in the compute() of customNodeA.

When i try to detect if the out_customData output is connected it fail.
But when i try to detect  if the out_floatData output is connected it works.

Below it's what i do in the compute of the customNodeA:

Code:

MStatus status;
if (plug == p_customData )
{
MGlobal::displayInfo(MString(" customNodeA -------> data "));
data.setClean(plug);
}else if (plug == p_floatData ){
MGlobal::displayInfo(MString(" customNodeA -------> float "));
data.setClean(plug);
}else{
return MS::kUnknownParameter;
}
return MS::kSuccess;


Below what i do i nthe initialize() of the computeA:
Code:

  //input  param
  p_inFloat = nAttr.create("in_float", "in_float", MFnNumericData::kFloat, 1.0f);
  nAttr.setMin(0.0f);
  nAttr.setSoftMax(10.0f);
  nAttr.setStorable(true);
  nAttr.setKeyable(true);
  addAttribute(p_inFloat);
  //output customData
    p_customData = tAttr.create("out_customData", "out_customData", customData::id, MObject::kNullObj, &status);
  tAttr.setWritable(false);
  tAttr.setStorable(false);
    status = addAttribute(p_customData);
  // output floatData
  p_floatData = nAttr.create( "out_floatData", "out_floatData", MFnNumericData::kFloat, 0.0 );
  nAttr.setWritable(false);
  nAttr.setStorable(false);
  status = addAttribute(p_floatData);

  attributeAffects(p_inFloat, p_customData);
  attributeAffects(p_inFloat, p_floatData);


I attach to this topic the sourceCode and the compiled mll(maya2016 win) of this example project.

Thanks

 

Quote 0 0
jujut
I just tested like this :
Code:

MObject thisNode = thisMObject();
MPlug testPlug (thisNode,p_customData);
if ( testPlug.isConnected() )
{
.....


And it seems to work, only if the out_float is also connected to customNodeB ...
Quote 0 0
pshipkov
MPxData is used rarely and i won't be surprised if it has bugs.

Usually what i do is create a compound attribute like this:
customData
   someDoubleArray
   someVectorArray
   someDouble
   someString
   etc. etc.

On the nodeA i have outCustomData attribute, on nodeB i have inCustomData attribute.
When i connect only the top compound attributes Maya takes care of moving the child attribute data. So it can be accessed from the target node in an explicit and easy way.
Quote 0 0
jujut
yes it will work like this, but i would like to store specific things for simplifying the workflow and add custom std<<vector, random etc

Quote 0 0
jujut
ok so i try different way with a compoundAttribute.

First i try a compoundAttribute with one child (customData), it's not working. The same issue as before. Also when trying to check the connection of the compoundAttribute

Second i try a compoundAttribute with two child: the customData and a dummy attribute, and it's working fine :)

So i keep the second try with  the one flow connection because of the compoundAttribute and i can continue to evaluate the connection with plug == customData for checking if the customAttribute is connected in the compute(). And i don't need to check if the dummy attribute is connected. I can now transfert all what i want in my customAttribute which is very cool for what i need.

Thanks you pshipkov  for the compoundAttribute idea :)

I think it's not the cleanest way but it work fine :)

If anybody have an other idea?



Quote 0 0
jujut
ok so i try different way with a compoundAttribute.

First i try a compoundAttribute with one child (customData), it's not working. The same issue as before. Also when trying to check the connection of the compoundAttribute

Second i try a compoundAttribute with two child: the customData and a dummy attribute, and it's working fine :)

So i keep the second try with  the one flow connection because of the compoundAttribute and i can continue to evaluate the connection with plug == compoundData for checking if the customAttribute is connected in the compute(). And i don't need to check if the dummy attribute is connected. I can now transfert all what i want in my customAttribute which is very cool for what i need.

Thanks you pshipkov  for the compoundAttribute idea :)

I think it's not the cleanest way but it work fine :)

If anybody have an other idea?

Quote 0 0
jujut
I finally get something working correctly without the compoundAttribute:
Capture.PNG 

On this exemple the custom data drive in one attribute 5 kind of data:
float
MColor
MPointArray
std::vector of MPointArray
std::mt19937

Below the compute of customNodeA:
Code:

  if ( plug==p_customData )
  {
    //create customData
    MFnPluginData fnCustomData;
    fnCustomData.create(customData::id, &status);
    MDataHandle customDataHandle;
    customDataHandle = data.outputValue(p_customData);
    customData* myData = NULL;
    myData = (customData*)fnCustomData.data(&status);

    //edit customData
    float floatValue = data.inputValue( p_inFloat ).asFloat();
    myData->floatData=floatValue;
    MColor colorValue (1,0,0);
    myData->colorData=colorValue;
    MPointArray pointArraValue;
    pointArraValue.setLength(25);
    myData->pointArrayData=pointArraValue;
    std::vector < MPointArray > pointArrayVectorValue;
    pointArrayVectorValue.resize(13);
    pointArrayVectorValue[5].setLength(3);
    pointArrayVectorValue[12].setLength(100);
    myData->pointArrayVectorData=pointArrayVectorValue;
    std::mt19937 randomValue;
    randomValue.seed(1234);
    myData->randomData=randomValue;
    //out data
    customDataHandle.set(myData);
    
    data.setClean(plug);
  }else{
    return MS::kUnknownParameter;
  }


Below the comput of the customNodeB
Code:

  if ( plug == p_outFloat )
  {
    //get customData
    MDataHandle customDataHandle = data.inputValue( p_inData, &status );
    customData* myData = (customData*) customDataHandle.asPluginData();
    float out=0.0f;
    MColor outColor(0,0,0);
    MPointArray outPointArray;
    std::vector < MPointArray > outPointArrayVector;
    std::mt19937 outRandomValue;
    MGlobal::displayInfo(MString("  check customNodeB -------> "));
    if (myData != NULL) 
    {
      out = myData->floatData;
      outColor = myData->colorData;
      outPointArray = myData->pointArrayData;
      outPointArrayVector = myData->pointArrayVectorData;
      outRandomValue = myData->randomData;
      std::uniform_real_distribution<> dis(0, 1);
  
      //check customData Value
      MGlobal::displayInfo(MString("  floatData -------> ")+out);
      MGlobal::displayInfo(MString("  outColor R -------> ")+outColor.r);
      MGlobal::displayInfo(MString("  outColor G -------> ")+outColor.g);
      MGlobal::displayInfo(MString("  outColor B -------> ")+outColor.b);
      MGlobal::displayInfo(MString("  outPointArray length -------> ")+outPointArray.length());
      MGlobal::displayInfo(MString("  outPointArrayVector length -------> ")+outPointArrayVector.size());
      MGlobal::displayInfo(MString("  outPointArrayVector[5] length -------> ")+outPointArrayVector[5].length());
      MGlobal::displayInfo(MString("  outPointArrayVector[12] length -------> ")+outPointArrayVector[12].length());
      MGlobal::displayInfo(MString("  random -------> ")+dis(outRandomValue));
      
    }else{
      MGlobal::displayInfo(MString("  nothing plug in p_inData "));
    }
    //test output
    data.outputValue(p_outFloat).set(out);
    data.setClean(plug);
  }else{
    return MS::kUnknownParameter;
  }


I attach  to this message the source code of the test plug.

Quote 0 0
pshipkov
I didn't have the time to take a look at your problem, but glad to see you figured it out and posted the solution.
Quote 0 0
pshipkov
Btw, there is another class in the Maya API that is similar to MPxData, but does not rely on hardcoded data structure, so you can add/remove data on the fly. But it works on few predefined data types only. Which is ok in like 90% of the cases i found.
Quote 0 0
pshipkov
Maybe i should provide the name of the class, but not just talk about it. :)
MFnArrayAttrsData
Quote 0 0

Add a Website Forum to your website.