Panda3D
maya_funcs.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 maya_funcs.cxx
10  * @author drose
11  * @date 2000-02-16
12  */
13 
14 #include "maya_funcs.h"
15 
16 #include "pre_maya_include.h"
17 #include <maya/MObject.h>
18 #include <maya/MAngle.h>
19 #include <maya/MFnDependencyNode.h>
20 #include <maya/MStatus.h>
21 #include <maya/MFnStringData.h>
22 #include <maya/MFnNumericData.h>
23 #include <maya/MPlugArray.h>
24 #include <maya/MPlug.h>
25 #include <maya/MFnAttribute.h>
26 #include <maya/MFnTypedAttribute.h>
27 #include <maya/MFnNumericAttribute.h>
28 #include <maya/MFnEnumAttribute.h>
29 #include <maya/MFnCompoundAttribute.h>
30 #include <maya/MFnMatrixData.h>
31 #include <maya/MMatrix.h>
32 #include "post_maya_include.h"
33 
34 using std::endl;
35 using std::string;
36 
37 /**
38  * Gets the named MPlug associated, if any.
39  */
40 bool
41 get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug) {
42  MStatus status;
43  MFnDependencyNode node_fn(node, &status);
44  if (!status) {
45  maya_cat.error()
46  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
47  return false;
48  }
49 
50  MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
51  if (!status) {
52  return false;
53  }
54 
55  MFnAttribute attr_fn(attr, &status);
56  if (!status) {
57  maya_cat.error()
58  << "Attribute " << attribute_name << " on " << node_fn.name().asChar()
59  << " is a " << attr.apiTypeStr() << ", not an Attribute.\n";
60  return false;
61  }
62 
63  plug = MPlug(node, attr);
64  return true;
65 }
66 
67 /**
68  * Returns true if the named connection exists on the node and is connected to
69  * anything, false otherwise.
70  */
71 bool
72 is_connected(MObject &node, const string &attribute_name) {
73  MPlug plug;
74  if (!get_maya_plug(node, attribute_name, plug)) {
75  return false;
76  }
77 
78  return plug.isConnected();
79 }
80 
81 /**
82  * Returns true if the node has the indicated attribute, false otherwise.
83  */
84 bool
85 has_attribute(MObject &node, const string &attribute_name) {
86  MStatus status;
87  MFnDependencyNode node_fn(node, &status);
88  if (!status) {
89  maya_cat.error()
90  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
91  return false;
92  }
93 
94  node_fn.attribute(attribute_name.c_str(), &status);
95  if (!status) {
96  // No such attribute.
97  return false;
98  }
99  return true;
100 }
101 
102 /**
103  * Removes the named attribute from the indicated Maya node. Returns true if
104  * successful, false otherwise.
105  */
106 bool
107 remove_attribute(MObject &node, const string &attribute_name) {
108  MStatus status;
109  MFnDependencyNode node_fn(node, &status);
110  if (!status) {
111  maya_cat.error()
112  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
113  return false;
114  }
115 
116  MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
117  if (!status) {
118  return false;
119  }
120 
121  {
122  // Just to prove the the attr is, in fact, an Attribute. According to the
123  // Maya docs, we shouldn't leave the MFnAttribute object around while we
124  // remove the attribute, though.
125  MFnAttribute attr_fn(attr, &status);
126  if (!status) {
127  maya_cat.error()
128  << "Attribute " << attribute_name << " on " << node_fn.name().asChar()
129  << " is a " << attr.apiTypeStr() << ", not an Attribute.\n";
130  return false;
131  }
132  }
133 
134  MFnDependencyNode::MAttrClass type = node_fn.attributeClass(attr, &status);
135  if (!status) {
136  maya_cat.error()
137  << "Couldn't get class of attribute " << attribute_name << " on "
138  << node_fn.name().asChar() << ".\n";
139  return false;
140  }
141 
142  status = node_fn.removeAttribute(attr, type);
143  if (!status) {
144  maya_cat.error()
145  << "Couldn't remove attribute " << attribute_name << " from "
146  << node_fn.name().asChar() << ".\n";
147  return false;
148  }
149 
150  return true;
151 }
152 
153 /**
154  * Extracts the named boolean attribute from the MObject.
155  */
156 bool
157 get_bool_attribute(MObject &node, const string &attribute_name,
158  bool &value) {
159  if (!has_attribute(node, attribute_name)) {
160  // For bool attributes only, we assume if the attribute is absent it's the
161  // same thing as being false.
162  return false;
163  }
164 
165  if (!get_maya_attribute(node, attribute_name, value)) {
166  maya_cat.warning()
167  << "Attribute " << attribute_name
168  << " does not have a bool value.\n";
169  describe_maya_attribute(node, attribute_name);
170  return false;
171  }
172  return true;
173 }
174 
175 /**
176  * Extracts the named angle in degrees from the MObject.
177  */
178 bool
179 get_angle_attribute(MObject &node, const string &attribute_name,
180  double &value) {
181  MAngle maya_value;
182  if (!get_maya_attribute(node, attribute_name, maya_value)) {
183  maya_cat.warning()
184  << "Attribute " << attribute_name
185  << " does not have an angle value.\n";
186  describe_maya_attribute(node, attribute_name);
187  return false;
188  }
189  value = maya_value.asDegrees();
190  return true;
191 }
192 
193 /**
194  * Extracts the named two-component vector from the MObject.
195  */
196 bool
197 get_vec2_attribute(MObject &node, const string &attribute_name,
198  LVecBase2 &value) {
199  MStatus status;
200 
201  MObject vec2_object;
202  if (!get_maya_attribute(node, attribute_name, vec2_object)) {
203  maya_cat.warning()
204  << "Attribute " << attribute_name
205  << " does not have a vec2 object value.\n";
206  describe_maya_attribute(node, attribute_name);
207  return false;
208  }
209 
210  MFnNumericData data(vec2_object, &status);
211  if (!status) {
212  maya_cat.warning()
213  << "Attribute " << attribute_name << " is of type "
214  << vec2_object.apiTypeStr() << ", not a NumericData.\n";
215  return false;
216  }
217 
218  status = data.getData(value[0], value[1]);
219  if (!status) {
220  maya_cat.warning()
221  << "Unable to extract 2 floats from " << attribute_name
222  << ", of type " << vec2_object.apiTypeStr() << "\n";
223  }
224 
225  return true;
226 }
227 
228 /**
229  * Extracts the named three-component vector from the MObject.
230  */
231 bool
232 get_vec3_attribute(MObject &node, const string &attribute_name,
233  LVecBase3 &value) {
234  MStatus status;
235 
236  MObject vec3_object;
237  if (!get_maya_attribute(node, attribute_name, vec3_object)) {
238  maya_cat.warning()
239  << "Attribute " << attribute_name
240  << " does not have a vec3 object value.\n";
241  describe_maya_attribute(node, attribute_name);
242  return false;
243  }
244 
245  MFnNumericData data(vec3_object, &status);
246  if (!status) {
247  maya_cat.warning()
248  << "Attribute " << attribute_name << " is of type "
249  << vec3_object.apiTypeStr() << ", not a NumericData.\n";
250  return false;
251  }
252 
253  status = data.getData(value[0], value[1], value[2]);
254  if (!status) {
255  maya_cat.warning()
256  << "Unable to extract 3 floats from " << attribute_name
257  << ", of type " << vec3_object.apiTypeStr() << "\n";
258  }
259 
260  return true;
261 }
262 
263 /**
264  * Extracts the named two-component vector from the MObject.
265  */
266 bool
267 get_vec2d_attribute(MObject &node, const string &attribute_name,
268  LVecBase2d &value) {
269  MStatus status;
270 
271  MObject vec2d_object;
272  if (!get_maya_attribute(node, attribute_name, vec2d_object)) {
273  maya_cat.warning()
274  << "Attribute " << attribute_name
275  << " does not have a vec2d object value.\n";
276  describe_maya_attribute(node, attribute_name);
277  return false;
278  }
279 
280  MFnNumericData data(vec2d_object, &status);
281  if (!status) {
282  maya_cat.warning()
283  << "Attribute " << attribute_name << " is of type "
284  << vec2d_object.apiTypeStr() << ", not a NumericData.\n";
285  return false;
286  }
287 
288  status = data.getData(value[0], value[1]);
289  if (!status) {
290  maya_cat.warning()
291  << "Unable to extract 2 doubles from " << attribute_name
292  << ", of type " << vec2d_object.apiTypeStr() << "\n";
293  }
294 
295  return true;
296 }
297 
298 /**
299  * Extracts the named three-component vector from the MObject.
300  */
301 bool
302 get_vec3d_attribute(MObject &node, const string &attribute_name,
303  LVecBase3d &value) {
304  MStatus status;
305 
306  MObject vec3d_object;
307  if (!get_maya_attribute(node, attribute_name, vec3d_object)) {
308  maya_cat.warning()
309  << "Attribute " << attribute_name
310  << " does not have a vec3d object value.\n";
311  describe_maya_attribute(node, attribute_name);
312  return false;
313  }
314 
315  MFnNumericData data(vec3d_object, &status);
316  if (!status) {
317  maya_cat.warning()
318  << "Attribute " << attribute_name << " is of type "
319  << vec3d_object.apiTypeStr() << ", not a NumericData.\n";
320  return false;
321  }
322 
323  status = data.getData(value[0], value[1], value[2]);
324  if (!status) {
325  maya_cat.warning()
326  << "Unable to extract 3 doubles from " << attribute_name
327  << ", of type " << vec3d_object.apiTypeStr() << "\n";
328  }
329 
330  return true;
331 }
332 
333 /**
334  * Extracts the named 4x4 matrix from the MObject.
335  */
336 bool
337 get_mat4d_attribute(MObject &node, const string &attribute_name,
338  LMatrix4d &value) {
339  MStatus status;
340  MObject matrix;
341  if (!get_maya_attribute(node, attribute_name, matrix)) {
342  return false;
343  }
344 
345  MFnMatrixData matrix_data(matrix, &status);
346  if (!status) {
347  maya_cat.warning()
348  << "Attribute " << attribute_name << " is of type "
349  << node.apiTypeStr() << ", not a Matrix.\n";
350  return false;
351  }
352 
353  const MMatrix &mat = matrix_data.matrix();
354  for (int i = 0; i < 4; i++) {
355  for (int j = 0; j < 4; j++) {
356  value(i, j) = mat(i, j);
357  }
358  }
359  return true;
360 }
361 
362 /**
363  * artists should be able to set arbitrary tags. Query all the attributes on
364  * this object and return the lists of attribute names that has "tag" prefix
365  */
366 void
367 get_tag_attribute_names(MObject &node, pvector<string> &tag_names) {
368  MStatus status;
369  MFnDependencyNode node_fn(node, &status);
370  if (!status) {
371  maya_cat.warning()
372  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
373  return;
374  }
375 
376  string name = node_fn.name().asChar();
377  unsigned i;
378 
379  for (i = 0; i < node_fn.attributeCount(); i++) {
380  MObject attr = node_fn.attribute(i, &status);
381  if (status) {
382  MFnAttribute attrib(attr, &status);
383  if (status) {
384  string attribute_name = attrib.name().asChar();
385  if (attribute_name.find("tag", 0) != string::npos) {
386  maya_cat.info() << ":" << name << ":" << " is tagged with <"
387  << attribute_name << ">" << endl;
388  tag_names.push_back(attribute_name);
389  }
390  }
391  }
392  }
393 }
394 /**
395  * Extracts the enum attribute from the MObject as a string value.
396  */
397 bool
398 get_enum_attribute(MObject &node, const string &attribute_name,
399  string &value) {
400  MStatus status;
401 
402  MPlug plug;
403  if (!get_maya_plug(node, attribute_name.c_str(), plug)) {
404  return false;
405  }
406 
407  MObject attrib = plug.attribute();
408  MFnEnumAttribute enum_attrib(attrib, &status);
409  if (!status) {
410  maya_cat.warning()
411  << "Not an enum attribute: " << attribute_name << "\n";
412  return false;
413  }
414 
415  short index;
416  status = plug.getValue(index);
417  if (!status) {
418  maya_cat.warning()
419  << "Could not get numeric value of " << attribute_name << "\n";
420  status.perror("MPlug::getValue(short)");
421  return false;
422  }
423 
424  MString name = enum_attrib.fieldName(index, &status);
425  if (!status) {
426  maya_cat.warning()
427  << "Invalid value for " << attribute_name << ": " << index << "\n";
428  status.perror("MFnEnumAttribute::fieldName()");
429  return false;
430  }
431 
432  value = name.asChar();
433  return true;
434 }
435 
436 /**
437  * Extracts the named string attribute from the MObject.
438  */
439 bool
440 get_string_attribute(MObject &node, const string &attribute_name,
441  string &value) {
442  MStatus status;
443 
444  MObject string_object;
445  if (!get_maya_attribute(node, attribute_name, string_object)) {
446  maya_cat.warning()
447  << "Attribute " << attribute_name
448  << " does not have an string object value.\n";
449  describe_maya_attribute(node, attribute_name);
450  return false;
451  }
452 
453  MFnStringData data(string_object, &status);
454  if (!status) {
455  maya_cat.warning()
456  << "Attribute " << attribute_name << " is of type "
457  << string_object.apiTypeStr() << ", not a StringData.\n";
458  return false;
459  }
460 
461  value = data.string().asChar();
462  return true;
463 }
464 
465 /**
466  * Sets the named string attribute on the MObject.
467  */
468 bool
469 set_string_attribute(MObject &node, const string &attribute_name,
470  const string &value) {
471  MStatus status;
472 
473  // First, we get the string_object, then we set its string.
474  MObject string_object;
475  if (!get_maya_attribute(node, attribute_name, string_object)) {
476  maya_cat.warning()
477  << "Attribute " << attribute_name
478  << " does not have a string object value.\n";
479  describe_maya_attribute(node, attribute_name);
480  return false;
481  }
482 
483  MFnStringData data(string_object, &status);
484  if (!status) {
485  maya_cat.warning()
486  << "Attribute " << attribute_name << " is of type "
487  << string_object.apiTypeStr() << ", not a StringData.\n";
488  return false;
489  }
490 
491  MString mstring_value(value.data(), value.length());
492  status = data.set(mstring_value);
493  if (!status) {
494  status.perror(attribute_name.c_str());
495  return false;
496  }
497 
498  // And it appears we now need to set the string object back.
499  if (!set_maya_attribute(node, attribute_name, string_object)) {
500  maya_cat.warning()
501  << "Attribute " << attribute_name
502  << " suddenly does not have a string object value.\n";
503  return false;
504  }
505 
506  return true;
507 }
508 
509 /**
510  * Extracts the children of this attribute from the MObject. test for now
511  */
512 bool
514  MStatus status;
515 
516  MFnCompoundAttribute comp_attr(node, &status);
517 
518  maya_cat.info() << "comp_attr has:" << comp_attr.numChildren() << " children" << endl;
519  for (size_t i = 0; i < comp_attr.numChildren(); i++) {
520  MObject child = comp_attr.child(i, &status);
521  if (child.apiType() == MFn::kAttribute3Float){
522  LRGBColor color;
523  /*
524  if (get_vec3_attribute(child, "color", color)) {
525  maya_cat.info() << "color: " << color << endl;
526  }
527  */
528  }
529  else if (child.apiType() == MFn::kNumericAttribute) {
530  MFnNumericAttribute numeric(child, &status);
531  if (status) {
532  switch(numeric.unitType()) {
533  case MFnNumericData::kFloat :
534  PN_stdfloat alpha;
535  status = numeric.getDefault(alpha);
536  maya_cat.info() << "found a float :" << alpha << endl;
537  break;
538  case MFnNumericData::kBoolean :
539  bool v;
540  status = numeric.getDefault(v);
541  maya_cat.info() << "found a bool :" << v << endl;
542  default:
543  maya_cat.info() << numeric.unitType() << endl;
544  }
545  }
546  }
547  else if (child.apiType() == MFn::kEnumAttribute) {
548  MFnEnumAttribute enu(child, &status);
549  if (status) {
550  MString blah;
551  status = enu.getDefault(blah);
552  maya_cat.info() << "found a string :" << blah.asChar() << endl;
553  MPlug plug = MPlug(node, child);
554  maya_cat.info() << "plug name" << plug.name().asChar() << endl;
555  }
556  }
557  }
558  return true;
559 }
560 
561 /**
562  * Writes some warning output about the indicated Maya attribute.
563  */
564 void
565 describe_maya_attribute(MObject &node, const string &attribute_name) {
566  MStatus status;
567  MFnDependencyNode node_fn(node, &status);
568  if (!status) {
569  maya_cat.warning()
570  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
571  return;
572  }
573 
574  MObject attr = node_fn.attribute(attribute_name.c_str(), &status);
575  if (!status) {
576  maya_cat.warning()
577  << "Object " << node_fn.name().asChar() << " does not support attribute "
578  << attribute_name << "\n";
579  return;
580  }
581 
582  maya_cat.warning()
583  << "Attribute " << attribute_name << " on object "
584  << node_fn.name().asChar() << " has type " << attr.apiTypeStr() << "\n";
585 }
586 
587 string
588 string_mfndata_type(MFnData::Type type) {
589  switch (type) {
590  case MFnData::kInvalid:
591  return "kInvalid";
592 
593  case MFnData::kNumeric:
594  return "kNumeric";
595 
596  case MFnData::kPlugin:
597  return "kPlugin";
598 
599  case MFnData::kPluginGeometry:
600  return "kPluginGeometry";
601 
602  case MFnData::kString:
603  return "kString";
604 
605  case MFnData::kMatrix:
606  return "kMatrix";
607 
608  case MFnData::kStringArray:
609  return "kStringArray";
610 
611  case MFnData::kDoubleArray:
612  return "kDoubleArray";
613 
614  case MFnData::kIntArray:
615  return "kIntArray";
616 
617  case MFnData::kPointArray:
618  return "kPointArray";
619 
620  case MFnData::kVectorArray:
621  return "kVectorArray";
622 
623  case MFnData::kComponentList:
624  return "kComponentList";
625 
626  case MFnData::kMesh:
627  return "kMesh";
628 
629  case MFnData::kLattice:
630  return "kLattice";
631 
632  case MFnData::kNurbsCurve:
633  return "kNurbsCurve";
634 
635  case MFnData::kNurbsSurface:
636  return "kNurbsSurface";
637 
638  case MFnData::kSphere:
639  return "kSphere";
640 
641  case MFnData::kDynArrayAttrs:
642  return "kDynArrayAttrs";
643 
644  case MFnData::kDynSweptGeometry:
645  return "kDynSweptGeometry";
646 
647  case MFnData::kSubdSurface:
648  return "kSubdSurface";
649 
650  case MFnData::kLast:
651  default:
652  break;
653  }
654 
655  return "**invalid**";
656 }
657 
658 /**
659  * Writes some info output showing all the attributes on the given dependency
660  * node. Primarily useful during development, to figure out where the heck
661  * Maya hides some of the connected properties.
662  */
663 void
664 list_maya_attributes(MObject &node) {
665  MStatus status;
666  MFnDependencyNode node_fn(node, &status);
667  if (!status) {
668  maya_cat.warning()
669  << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
670  return;
671  }
672 
673  string name = node_fn.name().asChar();
674  unsigned i;
675 
676  MPlugArray connections;
677  status = node_fn.getConnections(connections);
678  if (!status) {
679  status.perror("MFnDependencyNode::getConnections");
680 
681  } else {
682  maya_cat.info()
683  << name << " has " << connections.length() << " connections.\n";
684  for (i = 0; i < connections.length(); i++) {
685  MPlug plug = connections[i];
686 
687  maya_cat.info(false)
688  << " " << i << ". " << plug.name().asChar() << ", "
689  << plug.attribute().apiTypeStr() << ", "
690  << plug.node().apiTypeStr();
691  if (plug.attribute().apiType() == MFn::kCompoundAttribute) {
692  // maya_cat.info() << plug.info();
693  // describe_compound_attribute(plug.attribute());
694  }
695  if (plug.isConnected()) {
696  maya_cat.info(false)
697  << " (*)";
698  }
699  maya_cat.info(false)
700  << "\n";
701  }
702  }
703 
704  maya_cat.info()
705  << name << " has " << node_fn.attributeCount() << " attributes.\n";
706  for (i = 0; i < node_fn.attributeCount(); i++) {
707  MObject attr = node_fn.attribute(i, &status);
708  if (status) {
709  MFnTypedAttribute typed_attrib(attr, &status);
710  if (status) {
711  // It's a typed attrib.
712  maya_cat.info(false)
713  << " " << i << ". " << typed_attrib.name().asChar()
714  << " [" << attr.apiTypeStr() << ", "
715  << string_mfndata_type(typed_attrib.attrType()) << "]\n";
716  } else {
717  MFnAttribute attrib(attr, &status);
718  if (status) {
719  // It's a generic attrib.
720  maya_cat.info(false)
721  << " " << i << ". " << attrib.name().asChar()
722  << " [" << attr.apiTypeStr() << "]\n";
723  } else {
724  // Don't know what it is.
725  maya_cat.info(false)
726  << " " << i << ". [" << attr.apiTypeStr() << "]\n";
727  }
728  }
729  }
730  }
731 }
bool get_angle_attribute(MObject &node, const string &attribute_name, double &value)
Extracts the named angle in degrees from the MObject.
Definition: maya_funcs.cxx:179
bool get_mat4d_attribute(MObject &node, const string &attribute_name, LMatrix4d &value)
Extracts the named 4x4 matrix from the MObject.
Definition: maya_funcs.cxx:337
bool describe_compound_attribute(MObject &node)
Extracts the children of this attribute from the MObject.
Definition: maya_funcs.cxx:513
bool get_vec2d_attribute(MObject &node, const string &attribute_name, LVecBase2d &value)
Extracts the named two-component vector from the MObject.
Definition: maya_funcs.cxx:267
bool get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug)
Gets the named MPlug associated, if any.
Definition: maya_funcs.cxx:41
bool remove_attribute(MObject &node, const string &attribute_name)
Removes the named attribute from the indicated Maya node.
Definition: maya_funcs.cxx:107
bool get_string_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the named string attribute from the MObject.
Definition: maya_funcs.cxx:440
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
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 set_string_attribute(MObject &node, const string &attribute_name, const string &value)
Sets the named string attribute on the MObject.
Definition: maya_funcs.cxx:469
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.
bool is_connected(MObject &node, const string &attribute_name)
Returns true if the named connection exists on the node and is connected to anything,...
Definition: maya_funcs.cxx:72
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 describe_maya_attribute(MObject &node, const string &attribute_name)
Writes some warning output about the indicated Maya attribute.
Definition: maya_funcs.cxx:565
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_vec3_attribute(MObject &node, const string &attribute_name, LVecBase3 &value)
Extracts the named three-component vector from the MObject.
Definition: maya_funcs.cxx:232
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
void list_maya_attributes(MObject &node)
Writes some info output showing all the attributes on the given dependency node.
Definition: maya_funcs.cxx:664
bool get_vec2_attribute(MObject &node, const string &attribute_name, LVecBase2 &value)
Extracts the named two-component vector from the MObject.
Definition: maya_funcs.cxx:197
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.