Panda3D
mayaNodeTree.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file mayaNodeTree.cxx
10  * @author drose
11  * @date 2003-06-06
12  */
13 
14 #include "mayaNodeTree.h"
15 #include "mayaBlendDesc.h"
16 #include "mayaEggGroupUserData.h"
17 #include "mayaToEggConverter.h"
18 #include "config_mayaegg.h"
19 #include "maya_funcs.h"
20 #include "eggGroup.h"
21 #include "eggTable.h"
22 #include "eggXfmSAnim.h"
23 #include "eggSAnimData.h"
24 #include "eggData.h"
25 #include "eggSwitchCondition.h"
26 #include "dcast.h"
27 
28 #include "pre_maya_include.h"
29 #include <maya/MString.h>
30 #include <maya/MItDag.h>
31 #include <maya/MSelectionList.h>
32 #include <maya/MGlobal.h>
33 #include "post_maya_include.h"
34 
35 using std::string;
36 
37 /**
38  *
39  */
40 MayaNodeTree::
41 MayaNodeTree(MayaToEggConverter *converter) :
42  _converter(converter)
43 {
44  _root = new MayaNodeDesc(this);
45  _fps = 0.0;
46  _egg_data = nullptr;
47  _egg_root = nullptr;
48  _skeleton_node = nullptr;
49  _morph_node = nullptr;
50 }
51 
52 /**
53  * Returns a pointer to the node corresponding to the indicated dag_path
54  * object, creating it first if necessary.
55  */
57 build_node(const MDagPath &dag_path) {
58  MayaNodeDesc *node_desc = r_build_node(dag_path.fullPathName().asChar());
59  node_desc->from_dag_path(dag_path, _converter);
60  return node_desc;
61 }
62 
63 /**
64  * Walks through the complete Maya hierarchy but does not tag any nodes for
65  * conversion.
66  */
67 bool MayaNodeTree::
69  MStatus status;
70 
71  MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
72  if (!status) {
73  status.perror("MItDag constructor");
74  return false;
75  }
76 
77  /*
78  // this is how you can reset the traverser to a specific node
79  status = dag_iterator.reset(dag_iterator.item(),MItDag::kDepthFirst, MFn::kTransform);
80  */
81  // Get the entire Maya scene.
82 
83  // This while loop walks through the entire Maya hierarchy, one node at a
84  // time. Maya's MItDag object automatically performs a depth-first
85  // traversal of its scene graph.
86 
87  bool all_ok = true;
88  while (!dag_iterator.isDone()) {
89  MDagPath dag_path;
90  status = dag_iterator.getPath(dag_path);
91  if (!status) {
92  status.perror("MItDag::getPath");
93  } else {
94  build_node(dag_path);
95  }
96 
97  dag_iterator.next();
98  }
99 
100  if (all_ok) {
101  _root->check_pseudo_joints(false);
102  _root->check_lods();
103  }
104 
105  return all_ok;
106 }
107 
108 /**
109  * Tags the entire hierarchy for conversion. This is the normal behavior.
110  */
111 void MayaNodeTree::
113  _root->tag_joint_recursively();
114 }
115 
116 /**
117  * Tags nodes matching the indicated glob (and all of their children) for
118  * conversion. Returns true on success, false otherwise (e.g. the named node
119  * does not exist).
120  */
121 bool MayaNodeTree::
123  // There might be multiple nodes matching the name; search for all of them.
124  bool found_any = false;
125 
126  Nodes::iterator ni;
127  for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
128  MayaNodeDesc *node = (*ni);
129  if (glob.matches(node->get_name())) {
130  node->tag_joint_recursively();
131  found_any = true;
132  }
133  }
134 
135  return found_any;
136 }
137 
138 /**
139  * Tags the entire hierarchy for conversion. This is the normal behavior.
140  */
141 void MayaNodeTree::
143  _root->tag_recursively();
144 }
145 
146 /**
147  * Tags nodes matching the indicated glob (and all of their children) for
148  * conversion. Returns true on success, false otherwise (e.g. the named node
149  * does not exist).
150  */
151 bool MayaNodeTree::
152 tag_named(const GlobPattern &glob) {
153  // There might be multiple nodes matching the name; search for all of them.
154  bool found_any = false;
155 
156  Nodes::iterator ni;
157  for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
158  MayaNodeDesc *node = (*ni);
159  if (glob.matches(node->get_name())) {
160  node->tag_recursively();
161  found_any = true;
162  }
163  }
164 
165  return found_any;
166 }
167 
168 /**
169  * Un-tags nodes matching the indicated glob (and all of their children) for
170  * conversion. Returns true on success, false otherwise (e.g. the named node
171  * does not exist).
172  */
173 bool MayaNodeTree::
174 untag_named(const GlobPattern &glob) {
175  // There might be multiple nodes matching the name; search for all of them.
176  bool found_any = false;
177 
178  Nodes::iterator ni;
179  for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) {
180  MayaNodeDesc *node = (*ni);
181  if (glob.matches(node->get_name())) {
182  node->untag_recursively();
183  found_any = true;
184  }
185  }
186 
187  return found_any;
188 }
189 
190 /**
191  * Tags the just the selected hierarchy for conversion, or the entire
192  * hierarchy if nothing is selected. Returns true on success, false on
193  * failure.
194  */
195 bool MayaNodeTree::
197  MStatus status;
198 
199  MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
200  if (!status) {
201  status.perror("MItDag constructor");
202  return false;
203  }
204 
205  MSelectionList selection;
206  status = MGlobal::getActiveSelectionList(selection);
207  if (!status) {
208  status.perror("MGlobal::getActiveSelectionList");
209  return false;
210  }
211 
212  if (selection.isEmpty()) {
213  mayaegg_cat.info()
214  << "Selection list is empty.\n";
215  tag_all();
216  return true;
217  }
218 
219  bool all_ok = true;
220  unsigned int length = selection.length();
221  for (unsigned int i = 0; i < length; i++) {
222  MDagPath root_path;
223  status = selection.getDagPath(i, root_path);
224  if (!status) {
225  status.perror("MSelectionList::getDagPath");
226  } else {
227  // Now traverse through the selected dag path and all nested dag paths.
228  dag_iterator.reset(root_path);
229  while (!dag_iterator.isDone()) {
230  MDagPath dag_path;
231  status = dag_iterator.getPath(dag_path);
232  if (!status) {
233  status.perror("MItDag::getPath");
234  } else {
235  build_node(dag_path)->tag();
236  }
237 
238  dag_iterator.next();
239  }
240  }
241  }
242 
243  if (all_ok) {
244  _root->check_pseudo_joints(false);
245  }
246 
247  return all_ok;
248 }
249 
250 /**
251  * Returns the total number of nodes in the hierarchy, not counting the root
252  * node.
253  */
254 int MayaNodeTree::
255 get_num_nodes() const {
256  return _nodes.size();
257 }
258 
259 /**
260  * Returns the nth node in the hierarchy, in an arbitrary ordering.
261  */
263 get_node(int n) const {
264  nassertr(n >= 0 && n < (int)_nodes.size(), nullptr);
265  return _nodes[n];
266 }
267 
268 /**
269  * Resets the entire tree in preparation for repopulating with a new scene.
270  */
271 void MayaNodeTree::
272 clear() {
273  _root = new MayaNodeDesc(this);
274  _fps = 0.0;
275  _egg_data = nullptr;
276  _egg_root = nullptr;
277  _skeleton_node = nullptr;
278  _morph_node = nullptr;
279  _nodes_by_path.clear();
280  _nodes.clear();
281 }
282 
283 /**
284  * Removes all of the references to generated egg structures from the tree,
285  * and prepares the tree for generating new egg structures.
286  */
287 void MayaNodeTree::
288 clear_egg(EggData *egg_data, EggGroupNode *egg_root,
289  EggGroupNode *skeleton_node, EggGroupNode *morph_node) {
290  _root->clear_egg();
291  BlendDescs::iterator bi;
292  for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
293  (*bi)->clear_egg();
294  }
295 
296  _egg_data = egg_data;
297  _egg_root = egg_root;
298  _skeleton_node = skeleton_node;
299  _morph_node = morph_node;
300 }
301 
302 /**
303  * Returns the EggGroupNode corresponding to the group or joint for the
304  * indicated node. Creates the group node if it has not already been created.
305  */
308  nassertr(_egg_root != nullptr, nullptr);
309 
310  if (node_desc->_egg_group == nullptr) {
311  // We need to make a new group node.
312  EggGroup *egg_group;
313 
314  nassertr(node_desc->_parent != nullptr, nullptr);
315  egg_group = new EggGroup(node_desc->get_name());
316  if (node_desc->is_joint()) {
317  if (_converter->get_animation_convert() == AC_model ||
318  _converter->get_animation_convert() == AC_both) {
319  egg_group->set_group_type(EggGroup::GT_joint);
320  }
321  }
322 
323  MayaEggGroupUserData *parent_user_data = nullptr;
324 
325  if (node_desc->_parent == _root) {
326  // The parent is the root.
327  _egg_root->add_child(egg_group);
328 
329  } else {
330  // The parent is another node.
331  EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
332  parent_egg_group->add_child(egg_group);
333 
334  if (parent_egg_group->has_user_data()) {
335  DCAST_INTO_R(parent_user_data, parent_egg_group->get_user_data(), nullptr);
336  }
337  }
338 
339  if (node_desc->has_dag_path()) {
340  // Check for an object type setting, from Oliver's plug-in.
341  MObject dag_object = node_desc->get_dag_path().node();
342  string object_type;
343  LVector3d value;
344  if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
345  egg_group->add_object_type(object_type);
346  }
347  if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
348  egg_group->add_object_type(object_type);
349  }
350  if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
351  egg_group->add_object_type(object_type);
352  }
353 
354  if(has_attribute(dag_object, "scrollUV")) {
355  if(get_vec3d_attribute(dag_object, "scrollUV", value)) {
356  egg_group->set_scroll_u(value[0]);
357  egg_group->set_scroll_v(value[1]);
358  egg_group->set_scroll_r(value[2]);
359  }
360  }
361 
362  pvector<string> tag_attribute_names;
363  get_tag_attribute_names(dag_object, tag_attribute_names);
364  for (uint ti=0; ti < tag_attribute_names.size(); ti++) {
365  if (get_enum_attribute(dag_object, tag_attribute_names[ti], object_type)) {
366  egg_group->set_tag(tag_attribute_names[ti].substr(3), object_type);
367  }
368  }
369 
370  // Is the node flagged to be invisible? If it is, it is tagged with the
371  // "hidden" visibility flag, so it won't get converted in the normal
372  // case (unless it represents a collision solid or something).
373  bool visible = true;
374  get_bool_attribute(dag_object, "visibility", visible);
375  if (!visible && egg_group->get_num_object_types() == 0) {
376  egg_group->set_visibility_mode(EggGroup::VM_hidden);
377  }
378 
379  // We treat the object type "billboard" as a special case: we apply this
380  // one right away and also flag the group as an instance.
381  if (egg_group->has_object_type("billboard")) {
382  egg_group->remove_object_type("billboard");
383  egg_group->set_group_type(EggGroup::GT_instance);
384  egg_group->set_billboard_type(EggGroup::BT_axis);
385 
386  } else if (egg_group->has_object_type("billboard-point")) {
387  egg_group->remove_object_type("billboard-point");
388  egg_group->set_group_type(EggGroup::GT_instance);
389  egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
390 
391  } else if (egg_group->has_object_type("bbpoint")) {
392  egg_group->remove_object_type("bbpoint");
393  egg_group->set_group_type(EggGroup::GT_instance);
394  egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
395  }
396 
397  // We also treat the object type "dcs" and "model" as a special case, so
398  // we can test for these flags later.
399  if (egg_group->has_object_type("dcs")) {
400  egg_group->remove_object_type("dcs");
401  egg_group->set_dcs_type(EggGroup::DC_default);
402  }
403  if (egg_group->has_object_type("model")) {
404  egg_group->remove_object_type("model");
405  egg_group->set_model_flag(true);
406  }
407 
408  // And "vertex-color" and "double-sided" have meaning only to this
409  // converter.
410  MayaEggGroupUserData *user_data;
411  if (parent_user_data == nullptr) {
412  user_data = new MayaEggGroupUserData;
413  } else {
414  // Inherit the flags from above.
415  user_data = new MayaEggGroupUserData(*parent_user_data);
416  }
417 
418  if (egg_group->has_object_type("vertex-color")) {
419  egg_group->remove_object_type("vertex-color");
420  user_data->_vertex_color = true;
421  }
422  if (egg_group->has_object_type("double-sided")) {
423  egg_group->remove_object_type("double-sided");
424  user_data->_double_sided = true;
425  }
426  egg_group->set_user_data(user_data);
427  }
428 
429  if (node_desc->_is_lod) {
430  // Create an LOD specification.
431  egg_group->set_lod(EggSwitchConditionDistance(node_desc->_switch_in,
432  node_desc->_switch_out,
433  LPoint3d::zero()));
434  }
435 
436  node_desc->_egg_group = egg_group;
437  }
438 
439  return node_desc->_egg_group;
440 }
441 
442 /**
443  * Returns the EggTable corresponding to the joint for the indicated node.
444  * Creates the table node if it has not already been created.
445  */
448  nassertr(_skeleton_node != nullptr, nullptr);
449  nassertr(node_desc->is_joint(), nullptr);
450 
451  if (node_desc->_egg_table == nullptr) {
452  // We need to make a new table node.
453  nassertr(node_desc->_parent != nullptr, nullptr);
454 
455  EggTable *egg_table = new EggTable(node_desc->get_name());
456  node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
457  node_desc->_anim->set_fps(_fps);
458  egg_table->add_child(node_desc->_anim);
459 
460  if (!node_desc->_parent->is_joint()) {
461  // The parent is not a joint; put it at the top.
462  _skeleton_node->add_child(egg_table);
463 
464  } else {
465  // The parent is another joint.
466  EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
467  parent_egg_table->add_child(egg_table);
468  }
469 
470  node_desc->_egg_table = egg_table;
471  }
472 
473  return node_desc->_egg_table;
474 }
475 
476 /**
477  * Returns the anim table corresponding to the joint for the indicated node.
478  * Creates the table node if it has not already been created.
479  */
482  get_egg_table(node_desc);
483  return node_desc->_anim;
484 }
485 
486 /**
487  * Returns the anim table corresponding to the slider for the indicated blend.
488  * Creates the table node if it has not already been created.
489  */
492  nassertr(_morph_node != nullptr, nullptr);
493 
494  if (blend_desc->_anim == nullptr) {
495  // We need to make a new anim table.
496  EggSAnimData *egg_anim = new EggSAnimData(blend_desc->get_name());
497  egg_anim->set_fps(_fps);
498  _morph_node->add_child(egg_anim);
499 
500  blend_desc->_anim = egg_anim;
501  }
502 
503  return blend_desc->_anim;
504 }
505 
506 /**
507  * Returns true if the indicated name is on the list of sliders to ignore,
508  * false otherwise.
509  */
510 bool MayaNodeTree::
511 ignore_slider(const string &name) const {
512  return _converter->ignore_slider(name);
513 }
514 
515 /**
516  * Outputs a message to the user reporting that a slider was ignored. Each
517  * slider is only reported once.
518  */
519 void MayaNodeTree::
520 report_ignored_slider(const string &name) {
521  if (_ignored_slider_names.insert(name).second) {
522  mayaegg_cat.info()
523  << "Ignoring slider " << name << "\n";
524  }
525 }
526 
527 /**
528  * Adds the indicated MayaBlendDesc object to the list of blends collected so
529  * far. If a MayaBlendDesc object with the same name is already part of the
530  * tree, the supplied object is discarded and the previously-added object is
531  * returned; otherwise, the supplied object is added to the tree and the same
532  * object is returned.
533  *
534  * In either case, the return value is the MayaBlendDesc that should be used
535  * henceforth.
536  */
539  BlendDescs::iterator bi = _blend_descs.insert(blend_desc).first;
540 
541  return (*bi);
542 }
543 
544 /**
545  * Returns the number of unique MayaBlendDesc objects (and hence the number of
546  * morph sliders) discovered in the tree.
547  */
548 int MayaNodeTree::
550  return _blend_descs.size();
551 }
552 
553 /**
554  * Returns the nth MayaBlendDesc object discovered in the tree.
555  */
557 get_blend_desc(int n) const {
558  nassertr(n >= 0 && n < (int)_blend_descs.size(), nullptr);
559  return _blend_descs[n];
560 }
561 
562 /**
563  * Resets all of the sliders associated with all blend shapes down to 0.
564  */
565 void MayaNodeTree::
567  BlendDescs::iterator bi;
568  for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
569  (*bi)->set_slider(0.0);
570  }
571 }
572 
573 
574 /**
575  * The recursive implementation of build_node().
576  */
577 MayaNodeDesc *MayaNodeTree::
578 r_build_node(const string &path) {
579  // If we have already encountered this pathname, return the corresponding
580  // MayaNodeDesc immediately.
581  NodesByPath::const_iterator ni = _nodes_by_path.find(path);
582  if (ni != _nodes_by_path.end()) {
583  return (*ni).second;
584  }
585 
586  // Otherwise, we have to create it. Do this recursively, so we create each
587  // node along the path.
588  MayaNodeDesc *node_desc = nullptr;
589 
590  // mayaegg_cat.info() << "path: " << path << endl;
591  if (path.empty()) {
592  // This is the top. mayaegg_cat.info() << "found empty path: " << path <<
593  // endl;
594  node_desc = _root;
595 
596  } else {
597  // Maya uses vertical bars to separate path components. Remove everything
598  // from the rightmost bar on; this will give us the parent's path name.
599  size_t bar = path.rfind("|");
600  string parent_path, local_name;
601  if (bar != string::npos) {
602  parent_path = path.substr(0, bar);
603  // mayaegg_cat.info() << "parent_path: " << parent_path << endl;
604  local_name = path.substr(bar + 1);
605  if (local_name == _subroot_parent_name) {
606  node_desc = _root;
607  }
608  } else {
609  local_name = path;
610  }
611  // mayaegg_cat.info() << "local_name: " << local_name << endl;
612 
613  if (node_desc != _root) {
614  MayaNodeDesc *parent_node_desc = r_build_node(parent_path);
615  if (parent_node_desc == nullptr)
616  mayaegg_cat.info() << "empty parent: " << local_name << std::endl;
617  node_desc = new MayaNodeDesc(this, parent_node_desc, local_name);
618  _nodes.push_back(node_desc);
619  }
620  }
621 
622  _nodes_by_path.insert(NodesByPath::value_type(path, node_desc));
623  return node_desc;
624 }
EggXfmSAnim * get_egg_anim(MayaNodeDesc *node_desc)
Returns the anim table corresponding to the joint for the indicated node.
A handle to a Maya blend shape description.
Definition: mayaBlendDesc.h:40
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void from_dag_path(const MDagPath &dag_path, MayaToEggConverter *converter)
Indicates an association between the MayaNodeDesc and some Maya instance.
void tag_all()
Tags the entire hierarchy for conversion.
int get_num_nodes() const
Returns the total number of nodes in the hierarchy, not counting the root node.
bool ignore_slider(const std::string &name) const
Returns true if the indicated name is on the list of sliders to ignore, false otherwise.
bool remove_object_type(const std::string &object_type)
Removes the first instance of the indicated object type from the group if it is present.
Definition: eggGroup.cxx:161
size_type_0 size() const
Returns the number of elements in the ordered vector.
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
void clear()
Resets the entire tree in preparation for repopulating with a new scene.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
Definition: eggSAnimData.h:25
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
EggGroup * get_egg_group(MayaNodeDesc *node_desc)
Returns the EggGroupNode corresponding to the group or joint for the indicated node.
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
bool has_dag_path() const
Returns true if a Maya dag path has been associated with this node, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_egg(EggData *egg_data, EggGroupNode *egg_root, EggGroupNode *skeleton_node, EggGroupNode *morph_node)
Removes all of the references to generated egg structures from the tree, and prepares the tree for ge...
bool tag_named(const GlobPattern &glob)
Tags nodes matching the indicated glob (and all of their children) for conversion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool matches(const std::string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
Definition: globPattern.I:122
bool has_user_data() const
Returns true if a generic user data pointer has recently been set and not yet cleared,...
Definition: eggObject.cxx:107
MayaNodeDesc * build_node(const MDagPath &dag_path)
Returns a pointer to the node corresponding to the indicated dag_path object, creating it first if ne...
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
MayaBlendDesc * get_blend_desc(int n) const
Returns the nth MayaBlendDesc object discovered in the tree.
void get_tag_attribute_names(MObject &node, pvector< string > &tag_names)
artists should be able to set arbitrary tags.
Definition: maya_funcs.cxx:367
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void reset_sliders()
Resets all of the sliders associated with all blend shapes down to 0.
bool get_bool_attribute(MObject &node, const string &attribute_name, bool &value)
Extracts the named boolean attribute from the MObject.
Definition: maya_funcs.cxx:157
MayaBlendDesc * add_blend_desc(MayaBlendDesc *blend_desc)
Adds the indicated MayaBlendDesc object to the list of blends collected so far.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Describes a single instance of a node in the Maya scene graph, relating it to the corresponding egg s...
Definition: mayaNodeDesc.h:40
bool get_vec3d_attribute(MObject &node, const string &attribute_name, LVecBase3d &value)
Extracts the named three-component vector from the MObject.
Definition: maya_funcs.cxx:302
void report_ignored_slider(const std::string &name)
Outputs a message to the user reporting that a slider was ignored.
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool has_object_type(const std::string &object_type) const
Returns true if the indicated object type has been added to the group, or false otherwise.
Definition: eggGroup.cxx:145
int get_num_blend_descs() const
Returns the number of unique MayaBlendDesc objects (and hence the number of morph sliders) discovered...
AnimationConvert get_animation_convert() const
Returns how source animation will be converted into egg structures.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
Definition: eggXfmSAnim.h:28
EggUserData * get_user_data() const
Returns the user data pointer most recently stored on this object, or NULL if nothing was previously ...
Definition: eggObject.cxx:84
MayaNodeDesc * get_node(int n) const
Returns the nth node in the hierarchy, in an arbitrary ordering.
bool tag_joint_named(const GlobPattern &glob)
Tags nodes matching the indicated glob (and all of their children) for conversion.
bool ignore_slider(const std::string &name) const
Returns true if the indicated name is on the list of sliders to ignore, false otherwise.
const MDagPath & get_dag_path() const
Returns the dag path associated with this node.
void set_visibility_mode(VisibilityMode mode)
Specifies whether this geometry is to be considered normally visible, or hidden.
Definition: eggRenderMode.I:66
bool build_hierarchy()
Walks through the complete Maya hierarchy but does not tag any nodes for conversion.
This class supervises the construction of an EggData structure from a single Maya file,...
void set_user_data(EggUserData *user_data)
Sets the user data associated with this object.
Definition: eggObject.cxx:74
This corresponds to a.
Definition: eggTable.h:27
bool untag_named(const GlobPattern &glob)
Un-tags nodes matching the indicated glob (and all of their children) for conversion.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggTable * get_egg_table(MayaNodeDesc *node_desc)
Returns the EggTable corresponding to the joint for the indicated node.
EggSAnimData * get_egg_slider(MayaBlendDesc *blend_desc)
Returns the anim table corresponding to the slider for the indicated blend.
void tag_joint_all()
Tags the entire hierarchy for conversion.
bool has_attribute(MObject &node, const string &attribute_name)
Returns true if the node has the indicated attribute, false otherwise.
Definition: maya_funcs.cxx:85
get_coordinate_system
Returns the coordinate system in which the egg file is defined.
Definition: eggData.h:73
void set_tag(const std::string &key, const std::string &value)
Associates a user-defined value with a user-defined key which is stored on the node.
Definition: eggGroup.I:720
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_enum_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the enum attribute from the MObject as a string value.
Definition: maya_funcs.cxx:398
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A SwitchCondition that switches the levels-of-detail based on distance from the camera's eyepoint.
This class contains extra user data which is piggybacked onto EggGroup objects for the purpose of the...
bool tag_selected()
Tags the just the selected hierarchy for conversion, or the entire hierarchy if nothing is selected.
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
Definition: globPattern.h:32
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.