Hi,
I have created a custom MPxSurfaceShape to store the attributes for a camera frustrum based upon the shapes bounding box values.
It currently works perfectly for creating new nodes because the recomputeFrustrum function gets called when the frustrum attributes are dirtied.
When loading a maya scene containing this custom node the compute function is not called, meaning recomputeFrustrum is never called. Leaving the custom node drawing the frustrum using the default vertex array rather than using the correct attribute editor values for that custom node.
so my camera is initialized among other things with:
...
// This is required to set dirty and call compute
// when the attribute editor values are changed.
ATTRIBUTE_AFFECTS( frustrum_width, bboxCorner1 );
ATTRIBUTE_AFFECTS( frustrum_width, bboxCorner2 );
ATTRIBUTE_AFFECTS( frustrum_height, bboxCorner1 );
ATTRIBUTE_AFFECTS( frustrum_height, bboxCorner2 );
ATTRIBUTE_AFFECTS( frustrum_nearz, bboxCorner1 );
ATTRIBUTE_AFFECTS( frustrum_nearz, bboxCorner2 );
ATTRIBUTE_AFFECTS( frustrum_farz, bboxCorner1 );
ATTRIBUTE_AFFECTS( frustrum_farz, bboxCorner2 );
...
Then in the compute I have:
if( computing_plug == bboxCorner1 )
{
// Get input values from UI attributes
MDataHandle handle_w = datablock.inputValue( frustrum_width, &stat );
MDataHandle handle_h = datablock.inputValue( frustrum_height, &stat );
MDataHandle handle_n = datablock.inputValue( frustrum_nearz, &stat );
MDataHandle handle_f = datablock.inputValue( frustrum_farz, &stat );
// update bounding box co-ords
MDataHandle handle_o = datablock.outputValue( computing_plug );
handle_o.set( -(handle_w.asDouble() / 2.0), -(handle_h.asDouble() / 2.0), -handle_n.asDouble());
datablock.setClean( computing_plug );
// update camera frustrum draw co-ords
recomputeFrustrum( handle_w.asDouble(), handle_h.asDouble(), handle_n.asDouble(), handle_f.asDouble() );
stat = MS::kSuccess;
return stat;
}
else if( computing_plug == bboxCorner2 )
{
// Get input values from UI attributes
MDataHandle handle_w = datablock.inputValue( frustrum_width, &stat );
MDataHandle handle_h = datablock.inputValue( frustrum_height, &stat );
MDataHandle handle_n = datablock.inputValue( frustrum_nearz, &stat );
MDataHandle handle_f = datablock.inputValue( frustrum_farz, &stat );
// update bounding box co-ords
MDataHandle handle_o = datablock.outputValue( computing_plug );
handle_o.set( (handle_w.asDouble() / 2.0), (handle_h.asDouble() / 2.0), -handle_f.asDouble() );
datablock.setClean( computing_plug );
// update camera draw co-ords
recomputeFrustrum( handle_w.asDouble(), handle_h.asDouble(), handle_n.asDouble(), handle_f.asDouble() );
stat = MS::kSuccess;
return stat;
}
Where the recomputeFrustrum takes the input values for the frustrum attributes and uses them to create the vertex array to draw the camera frustrum.
The vertex array edited by recomputeFrustrum is then passed through to the camera geometry for drawing:
bool MyCamera::setValue( int pntInd, const MPoint & val )
{
bool result = false; MyCamera* nonConstThis = (MyCamera*)this;
MyCamera_Geom* geomPtr = nonConstThis->cachedGeom();
if ( NULL != geomPtr ) { geomPtr->vertices[ pntInd ] = val; result = true; }
childChanged( MPxSurfaceShape::kBoundingBoxChanged );
childChanged( MPxSurfaceShape::kObjectChanged );
return result; }
I call this from postConstructor and the camera draw call.
Unfortunately the postConstructor values are not correct for the frustrum attributes.
I'm assuming the attribute editor values haven't been updated for that plug until after the post constructor has completed?