Panda3D

mayaNodeTree.cxx

00001 // Filename: mayaNodeTree.cxx
00002 // Created by:  drose (06Jun03)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "mayaNodeTree.h"
00016 #include "mayaBlendDesc.h"
00017 #include "mayaEggGroupUserData.h"
00018 #include "mayaToEggConverter.h"
00019 #include "config_mayaegg.h"
00020 #include "maya_funcs.h"
00021 #include "eggGroup.h"
00022 #include "eggTable.h"
00023 #include "eggXfmSAnim.h"
00024 #include "eggSAnimData.h"
00025 #include "eggData.h"
00026 #include "eggSwitchCondition.h"
00027 #include "dcast.h"
00028 
00029 #include "pre_maya_include.h"
00030 #include <maya/MString.h>
00031 #include <maya/MItDag.h>
00032 #include <maya/MSelectionList.h>
00033 #include <maya/MGlobal.h>
00034 #include "post_maya_include.h"
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: MayaNodeTree::Constructor
00038 //       Access: Public
00039 //  Description: 
00040 ////////////////////////////////////////////////////////////////////
00041 MayaNodeTree::
00042 MayaNodeTree(MayaToEggConverter *converter) :
00043   _converter(converter)
00044 {
00045   _root = new MayaNodeDesc(this);
00046   _fps = 0.0;
00047   _egg_data = (EggData *)NULL;
00048   _egg_root = (EggGroupNode *)NULL;
00049   _skeleton_node = (EggGroupNode *)NULL;
00050   _morph_node = (EggGroupNode *)NULL;
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: MayaNodeTree::build_node
00055 //       Access: Public
00056 //  Description: Returns a pointer to the node corresponding to the
00057 //               indicated dag_path object, creating it first if
00058 //               necessary.
00059 ////////////////////////////////////////////////////////////////////
00060 MayaNodeDesc *MayaNodeTree::
00061 build_node(const MDagPath &dag_path) {
00062   MayaNodeDesc *node_desc = r_build_node(dag_path.fullPathName().asChar());
00063   node_desc->from_dag_path(dag_path, _converter);
00064   return node_desc;
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: MayaNodeTree::build_hierarchy
00069 //       Access: Public
00070 //  Description: Walks through the complete Maya hierarchy but does 
00071 //               not tag any nodes for conversion.
00072 ////////////////////////////////////////////////////////////////////
00073 bool MayaNodeTree::
00074 build_hierarchy() {
00075   MStatus status;
00076 
00077   MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
00078   if (!status) {
00079     status.perror("MItDag constructor");
00080     return false;
00081   }
00082 
00083   /*
00084     // this is how you can reset the traverser to a specific node
00085     status = dag_iterator.reset(dag_iterator.item(),MItDag::kDepthFirst, MFn::kTransform);
00086   */
00087   // Get the entire Maya scene.
00088     
00089   // This while loop walks through the entire Maya hierarchy, one
00090   // node at a time.  Maya's MItDag object automatically performs a
00091   // depth-first traversal of its scene graph.
00092   
00093   bool all_ok = true;
00094   while (!dag_iterator.isDone()) {
00095     MDagPath dag_path;
00096     status = dag_iterator.getPath(dag_path);
00097     if (!status) {
00098       status.perror("MItDag::getPath");
00099     } else {
00100       build_node(dag_path);
00101     }
00102     
00103     dag_iterator.next();
00104   }
00105 
00106   if (all_ok) {
00107     _root->check_pseudo_joints(false);
00108     _root->check_lods();
00109   }
00110   
00111   return all_ok;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: MayaNodeTree::tag_joint_all
00116 //       Access: Public
00117 //  Description: Tags the entire hierarchy for conversion.  This is
00118 //               the normal behavior.
00119 ////////////////////////////////////////////////////////////////////
00120 void MayaNodeTree::
00121 tag_joint_all() {
00122   _root->tag_joint_recursively();
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: MayaNodeTree::tag_joint_named
00127 //       Access: Public
00128 //  Description: Tags nodes matching the indicated glob (and all of
00129 //               their children) for conversion.  Returns true on
00130 //               success, false otherwise (e.g. the named node does
00131 //               not exist).
00132 ////////////////////////////////////////////////////////////////////
00133 bool MayaNodeTree::
00134 tag_joint_named(const GlobPattern &glob) {
00135   // There might be multiple nodes matching the name; search for all
00136   // of them.
00137   bool found_any = false;
00138 
00139   Nodes::iterator ni;
00140   for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
00141     MayaNodeDesc *node = (*ni);
00142     if (glob.matches(node->get_name())) {
00143       node->tag_joint_recursively();
00144       found_any = true;
00145     }
00146   }
00147 
00148   return found_any;
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: MayaNodeTree::tag_all
00153 //       Access: Public
00154 //  Description: Tags the entire hierarchy for conversion.  This is
00155 //               the normal behavior.
00156 ////////////////////////////////////////////////////////////////////
00157 void MayaNodeTree::
00158 tag_all() {
00159   _root->tag_recursively();
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: MayaNodeTree::tag_named
00164 //       Access: Public
00165 //  Description: Tags nodes matching the indicated glob (and all of
00166 //               their children) for conversion.  Returns true on
00167 //               success, false otherwise (e.g. the named node does
00168 //               not exist).
00169 ////////////////////////////////////////////////////////////////////
00170 bool MayaNodeTree::
00171 tag_named(const GlobPattern &glob) {
00172   // There might be multiple nodes matching the name; search for all
00173   // of them.
00174   bool found_any = false;
00175 
00176   Nodes::iterator ni;
00177   for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
00178     MayaNodeDesc *node = (*ni);
00179     if (glob.matches(node->get_name())) {
00180       node->tag_recursively();
00181       found_any = true;
00182     }
00183   }
00184 
00185   return found_any;
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: MayaNodeTree::untag_named
00190 //       Access: Public
00191 //  Description: Un-tags nodes matching the indicated glob (and all of
00192 //               their children) for conversion.  Returns true on
00193 //               success, false otherwise (e.g. the named node does
00194 //               not exist).
00195 ////////////////////////////////////////////////////////////////////
00196 bool MayaNodeTree::
00197 untag_named(const GlobPattern &glob) {
00198   // There might be multiple nodes matching the name; search for all
00199   // of them.
00200   bool found_any = false;
00201 
00202   Nodes::iterator ni;
00203   for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
00204     MayaNodeDesc *node = (*ni);
00205     if (glob.matches(node->get_name())) {
00206       node->untag_recursively();
00207       found_any = true;
00208     }
00209   }
00210 
00211   return found_any;
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: MayaNodeTree::tag_selected
00216 //       Access: Public
00217 //  Description: Tags the just the selected hierarchy for conversion,
00218 //               or the entire hierarchy if nothing is selected.
00219 //               Returns true on success, false on failure.
00220 ////////////////////////////////////////////////////////////////////
00221 bool MayaNodeTree::
00222 tag_selected() {
00223   MStatus status;
00224 
00225   MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
00226   if (!status) {
00227     status.perror("MItDag constructor");
00228     return false;
00229   }
00230 
00231   MSelectionList selection;
00232   status = MGlobal::getActiveSelectionList(selection);
00233   if (!status) {
00234     status.perror("MGlobal::getActiveSelectionList");
00235     return false;
00236   }
00237   
00238   if (selection.isEmpty()) {
00239     mayaegg_cat.info()
00240       << "Selection list is empty.\n";
00241     tag_all();
00242     return true;
00243   }
00244 
00245   bool all_ok = true;
00246   unsigned int length = selection.length();
00247   for (unsigned int i = 0; i < length; i++) {
00248     MDagPath root_path;
00249     status = selection.getDagPath(i, root_path);
00250     if (!status) {
00251       status.perror("MSelectionList::getDagPath");
00252     } else {
00253       // Now traverse through the selected dag path and all nested
00254       // dag paths.
00255       dag_iterator.reset(root_path);
00256       while (!dag_iterator.isDone()) {
00257         MDagPath dag_path;
00258         status = dag_iterator.getPath(dag_path);
00259         if (!status) {
00260           status.perror("MItDag::getPath");
00261         } else {
00262           build_node(dag_path)->tag();
00263         }
00264         
00265         dag_iterator.next();
00266       }
00267     }
00268   }
00269 
00270   if (all_ok) {
00271     _root->check_pseudo_joints(false);
00272   }
00273 
00274   return all_ok;
00275 }
00276 
00277 ////////////////////////////////////////////////////////////////////
00278 //     Function: MayaNodeTree::get_num_nodes
00279 //       Access: Public
00280 //  Description: Returns the total number of nodes in the hierarchy,
00281 //               not counting the root node.
00282 ////////////////////////////////////////////////////////////////////
00283 int MayaNodeTree::
00284 get_num_nodes() const {
00285   return _nodes.size();
00286 }
00287 
00288 ////////////////////////////////////////////////////////////////////
00289 //     Function: MayaNodeTree::get_node
00290 //       Access: Public
00291 //  Description: Returns the nth node in the hierarchy, in an
00292 //               arbitrary ordering.
00293 ////////////////////////////////////////////////////////////////////
00294 MayaNodeDesc *MayaNodeTree::
00295 get_node(int n) const {
00296   nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
00297   return _nodes[n];
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: MayaNodeTree::clear
00302 //       Access: Public
00303 //  Description: Resets the entire tree in preparation for
00304 //               repopulating with a new scene.
00305 ////////////////////////////////////////////////////////////////////
00306 void MayaNodeTree::
00307 clear() {
00308   _root = new MayaNodeDesc(this);
00309   _fps = 0.0;
00310   _egg_data = (EggData *)NULL;
00311   _egg_root = (EggGroupNode *)NULL;
00312   _skeleton_node = (EggGroupNode *)NULL;
00313   _morph_node = (EggGroupNode *)NULL;
00314   _nodes_by_path.clear();
00315   _nodes.clear();
00316 }
00317 
00318 ////////////////////////////////////////////////////////////////////
00319 //     Function: MayaNodeTree::clear_egg
00320 //       Access: Public
00321 //  Description: Removes all of the references to generated egg
00322 //               structures from the tree, and prepares the tree for
00323 //               generating new egg structures.
00324 ////////////////////////////////////////////////////////////////////
00325 void MayaNodeTree::
00326 clear_egg(EggData *egg_data, EggGroupNode *egg_root, 
00327           EggGroupNode *skeleton_node, EggGroupNode *morph_node) {
00328   _root->clear_egg();
00329   BlendDescs::iterator bi;
00330   for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
00331     (*bi)->clear_egg();
00332   }
00333 
00334   _egg_data = egg_data;
00335   _egg_root = egg_root;
00336   _skeleton_node = skeleton_node;
00337   _morph_node = morph_node;
00338 }
00339 
00340 ////////////////////////////////////////////////////////////////////
00341 //     Function: MayaNodeTree::get_egg_group
00342 //       Access: Public
00343 //  Description: Returns the EggGroupNode corresponding to the group
00344 //               or joint for the indicated node.  Creates the group
00345 //               node if it has not already been created.
00346 ////////////////////////////////////////////////////////////////////
00347 EggGroup *MayaNodeTree::
00348 get_egg_group(MayaNodeDesc *node_desc) {
00349   nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
00350 
00351   if (node_desc->_egg_group == (EggGroup *)NULL) {
00352     // We need to make a new group node.
00353     EggGroup *egg_group;
00354 
00355     nassertr(node_desc->_parent != (MayaNodeDesc *)NULL, NULL);
00356     egg_group = new EggGroup(node_desc->get_name());
00357     if (node_desc->is_joint()) {
00358       if (_converter->get_animation_convert() == AC_model ||
00359           _converter->get_animation_convert() == AC_both) {
00360         egg_group->set_group_type(EggGroup::GT_joint);
00361       }
00362     }
00363 
00364     MayaEggGroupUserData *parent_user_data = NULL;
00365 
00366     if (node_desc->_parent == _root) {
00367       // The parent is the root.
00368       _egg_root->add_child(egg_group);
00369 
00370     } else {
00371       // The parent is another node.
00372       EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
00373       parent_egg_group->add_child(egg_group);
00374 
00375       if (parent_egg_group->has_user_data()) {
00376         DCAST_INTO_R(parent_user_data, parent_egg_group->get_user_data(), NULL);
00377       }
00378     }
00379 
00380     if (node_desc->has_dag_path()) {
00381       // Check for an object type setting, from Oliver's plug-in.
00382       MObject dag_object = node_desc->get_dag_path().node();
00383       string object_type;
00384       LVector3d value;
00385       if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
00386         egg_group->add_object_type(object_type);
00387       }
00388       if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
00389         egg_group->add_object_type(object_type);
00390       }
00391       if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
00392         egg_group->add_object_type(object_type);
00393       }
00394 
00395       if(has_attribute(dag_object, "scrollUV")) {
00396         if(get_vec3d_attribute(dag_object, "scrollUV", value)) {
00397           egg_group->set_scroll_u(value[0]);
00398           egg_group->set_scroll_v(value[1]);
00399           egg_group->set_scroll_r(value[2]);
00400         }
00401       }
00402 
00403       pvector<string> tag_attribute_names;
00404       get_tag_attribute_names(dag_object, tag_attribute_names);
00405       for (uint ti=0; ti < tag_attribute_names.size(); ti++) {
00406         if (get_enum_attribute(dag_object, tag_attribute_names[ti], object_type)) {
00407           egg_group->set_tag(tag_attribute_names[ti].substr(3), object_type);
00408         }
00409       }
00410 
00411       // Is the node flagged to be invisible?  If it is, it is tagged
00412       // with the "hidden" visibility flag, so it won't get converted
00413       // in the normal case (unless it represents a collision solid or
00414       // something).
00415       bool visible = true;
00416       get_bool_attribute(dag_object, "visibility", visible);
00417       if (!visible && egg_group->get_num_object_types() == 0) {
00418         egg_group->set_visibility_mode(EggGroup::VM_hidden);
00419       }
00420 
00421       // We treat the object type "billboard" as a special case: we
00422       // apply this one right away and also flag the group as an
00423       // instance.
00424       if (egg_group->has_object_type("billboard")) {    
00425         egg_group->remove_object_type("billboard");
00426         egg_group->set_group_type(EggGroup::GT_instance);
00427         egg_group->set_billboard_type(EggGroup::BT_axis);
00428         
00429       } else if (egg_group->has_object_type("billboard-point")) {
00430         egg_group->remove_object_type("billboard-point");
00431         egg_group->set_group_type(EggGroup::GT_instance);
00432         egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
00433         
00434       } else if (egg_group->has_object_type("bbpoint")) {
00435         egg_group->remove_object_type("bbpoint");
00436         egg_group->set_group_type(EggGroup::GT_instance);
00437         egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
00438       }
00439       
00440       // We also treat the object type "dcs" and "model" as a special
00441       // case, so we can test for these flags later.
00442       if (egg_group->has_object_type("dcs")) {
00443         egg_group->remove_object_type("dcs");
00444         egg_group->set_dcs_type(EggGroup::DC_default);
00445       }
00446       if (egg_group->has_object_type("model")) {
00447         egg_group->remove_object_type("model");
00448         egg_group->set_model_flag(true);
00449       }
00450       
00451       // And "vertex-color" and "double-sided" have meaning only to
00452       // this converter.
00453       MayaEggGroupUserData *user_data;
00454       if (parent_user_data == (MayaEggGroupUserData *)NULL) {
00455         user_data = new MayaEggGroupUserData;
00456       } else {
00457         // Inherit the flags from above.
00458         user_data = new MayaEggGroupUserData(*parent_user_data);
00459       }
00460 
00461       if (egg_group->has_object_type("vertex-color")) {
00462         egg_group->remove_object_type("vertex-color");
00463         user_data->_vertex_color = true;
00464       }
00465       if (egg_group->has_object_type("double-sided")) {
00466         egg_group->remove_object_type("double-sided");
00467         user_data->_double_sided = true;
00468       }
00469       egg_group->set_user_data(user_data);
00470     }
00471 
00472     if (node_desc->_is_lod) {
00473       // Create an LOD specification.
00474       egg_group->set_lod(EggSwitchConditionDistance(node_desc->_switch_in,
00475                                                     node_desc->_switch_out,
00476                                                     LPoint3d::zero()));
00477     }
00478 
00479     node_desc->_egg_group = egg_group;
00480   }
00481 
00482   return node_desc->_egg_group;
00483 }
00484 
00485 ////////////////////////////////////////////////////////////////////
00486 //     Function: MayaNodeTree::get_egg_table
00487 //       Access: Public
00488 //  Description: Returns the EggTable corresponding to the joint
00489 //               for the indicated node.  Creates the table node if it
00490 //               has not already been created.
00491 ////////////////////////////////////////////////////////////////////
00492 EggTable *MayaNodeTree::
00493 get_egg_table(MayaNodeDesc *node_desc) {
00494   nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
00495   nassertr(node_desc->is_joint(), NULL);
00496 
00497   if (node_desc->_egg_table == (EggTable *)NULL) {
00498     // We need to make a new table node.
00499     nassertr(node_desc->_parent != (MayaNodeDesc *)NULL, NULL);
00500 
00501     EggTable *egg_table = new EggTable(node_desc->get_name());
00502     node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
00503     node_desc->_anim->set_fps(_fps);
00504     egg_table->add_child(node_desc->_anim);
00505 
00506     if (!node_desc->_parent->is_joint()) {
00507       // The parent is not a joint; put it at the top.
00508       _skeleton_node->add_child(egg_table);
00509 
00510     } else {
00511       // The parent is another joint.
00512       EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
00513       parent_egg_table->add_child(egg_table);
00514     }
00515 
00516     node_desc->_egg_table = egg_table;
00517   }
00518 
00519   return node_desc->_egg_table;
00520 }
00521 
00522 ////////////////////////////////////////////////////////////////////
00523 //     Function: MayaNodeTree::get_egg_anim
00524 //       Access: Public
00525 //  Description: Returns the anim table corresponding to the joint
00526 //               for the indicated node.  Creates the table node if it
00527 //               has not already been created.
00528 ////////////////////////////////////////////////////////////////////
00529 EggXfmSAnim *MayaNodeTree::
00530 get_egg_anim(MayaNodeDesc *node_desc) {
00531   get_egg_table(node_desc);
00532   return node_desc->_anim;
00533 }
00534 
00535 ////////////////////////////////////////////////////////////////////
00536 //     Function: MayaNodeTree::get_egg_slider
00537 //       Access: Public
00538 //  Description: Returns the anim table corresponding to the slider
00539 //               for the indicated blend.  Creates the table node if it
00540 //               has not already been created.
00541 ////////////////////////////////////////////////////////////////////
00542 EggSAnimData *MayaNodeTree::
00543 get_egg_slider(MayaBlendDesc *blend_desc) {
00544   nassertr(_morph_node != (EggGroupNode *)NULL, NULL);
00545 
00546   if (blend_desc->_anim == (EggSAnimData *)NULL) {
00547     // We need to make a new anim table.
00548     EggSAnimData *egg_anim = new EggSAnimData(blend_desc->get_name());
00549     egg_anim->set_fps(_fps);
00550     _morph_node->add_child(egg_anim);
00551 
00552     blend_desc->_anim = egg_anim;
00553   }
00554 
00555   return blend_desc->_anim;
00556 }
00557 
00558 ////////////////////////////////////////////////////////////////////
00559 //     Function: MayaNodeTree::ignore_slider
00560 //       Access: Public
00561 //  Description: Returns true if the indicated name is on the list of
00562 //               sliders to ignore, false otherwise.
00563 ////////////////////////////////////////////////////////////////////
00564 bool MayaNodeTree::
00565 ignore_slider(const string &name) const {
00566   return _converter->ignore_slider(name);
00567 }
00568 
00569 ////////////////////////////////////////////////////////////////////
00570 //     Function: MayaNodeTree::report_ignored_slider
00571 //       Access: Public
00572 //  Description: Outputs a message to the user reporting that a slider
00573 //               was ignored.  Each slider is only reported once.
00574 ////////////////////////////////////////////////////////////////////
00575 void MayaNodeTree::
00576 report_ignored_slider(const string &name) {
00577   if (_ignored_slider_names.insert(name).second) {
00578     mayaegg_cat.info()
00579       << "Ignoring slider " << name << "\n";
00580   }
00581 }
00582 
00583 ////////////////////////////////////////////////////////////////////
00584 //     Function: MayaNodeTree::add_blend_desc
00585 //       Access: Public
00586 //  Description: Adds the indicated MayaBlendDesc object to the list
00587 //               of blends collected so far.  If a MayaBlendDesc
00588 //               object with the same name is already part of the
00589 //               tree, the supplied object is discarded and the
00590 //               previously-added object is returned; otherwise, the
00591 //               supplied object is added to the tree and the same
00592 //               object is returned.
00593 //
00594 //               In either case, the return value is the MayaBlendDesc
00595 //               that should be used henceforth.
00596 ////////////////////////////////////////////////////////////////////
00597 MayaBlendDesc *MayaNodeTree::
00598 add_blend_desc(MayaBlendDesc *blend_desc) {
00599   BlendDescs::iterator bi = _blend_descs.insert(blend_desc).first;
00600 
00601   return (*bi);
00602 }
00603 
00604 ////////////////////////////////////////////////////////////////////
00605 //     Function: MayaNodeTree::get_num_blend_descs
00606 //       Access: Public
00607 //  Description: Returns the number of unique MayaBlendDesc objects
00608 //               (and hence the number of morph sliders) discovered in
00609 //               the tree.
00610 ////////////////////////////////////////////////////////////////////
00611 int MayaNodeTree::
00612 get_num_blend_descs() const {
00613   return _blend_descs.size();
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: MayaNodeTree::get_blend_desc
00618 //       Access: Public
00619 //  Description: Returns the nth MayaBlendDesc object discovered in
00620 //               the tree.
00621 ////////////////////////////////////////////////////////////////////
00622 MayaBlendDesc *MayaNodeTree::
00623 get_blend_desc(int n) const {
00624   nassertr(n >= 0 && n < (int)_blend_descs.size(), NULL);
00625   return _blend_descs[n];
00626 }
00627 
00628 ////////////////////////////////////////////////////////////////////
00629 //     Function: MayaNodeTree::reset_sliders
00630 //       Access: Public
00631 //  Description: Resets all of the sliders associated with all blend
00632 //               shapes down to 0.
00633 ////////////////////////////////////////////////////////////////////
00634 void MayaNodeTree::
00635 reset_sliders() {
00636   BlendDescs::iterator bi;
00637   for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
00638     (*bi)->set_slider(0.0);
00639   }
00640 }
00641 
00642 
00643 ////////////////////////////////////////////////////////////////////
00644 //     Function: MayaNodeTree::r_build_node
00645 //       Access: Private
00646 //  Description: The recursive implementation of build_node().
00647 ////////////////////////////////////////////////////////////////////
00648 MayaNodeDesc *MayaNodeTree::
00649 r_build_node(const string &path) {
00650   // If we have already encountered this pathname, return the
00651   // corresponding MayaNodeDesc immediately.
00652   NodesByPath::const_iterator ni = _nodes_by_path.find(path);
00653   if (ni != _nodes_by_path.end()) {
00654     return (*ni).second;
00655   }
00656 
00657   // Otherwise, we have to create it.  Do this recursively, so we
00658   // create each node along the path.
00659   MayaNodeDesc *node_desc;
00660 
00661   //mayaegg_cat.info() << "path: " << path << endl;
00662   if (path.empty()) {
00663     // This is the top.
00664     //mayaegg_cat.info() << "found empty path: " << path << endl;
00665     node_desc = _root;
00666 
00667   } else {
00668     // Maya uses vertical bars to separate path components.  Remove
00669     // everything from the rightmost bar on; this will give us the
00670     // parent's path name.
00671     size_t bar = path.rfind("|");
00672     string parent_path, local_name;
00673     if (bar != string::npos) {
00674       parent_path = path.substr(0, bar);
00675       //mayaegg_cat.info() << "parent_path: " << parent_path << endl;
00676       local_name = path.substr(bar + 1);
00677       if (local_name == _subroot_parent_name) {
00678         node_desc = _root;
00679       }
00680     } else {
00681       local_name = path;
00682     }
00683     //mayaegg_cat.info() << "local_name: " << local_name << endl;
00684 
00685     if (node_desc != _root) {
00686       MayaNodeDesc *parent_node_desc = r_build_node(parent_path);
00687       if (parent_node_desc == (MayaNodeDesc *)NULL)
00688         mayaegg_cat.info() << "empty parent: " << local_name << endl;
00689       node_desc = new MayaNodeDesc(this, parent_node_desc, local_name);
00690       _nodes.push_back(node_desc);
00691     }
00692   }
00693 
00694   _nodes_by_path.insert(NodesByPath::value_type(path, node_desc));
00695   return node_desc;
00696 }
 All Classes Functions Variables Enumerations