Following on from this discussion, I have found that refreshing a Maya scene in a loop using the python command cmds.refresh() eventually crashes the application (it runs out of memory before the loop returns).
The problem raised in the discussion related to the creation of a nurbs boolean surface by, first, taking the difference between a large sphere and a small sphere centred on the large sphere's surface, then taking the difference of the resulting nurbs surface and a second small sphere. The DAG hierarchy for this geometry was a surfaceVarGroup, nurbsBooleanSurface1, parenting three transform nodes nurbsBooleanSurface1_1, nurbsBooleanSurface1_2 and nurbsBooleanSurface1_3, each of which parented its own shape node.
The strange thing was that while the execution of
cmds.nurbsBoolean("nurbsSphere1", "nurbsSphere2", nsf=1, op=1)
(where nurbsSphere1 was the large sphere and nurbsSphere2 was the first of the two small spheres) followed by
print(cmds.ls("nurbsBooleanSurface1_*", type="transform"))
yielded [u'nurbsBooleanSurface1_1', u'nurbsBooleanSurface1_2'] as expected, the subsequent execution of
cmds.nurbsBoolean("nurbsBooleanSurface1", "nurbsSphere3", nsf=1, op=1)
(where nurbsBooleanSurface1 was the 'single-dimple' nurbs surface resulting from the above boolean computation and nurbsSphere3 was the second of the two small spheres) followed by
print(cmds.ls("nurbsBooleanSurface1_*", type="transform"))
again yielded [u'nurbsBooleanSurface1_1', u'nurbsBooleanSurface1_2']; nurbsBooleanSurface1_3 was missing.
amorten's solution involved refreshing the scene after the second boolean computation by invoking cmds.refresh(). But as I have said, this does not work in a loop (whose number of iterations is greater than 100ish).
I have since found that nurbsBooleanSurface1_3 does not appear as a DAG node during program execution; it sort of 'pops' out at the end. The following c++ API code traverses all DAG nodes in the scene:
#include <maya/MSimple.h>
#include<maya/MGlobal.h>
#include <iostream>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MDagPath.h>
#include<maya/MObject.h>
#include<maya/MItDag.h>
#include<maya/MFnDagNode.h>
// This command iteratively computes the boolen difference between a large nurbs surface and a set of small nurbs spheres. It first
// executes the nurbs boolean (difference) command on a pair of intersecting nurbs spheres, one of radius 10 (the large sphere) and
// the other of radius 3 (a small sphere, whose centre sits on the surface of the large sphere). The result is a transform node Maya names
// nurbsBooleanSurface1, which has two children transform nodes, nurbsBooleanSurface1_1 and nurbsBooleanSurface1_2. The latter are the two
// components of the dimpled large sphere.
//
// When the nurbs boolean command is executed on nurbsBooleanSurface1 and a second small sphere of radius 3, a thrid node, nurbsBooleanSurface1_3,
// is added to the list of child nodes parented by nurbsBooleanSurface1.
//
// The problem is that nurbsBooleanSurface1_3 does not appear in the DAG during program execution.
DeclareSimpleCommand( nurbsBooleanSurface, "A test of the presence in the DAG of the child nodes of a nurbs boolean surface node", "4.0");
MStatus nurbsBooleanSurface::doIt( const MArgList& args ) {
MStatus stat = MS::kSuccess;
// Create the large sphere
MGlobal::executeCommand("sphere -r 10 -n sphere1");
// Create the first small sphere, with centre on the surface of the large sphere at (10,0,0)
MGlobal::executeCommand("sphere -r 3 -n sphere2");
MGlobal::executeCommand("setAttr \"sphere2.translateX\" 10;");
// First nurbs boolean computation
stat = MGlobal::executeCommand("nurbsBoolean -nsf 1 -op 1 sphere1 sphere2;");
// Check the boolean computation
if(stat==MS::kSuccess) {
std::cout << "Boolean computation success." << std::endl;
}
else {
displayError("Boolean computation fail.");
}
// Create the second small sphere, with centre on the surface of the nurbs boolean surface at (0,10,0)
MGlobal::executeCommand("sphere -r 3 -n sphere3");
MGlobal::executeCommand("setAttr \"sphere3.translateY\" 10;");
// Second nurbs boolean computation
stat = MGlobal::executeCommand("nurbsBoolean -nsf 1 -op 1 nurbsBooleanSurface1 sphere3;");
if(stat==MS::kSuccess) {
std::cout << "Boolean computation success." << std::endl;
}
else {
displayError("Boolean computation fail.");
}
// Use an iterator to traverse the DAG nodes
MItDag it(MItDag::kDepthFirst);
// Loop through all the DAG nodes
while(!it.isDone()) {
// Attach a function set for a DAG node to the
// object. Rather than access data directly,
// it is accessed via the function set.
MFnDagNode fn(it.currentItem());
// Get the name of the node
MString name = fn.name();
// Write the node type found
cout << "node: " << name.asChar() << endl;
// Write the info about the children
cout <<"num_children " << fn.childCount() << endl;
for(int i=0;i<fn.childCount();++i) {
// Get the MObject for the ith child
MObject child = fn.child(i);
// Attach a function set to it
MFnDagNode fnChild(child);
// Write the child name
cout << "\t" << fnChild.name().asChar();
cout << endl;
}
// Write the info about the parents
cout<<"num_parents "<< fn.parentCount() << endl;
for(int i=0;i<fn.parentCount();++i) {
// Get the MObject for the ith parent
MObject parent = fn.parent(i);
// Attach a function set to it
MFnDagNode fnParent(parent);
// Write the parent name
cout << "\t" << fnParent.name().asChar();
cout << endl;
}
// Move to next node
it.next();
}
return stat;
}
The relevant snippet in the output window is
node: nurbsBooleanSurface1
num_children 2
nurbsBooleanSurface1_1
nurbsBooleanSurface1_2
num_parents 1
world
which clearly makes no reference to the elusive nurbsBooleanSurface1_3.
So my question is, where is this node or its data stored and in what form during program execution? It must be in Maya's database somewhere.
Having worked out where it is, I'd also like to know how to access it.