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