Panda3D
|
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 }