23 #include <maya/MFnBlendShapeDeformer.h>
24 #include <maya/MItDependencyGraph.h>
25 #include <maya/MFnNurbsSurface.h>
26 #include <maya/MFnMesh.h>
34 static const char *transform_connections[] = {
44 static const int num_transform_connections =
sizeof(transform_connections) /
sizeof(
const char *);
59 _joint_type = JT_none;
62 _joint_tagged =
false;
65 if (_parent !=
nullptr) {
66 _parent->_children.push_back(
this);
75 if (_dag_path !=
nullptr) {
87 if (_dag_path ==
nullptr) {
88 _dag_path =
new MDagPath(dag_path);
91 MFnDagNode dag_node(dag_path, &status);
93 status.perror(
"MFnDagNode constructor");
95 name = dag_node.name().asChar();
98 if (_dag_path->hasFn(MFn::kJoint) || converter->
force_joint(name)) {
101 _joint_type = JT_joint;
102 if (_parent !=
nullptr) {
103 _parent->mark_joint_parent();
109 bool transform_connected =
false;
112 MObject node = dag_path.node(&status);
115 i < num_transform_connections && !transform_connected;
118 transform_connected =
true;
123 if (transform_connected) {
124 _joint_type = JT_joint;
125 if (_parent !=
nullptr) {
126 _parent->mark_joint_parent();
131 if (dag_path.hasFn(MFn::kNurbsSurface)) {
132 MFnNurbsSurface surface(dag_path, &status);
134 check_blend_shapes(surface,
"create");
136 }
else if (dag_path.hasFn(MFn::kMesh)) {
137 MFnMesh mesh(dag_path, &status);
139 check_blend_shapes(mesh,
"inMesh");
151 return (_dag_path !=
nullptr);
160 nassertr(_dag_path !=
nullptr, *_dag_path);
170 return _blend_descs.size();
179 nassertr(n >= 0 && n < (
int)_blend_descs.size(),
nullptr);
180 return _blend_descs[n];
189 return _joint_tagged && (_joint_type == JT_joint || _joint_type == JT_pseudo_joint);
197 return _joint_type == JT_joint_parent;
207 return _joint_tagged;
215 _joint_tagged =
true;
222 tag_joint_recursively() {
223 _joint_tagged =
true;
225 Children::const_iterator ci;
226 for (ci = _children.begin(); ci != _children.end(); ++ci) {
228 child->tag_joint_recursively();
263 Children::const_iterator ci;
264 for (ci = _children.begin(); ci != _children.end(); ++ci) {
266 child->tag_recursively();
274 untag_recursively() {
277 Children::const_iterator ci;
278 for (ci = _children.begin(); ci != _children.end(); ++ci) {
280 child->untag_recursively();
291 if ((_egg_group !=
nullptr)
295 if (_parent !=
nullptr) {
306 _egg_group =
nullptr;
307 _egg_table =
nullptr;
310 Children::const_iterator ci;
311 for (ci = _children.begin(); ci != _children.end(); ++ci) {
322 mark_joint_parent() {
323 if (_joint_type == JT_none) {
324 _joint_type = JT_joint_parent;
325 if (_parent !=
nullptr) {
326 _parent->mark_joint_parent();
337 check_pseudo_joints(
bool joint_above) {
338 static uint32_t space_count = 0;
340 for (uint32_t idx=0; idx<space_count; ++idx) {
343 if (mayaegg_cat.is_spam()) {
344 mayaegg_cat.spam() <<
"cpj:" << space << get_name() <<
" joint_type: " << _joint_type << std::endl;
346 if (_joint_type == JT_joint_parent && joint_above) {
349 _joint_type = JT_pseudo_joint;
352 if (_joint_type == JT_joint) {
360 if (_joint_type != JT_none) {
362 bool any_joints =
false;
363 Children::const_iterator ci;
364 for (ci = _children.begin(); ci != _children.end(); ++ci) {
366 if (mayaegg_cat.is_spam()) {
369 child->check_pseudo_joints(joint_above);
371 if (child->_joint_type == JT_joint || child->_joint_type == JT_pseudo_joint) {
379 bool all_joints =
true;
380 for (ci = _children.begin(); ci != _children.end(); ++ci) {
385 status.perror(
"MFnDagNode constructor");
387 string type_name = dag_node.typeName().asChar();
388 if (child->_joint_type == JT_joint_parent) {
389 child->_joint_type = JT_pseudo_joint;
390 }
else if (child->_joint_type == JT_none) {
391 if (mayaegg_cat.is_spam()) {
392 mayaegg_cat.spam() <<
"cpj: " << space <<
"jt_none for " << child->get_name() << std::endl;
394 if (type_name.find(
"transform") == string::npos) {
395 if (mayaegg_cat.is_spam()) {
396 mayaegg_cat.spam() <<
"cpj: " << space <<
"all_joints false for " << get_name() << std::endl;
405 if (_joint_type == JT_joint_parent) {
406 if (!get_name().empty()) {
407 _joint_type = JT_pseudo_joint;
413 if (mayaegg_cat.is_spam()) {
428 check_blend_shapes(
const MFnDagNode &node,
const string &attrib_name) {
431 MObject attr = node.attribute(attrib_name.c_str());
433 MPlug history(node.object(), attr);
434 MItDependencyGraph it(history, MFn::kDependencyNode,
435 MItDependencyGraph::kUpstream,
436 MItDependencyGraph::kDepthFirst,
437 MItDependencyGraph::kNodeLevel);
439 while (!it.isDone()) {
440 MObject c_node = it.thisNode();
442 if (c_node.hasFn(MFn::kBlendShape)) {
443 MFnBlendShapeDeformer blends(c_node, &status);
445 status.perror(
"MFnBlendShapeDeformer constructor");
451 MPlug plug = blends.findPlug(
"pb");
452 bool is_parallel_blender;
453 status = plug.getValue(is_parallel_blender);
455 status.perror(
"Could not get value of pb plug.");
456 is_parallel_blender =
false;
459 if (is_parallel_blender ||
464 MObjectArray base_objects;
465 status = blends.getBaseObjects(base_objects);
467 status.perror(
"MFnBlendShapeDeformer::getBaseObjects");
469 for (
unsigned int oi = 0; oi < base_objects.length(); oi++) {
470 MObject base_object = base_objects[oi];
472 MIntArray index_list;
473 status = blends.weightIndexList(index_list);
475 status.perror(
"MFnBlendShapeDeformer::weightIndexList");
477 for (
unsigned int i = 0; i < index_list.length(); i++) {
478 int wi = index_list[i];
481 _blend_descs.push_back(blend_desc);
504 Children::iterator ci;
505 for (ci = _children.begin(); ci != _children.end(); ++ci) {
511 if (_dag_path !=
nullptr &&
512 _dag_path->hasFn(MFn::kLodGroup)) {
515 MFnDagNode dag_node(*_dag_path, &status);
517 status.perror(
"Couldn't get node from dag path for lodGroup");
521 MPlug plug = dag_node.findPlug(
"threshold", &status);
523 status.perror(
"Couldn't get threshold attributes on lodGroup");
529 unsigned int num_elements = plug.numElements();
530 unsigned int num_children = _children.size();
531 if (num_elements + 1 != num_children) {
532 mayaegg_cat.warning()
533 <<
"Node " << get_name() <<
" has " << num_elements
534 <<
" LOD entries, but " << num_children <<
" children.\n";
541 double switch_out = 0.0;
543 while (i < num_elements && i < num_children) {
544 MPlug element = plug.elementByLogicalIndex(i);
548 status = element.getValue(switch_in);
550 status.perror(
"Couldn't get double value from threshold.");
554 child->_is_lod =
true;
555 child->_switch_in = switch_in;
556 child->_switch_out = switch_out;
558 switch_out = switch_in;
562 while (i < num_children) {
567 child->_is_lod =
true;
568 child->_switch_in = switch_out * 4.0;
569 child->_switch_out = switch_out;