Panda3D
Loading...
Searching...
No Matches
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
34using std::endl;
35using std::string;
36
37/**
38 * Gets the named MPlug associated, if any.
39 */
40bool
41get_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 */
71bool
72is_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 */
84bool
85has_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 */
106bool
107remove_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 */
156bool
157get_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 */
178bool
179get_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 */
196bool
197get_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 */
231bool
232get_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 */
266bool
267get_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 */
301bool
302get_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 */
336bool
337get_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 */
366void
367get_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 */
397bool
398get_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 */
439bool
440get_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 */
468bool
469set_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 */
512bool
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 /*
523 LRGBColor color;
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 */
564void
565describe_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
587string
588string_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 */
663void
664list_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}
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
bool remove_attribute(MObject &node, const string &attribute_name)
Removes the named attribute from the indicated Maya node.
bool get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug)
Gets the named MPlug associated, if any.
bool get_vec3d_attribute(MObject &node, const string &attribute_name, LVecBase3d &value)
Extracts the named three-component vector from the MObject.
bool get_string_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the named string attribute from the MObject.
void get_tag_attribute_names(MObject &node, pvector< string > &tag_names)
artists should be able to set arbitrary tags.
bool get_angle_attribute(MObject &node, const string &attribute_name, double &value)
Extracts the named angle in degrees from the MObject.
bool set_string_attribute(MObject &node, const string &attribute_name, const string &value)
Sets the named string attribute on the MObject.
void list_maya_attributes(MObject &node)
Writes some info output showing all the attributes on the given dependency node.
bool is_connected(MObject &node, const string &attribute_name)
Returns true if the named connection exists on the node and is connected to anything,...
void describe_maya_attribute(MObject &node, const string &attribute_name)
Writes some warning output about the indicated Maya attribute.
bool get_vec3_attribute(MObject &node, const string &attribute_name, LVecBase3 &value)
Extracts the named three-component vector from the MObject.
bool get_enum_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the enum attribute from the MObject as a string value.
bool has_attribute(MObject &node, const string &attribute_name)
Returns true if the node has the indicated attribute, false otherwise.
bool get_mat4d_attribute(MObject &node, const string &attribute_name, LMatrix4d &value)
Extracts the named 4x4 matrix from the MObject.
bool get_vec2d_attribute(MObject &node, const string &attribute_name, LVecBase2d &value)
Extracts the named two-component vector from the MObject.
bool describe_compound_attribute(MObject &node)
Extracts the children of this attribute from the MObject.
bool get_vec2_attribute(MObject &node, const string &attribute_name, LVecBase2 &value)
Extracts the named two-component vector from the MObject.
bool get_bool_attribute(MObject &node, const string &attribute_name, bool &value)
Extracts the named boolean attribute from the MObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.