1 /* 2 Copyright (c) 2008-2009 NetAllied Systems GmbH 3 4 This file is part of COLLADAMaya. 5 6 Portions of the code are: 7 Copyright (c) 2005-2007 Feeling Software Inc. 8 Copyright (c) 2005-2007 Sony Computer Entertainment America 9 Copyright (c) 2004-2005 Alias Systems Corp. 10 11 Licensed under the MIT Open Source License, 12 for details please see LICENSE file or the website 13 http://www.opensource.org/licenses/mit-license.php 14 */ 15 16 #include "COLLADAMayaStableHeaders.h" 17 #include "COLLADAMayaAttributeParser.h" 18 19 #include <maya/MAngle.h> 20 #include <maya/MDataHandle.h> 21 #include <maya/MDistance.h> 22 #include <maya/MFnAttribute.h> 23 #include <maya/MFnComponentListData.h> 24 #include <maya/MFnCompoundAttribute.h> 25 #include <maya/MFnEnumAttribute.h> 26 #include <maya/MFnGenericAttribute.h> 27 #include <maya/MFnLightDataAttribute.h> 28 #include <maya/MFnMatrixData.h> 29 #include <maya/MFnMesh.h> 30 #include <maya/MFnMessageAttribute.h> 31 #include <maya/MFnNumericAttribute.h> 32 #include <maya/MFnTypedAttribute.h> 33 #include <maya/MFnUnitAttribute.h> 34 #include <maya/MTime.h> 35 36 namespace COLLADAMaya 37 { parseAttributes(MFnDependencyNode & fnNode,AttributeParser & parser)38 void AttributeParser::parseAttributes(MFnDependencyNode & fnNode, AttributeParser & parser) 39 { 40 MStatus status; 41 42 unsigned int attrCount = fnNode.attributeCount(&status); 43 if (!status) return; 44 45 for (unsigned int attrIndex = 0; attrIndex < attrCount; ++attrIndex) 46 { 47 MObject attr = fnNode.attribute(attrIndex, &status); 48 if (!status) continue; 49 50 MFnAttribute fnAttr(attr, &status); 51 if (!status) continue; 52 53 MString attrName = fnAttr.name(&status); 54 if (!status) continue; 55 56 MPlug plug = fnNode.findPlug(attr, &status); 57 if (!status) continue; 58 59 bool isArray = plug.isArray(&status); 60 if (!status) continue; 61 62 if (isArray) 63 { 64 unsigned int numElements = 0; 65 // evaluateNumElements() may throw an exception is some cases... 66 try 67 { 68 numElements = plug.evaluateNumElements(&status); 69 } 70 catch (...) 71 { 72 continue; 73 } 74 if (!status) continue; 75 76 for (unsigned int plugIndex = 0; plugIndex < numElements; ++plugIndex) 77 { 78 MPlug element = plug.elementByPhysicalIndex(plugIndex, &status); 79 if (!status) continue; 80 81 parser.parsePlug(element); 82 } 83 } 84 else 85 { 86 parser.parsePlug(plug); 87 } 88 } 89 } 90 91 class AutoOnAfterPlug 92 { 93 public: AutoOnAfterPlug(AttributeParser & parser,MPlug & plug)94 AutoOnAfterPlug(AttributeParser & parser, MPlug & plug) 95 : mParser(parser) 96 , mPlug(plug) 97 {} 98 ~AutoOnAfterPlug()99 ~AutoOnAfterPlug() 100 { 101 mParser.onAfterPlug(mPlug); 102 } 103 104 private: 105 AttributeParser & mParser; 106 MPlug & mPlug; 107 }; 108 parsePlug(MPlug & plug)109 void AttributeParser::parsePlug(MPlug & plug) 110 { 111 AutoOnAfterPlug(*this, plug); 112 113 if (!onBeforePlug(plug)) { 114 // Skip plug 115 return; 116 } 117 118 MStatus status; 119 120 MObject attr = plug.attribute(&status); 121 if (!status) return; 122 123 MFnAttribute fnAttr(attr, &status); 124 if (!status) return; 125 126 MString attrName = fnAttr.name(&status);; 127 if (!status) return; 128 129 // First handle numeric compound types 130 MFnNumericData::Type type; 131 if (IsNumericCompoundAttribute(attr, type)) 132 { 133 parseNumeric(plug, type); 134 135 // Mark children as parsed 136 //MFnCompoundAttribute fnCompoundAttribute(attr, &status); 137 //if (!status) return; 138 139 //unsigned int numChildren = fnCompoundAttribute.numChildren(&status); 140 //if (!status) return; 141 142 //for (unsigned int i = 0; i < fnCompoundAttribute.numChildren(); ++i) 143 //{ 144 // MObject child = fnCompoundAttribute.child(i, &status); 145 // if (!status) return; 146 147 // MFnAttribute childFnAttr(child); 148 // //parsedAttributes.insert(childFnAttr.name().asChar()); 149 //} 150 } 151 // Other cases 152 else if (attr.hasFn(MFn::kCompoundAttribute)) { 153 parseCompoundPlug(plug); 154 } 155 else if (attr.hasFn(MFn::kEnumAttribute)) { 156 parseEnumPlug(plug); 157 } 158 else if (attr.hasFn(MFn::kGenericAttribute)) { 159 parseGenericPlug(plug); 160 } 161 else if (attr.hasFn(MFn::kLightDataAttribute)) { 162 parseLightDataPlug(plug); 163 } 164 else if (attr.hasFn(MFn::kMatrixAttribute)) { 165 parseMatrixPlug(plug); 166 } 167 else if (attr.hasFn(MFn::kMessageAttribute)) { 168 parseMessagePlug(plug); 169 } 170 else if (attr.hasFn(MFn::kNumericAttribute)) { 171 parseNumericPlug(plug); 172 } 173 else if (attr.hasFn(MFn::kTypedAttribute)) { 174 parseTypedPlug(plug); 175 } 176 else if (attr.hasFn(MFn::kUnitAttribute)) { 177 parseUnitPlug(plug); 178 } 179 } 180 parseNumericPlug(MPlug & plug)181 void AttributeParser::parseNumericPlug(MPlug & plug) 182 { 183 MStatus status; 184 185 MObject attr = plug.attribute(&status); 186 if (!status) return; 187 188 MFnNumericAttribute fnNumAttr(attr, &status); 189 if (!status) return; 190 191 MFnNumericData::Type type = fnNumAttr.unitType(&status); 192 if (!status) return; 193 194 parseNumeric(plug, type); 195 } 196 parseTypedPlug(MPlug & plug)197 void AttributeParser::parseTypedPlug(MPlug & plug) 198 { 199 MStatus status; 200 201 MObject attr = plug.attribute(&status); 202 if (!status) return; 203 204 MFnTypedAttribute fnTypedAttr(attr, &status); 205 if (!status) return; 206 207 MFnData::Type type = fnTypedAttr.attrType(&status); 208 if (!status) return; 209 210 switch (type) 211 { 212 //! Invalid value 213 case MFnData::kInvalid: 214 break; 215 216 //! Numeric, use MFnNumericData extract the node data. 217 case MFnData::kNumeric: 218 parseNumericData(plug); 219 break; 220 221 //! Plugin Blind Data, use MFnPluginData to extract the node data. 222 case MFnData::kPlugin: 223 // TODO 224 break; 225 226 //! Plugin Geometry, use MFnGeometryData to extract the node data. 227 case MFnData::kPluginGeometry: 228 // TODO 229 break; 230 231 //! String, use MFnStringData to extract the node data. 232 case MFnData::kString: 233 parseStringData(plug); 234 break; 235 236 //! Matrix, use MFnMatrixData to extract the node data. 237 case MFnData::kMatrix: 238 parseMatrixPlug(plug); 239 break; 240 241 //! String Array, use MFnStringArrayData to extract the node data. 242 case MFnData::kStringArray: 243 // TODO 244 break; 245 246 //! Double Array, use MFnDoubleArrayData to extract the node data. 247 case MFnData::kDoubleArray: 248 // TODO 249 break; 250 251 #if MAYA_API_VERSION >= 201400 252 //! Float Array, use MFnFloatArrayData to extract the node data. 253 case MFnData::kFloatArray: 254 // TODO 255 break; 256 #endif 257 258 //! Int Array, use MFnIntArrayData to extract the node data. 259 case MFnData::kIntArray: 260 // TODO 261 break; 262 263 //! Point Array, use MFnPointArrayData to extract the node data. 264 case MFnData::kPointArray: 265 // TODO 266 break; 267 268 //! Vector Array, use MFnVectorArrayData to extract the node data. 269 case MFnData::kVectorArray: 270 // TODO 271 break; 272 273 //! Component List, use MFnComponentListData to extract the node data. 274 case MFnData::kComponentList: 275 parseComponentListData(plug); 276 break; 277 278 //! Mesh, use MFnMeshData to extract the node data. 279 case MFnData::kMesh: 280 parseMeshData(plug); 281 break; 282 283 //! Lattice, use MFnLatticeData to extract the node data. 284 case MFnData::kLattice: 285 // TODO 286 break; 287 288 //! Nurbs Curve, use MFnNurbsCurveData to extract the node data. 289 case MFnData::kNurbsCurve: 290 // TODO 291 break; 292 293 //! Nurbs Surface, use MFnNurbsSurfaceData to extract the node data. 294 case MFnData::kNurbsSurface: 295 // TODO 296 break; 297 298 //! Sphere, use MFnSphereData to extract the node data. 299 case MFnData::kSphere: 300 // TODO 301 break; 302 303 //! ArrayAttrs, use MFnArrayAttrsData to extract the node data. 304 case MFnData::kDynArrayAttrs: 305 // TODO 306 break; 307 308 //! SweptGeometry, use MFnDynSweptGeometryData to extract the 309 //node data. This data node is in OpenMayaFX which must be 310 //linked to. 311 312 case MFnData::kDynSweptGeometry: 313 // TODO 314 break; 315 316 //! Subdivision Surface, use MFnSubdData to extract the node data. 317 case MFnData::kSubdSurface: 318 // TODO 319 break; 320 321 //! nObject data, use MFnNObjectData to extract node data 322 case MFnData::kNObject: 323 // TODO 324 break; 325 326 //! nId data, use MFnNIdData to extract node data 327 case MFnData::kNId: 328 // TODO 329 break; 330 331 #if MAYA_API_VERSION >= 201200 332 //! Typically used when the data can be one of several types. 333 case MFnData::kAny: 334 // TODO 335 break; 336 #endif 337 338 default: 339 break; 340 } 341 } 342 parseEnumPlug(MPlug & plug)343 void AttributeParser::parseEnumPlug(MPlug & plug) 344 { 345 MStatus status; 346 347 MObject attr = plug.attribute(&status); 348 if (!status) return; 349 350 MFnEnumAttribute fnEnumAttribute(attr, &status); 351 if (!status) return; 352 353 int enumValue = 0; 354 status = plug.getValue(enumValue); 355 if (!status) return; 356 357 MString enumName = fnEnumAttribute.fieldName(enumValue, &status); 358 if (!status) return; 359 360 MString name = fnEnumAttribute.name(&status); 361 if (!status) return; 362 363 onEnum(plug, name, enumValue, enumName); 364 } 365 parseMessagePlug(MPlug & plug)366 void AttributeParser::parseMessagePlug(MPlug & plug) 367 { 368 MStatus status; 369 370 MObject attr = plug.attribute(&status); 371 if (!status) return; 372 373 MFnMessageAttribute fnMessageAttribute(attr, &status); 374 if (!status) return; 375 376 MFnAttribute fnAttribute(attr, &status); 377 if (!status) return; 378 379 MString name = fnAttribute.name(&status); 380 if (!status) return; 381 382 onMessage(plug, name); 383 } 384 parseMatrixPlug(MPlug & plug)385 void AttributeParser::parseMatrixPlug(MPlug & plug) 386 { 387 MStatus status; 388 389 MObject attr = plug.attribute(&status); 390 if (!status) return; 391 392 MFnAttribute fnAttribute(attr, &status); 393 if (!status) return; 394 395 MString name = fnAttribute.name(&status); 396 if (!status) return; 397 398 MFnMatrixData mxData; 399 MObject object = mxData.create(&status); 400 if (!status) return; 401 402 status = plug.getValue(object); 403 if (!status) return; 404 405 status = mxData.setObject(object); 406 if (!status) return; 407 408 const MMatrix& matrix = mxData.matrix(); 409 410 onMatrix(plug, name, matrix); 411 } 412 parseCompoundPlug(MPlug & plug)413 void AttributeParser::parseCompoundPlug(MPlug & plug) 414 { 415 MStatus status; 416 417 unsigned int plugNumChildren = plug.numChildren(&status); 418 if (!status) return; 419 420 MObject attr = plug.attribute(&status); 421 if (!status) return; 422 423 MFnCompoundAttribute fnCompoundAttribute(attr, &status); 424 if (!status) return; 425 426 unsigned int attrNumChildren = fnCompoundAttribute.numChildren(&status); 427 if (!status) return; 428 429 if (plugNumChildren != attrNumChildren) return; 430 431 MFnAttribute fnAttr(attr, &status); 432 if (!status) return; 433 434 MString name = fnAttr.name(&status); 435 if (!status) return; 436 437 onCompoundAttribute(plug, name); 438 439 // Recurse children 440 for (unsigned int i = 0; i < plugNumChildren; ++i) 441 { 442 MPlug child = plug.child(i, &status); 443 if (!status) continue; 444 445 parsePlug(child); 446 } 447 } 448 parseUnitPlug(MPlug & plug)449 void AttributeParser::parseUnitPlug(MPlug & plug) 450 { 451 MStatus status; 452 453 MObject attr = plug.attribute(&status); 454 if (!status) return; 455 456 MFnUnitAttribute fnAttr(attr, &status); 457 if (!status) return; 458 459 MFnUnitAttribute::Type unitType = fnAttr.unitType(&status); 460 if (!status) return; 461 462 MString name = fnAttr.name(&status); 463 if (!status) return; 464 465 switch (unitType) 466 { 467 case MFnUnitAttribute::kAngle: 468 { 469 MAngle angle; 470 status = plug.getValue(angle); 471 if (!status) return; 472 onAngle(plug, name, angle); 473 } 474 break; 475 476 case MFnUnitAttribute::kDistance: 477 { 478 MDistance distance; 479 status = plug.getValue(distance); 480 if (!status) return; 481 onDistance(plug, name, distance); 482 } 483 break; 484 485 case MFnUnitAttribute::kTime: 486 { 487 MTime time; 488 status = plug.getValue(time); 489 if (!status) return; 490 onTime(plug, name, time); 491 } 492 break; 493 } 494 } 495 parseGenericPlug(MPlug & plug)496 void AttributeParser::parseGenericPlug(MPlug & plug) 497 { 498 MStatus status; 499 500 MObject attr = plug.attribute(&status); 501 if (!status) return; 502 503 MFnGenericAttribute genericAttribute(attr, &status); 504 if (!status) return; 505 506 MFn::Type type = genericAttribute.type(); 507 508 // TODO ? 509 } 510 parseLightDataPlug(MPlug & plug)511 void AttributeParser::parseLightDataPlug(MPlug & plug) 512 { 513 MStatus status; 514 515 MObject attr = plug.attribute(&status); 516 if (!status) return; 517 518 MFnLightDataAttribute lightDataAttribute(attr, &status); 519 if (!status) return; 520 521 // TODO 522 523 // MObject directionX = fnLightDataAttribute.child(0, &status); 524 // if (!status) return; 525 //MObject directionY = fnLightDataAttribute.child(1, &status); 526 // if (!status) return; 527 //MObject directionZ = fnLightDataAttribute.child(2, &status); 528 // if (!status) return; 529 //MObject intensityR = fnLightDataAttribute.child(3, &status); 530 // if (!status) return; 531 //MObject intensityG = fnLightDataAttribute.child(4, &status); 532 // if (!status) return; 533 //MObject intensityB = fnLightDataAttribute.child(5, &status); 534 // if (!status) return; 535 //MObject ambient = fnLightDataAttribute.child(6, &status); 536 // if (!status) return; 537 //MObject diffuse = fnLightDataAttribute.child(7, &status); 538 // if (!status) return; 539 //MObject specular = fnLightDataAttribute.child(8, &status); 540 // if (!status) return; 541 //MObject shadowFraction = fnLightDataAttribute.child(9, &status); 542 // if (!status) return; 543 //MObject preShadowIntensity = fnLightDataAttribute.child(10, &status); 544 // if (!status) return; 545 } 546 parseNumericData(MPlug & plug)547 void AttributeParser::parseNumericData(MPlug & plug) 548 { 549 MStatus status; 550 551 MObject attr = plug.attribute(&status); 552 if (!status) return; 553 554 MFnNumericData fnNumericData(attr, &status); 555 if (!status) return; 556 557 MFnNumericData::Type type = fnNumericData.numericType(&status); 558 559 parseNumeric(plug, type); 560 } 561 parseNumeric(MPlug plug,MFnNumericData::Type type)562 void AttributeParser::parseNumeric(MPlug plug, MFnNumericData::Type type) 563 { 564 MStatus status; 565 566 MObject attrObj = plug.attribute(&status); 567 if (!status) return; 568 569 MFnAttribute attr(attrObj, &status); 570 if (!status) return; 571 572 MString name = attr.name(&status); 573 if (!status) return; 574 575 switch (type) 576 { 577 case MFnNumericData::kInvalid: //!< Invalid data. 578 break; 579 case MFnNumericData::kBoolean: //!< Boolean. 580 { 581 bool value; 582 status = plug.getValue(value); 583 if (!status) return; 584 onBoolean(plug, name, value); 585 } 586 break; 587 case MFnNumericData::kByte: //!< One byte. 588 { 589 char value; 590 status = plug.getValue(value); 591 if (!status) return; 592 onByte(plug, name, value); 593 } 594 break; 595 case MFnNumericData::kChar: //!< One character. 596 { 597 char value; 598 status = plug.getValue(value); 599 if (!status) return; 600 onChar(plug, name, value); 601 } 602 break; 603 case MFnNumericData::kShort: //!< One short. 604 { 605 short value; 606 status = plug.getValue(value); 607 if (!status) return; 608 onShort(plug, name, value); 609 } 610 break; 611 case MFnNumericData::k2Short: //!< Two shorts. 612 { 613 MObject object; 614 status = plug.getValue(object); 615 if (!status) return; 616 MFnNumericData fnNumericData(object, &status); 617 if (!status) return; 618 short value[2]; 619 status = fnNumericData.getData(value[0], value[1]); 620 if (!status) return; 621 onShort2(plug, name, value); 622 } 623 break; 624 case MFnNumericData::k3Short: //!< Three shorts. 625 { 626 MObject object; 627 status = plug.getValue(object); 628 if (!status) return; 629 MFnNumericData fnNumericData(object, &status); 630 if (!status) return; 631 short value[3]; 632 status = fnNumericData.getData(value[0], value[1], value[2]); 633 if (!status) return; 634 onShort3(plug, name, value); 635 } 636 break; 637 case MFnNumericData::kInt: //!< One long. Same as int since "long" is not platform-consistent. 638 { 639 int value; 640 status = plug.getValue(value); 641 if (!status) return; 642 onInteger(plug, name, value); 643 } 644 break; 645 case MFnNumericData::k2Int: //!< Two longs. Same as 2 ints since "long" is not platform-consistent. 646 { 647 MObject object; 648 status = plug.getValue(object); 649 if (!status) return; 650 MFnNumericData fnNumericData(object, &status); 651 if (!status) return; 652 int value[2]; 653 status = fnNumericData.getData(value[0], value[1]); 654 if (!status) return; 655 onInteger2(plug, name, value); 656 } 657 break; 658 case MFnNumericData::k3Int: //!< Three longs. Same as 3 ints since "long" is not platform-consistent. 659 { 660 MObject object; 661 status = plug.getValue(object); 662 if (!status) return; 663 MFnNumericData fnNumericData(object, &status); 664 if (!status) return; 665 int value[3]; 666 status = fnNumericData.getData(value[0], value[1], value[2]); 667 if (!status) return; 668 onInteger3(plug, name, value); 669 } 670 break; 671 case MFnNumericData::kFloat: //!< One float. 672 { 673 MFn::Type apiType = attrObj.apiType(); 674 switch (apiType) 675 { 676 case MFn::kFloatAngleAttribute: 677 { 678 MAngle angle = plug.asMAngle(MDGContext::fsNormal, &status); 679 if (!status) return; 680 onAngle(plug, name, angle); 681 } 682 break; 683 case MFn::kFloatLinearAttribute: 684 { 685 MDistance distance = plug.asMDistance(MDGContext::fsNormal, &status); 686 if (!status) return; 687 onDistance(plug, name, distance); 688 } 689 break; 690 default: 691 { 692 float value = plug.asFloat(MDGContext::fsNormal, &status); 693 if (!status) return; 694 onFloat(plug, name, value); 695 } 696 break; 697 } 698 } 699 break; 700 case MFnNumericData::k2Float: //!< Two floats. 701 { 702 const unsigned int numChildren = 2; 703 704 MPlug childPlugs[numChildren]; 705 for (unsigned int i = 0; i < numChildren; ++i) { 706 childPlugs[i] = plug.child(i, &status); 707 if (!status) return; 708 } 709 710 MObject childAttr[numChildren]; 711 for (unsigned int i = 0; i < numChildren; ++i) { 712 childAttr[i] = childPlugs[i].attribute(&status); 713 if (!status) return; 714 } 715 716 MFn::Type apiType = childAttr[0].apiType(); 717 switch (apiType) 718 { 719 case MFn::kFloatAngleAttribute: 720 { 721 MAngle angles[numChildren]; 722 for (unsigned int i = 0; i < numChildren; ++i) { 723 angles[i] = childPlugs[i].asMAngle(MDGContext::fsNormal, &status); 724 if (!status) return; 725 } 726 onAngle2(plug, name, angles); 727 } 728 break; 729 case MFn::kFloatLinearAttribute: 730 { 731 MDistance distances[numChildren]; 732 for (unsigned int i = 0; i < numChildren; ++i) { 733 distances[i] = childPlugs[i].asMDistance(MDGContext::fsNormal, &status); 734 if (!status) return; 735 } 736 onDistance2(plug, name, distances); 737 } 738 break; 739 default: 740 { 741 float values[numChildren]; 742 for (unsigned int i = 0; i < numChildren; ++i) { 743 values[i] = childPlugs[i].asFloat(MDGContext::fsNormal, &status); 744 if (!status) return; 745 } 746 onFloat2(plug, name, values); 747 } 748 break; 749 } 750 } 751 break; 752 case MFnNumericData::k3Float: //!< Three floats. 753 { 754 const unsigned int numChildren = 3; 755 756 MPlug childPlugs[numChildren]; 757 for (unsigned int i = 0; i < numChildren; ++i) { 758 childPlugs[i] = plug.child(i, &status); 759 if (!status) return; 760 } 761 762 MObject childAttr[numChildren]; 763 for (unsigned int i = 0; i < numChildren; ++i) { 764 childAttr[i] = childPlugs[i].attribute(&status); 765 if (!status) return; 766 } 767 768 MFn::Type apiType = childAttr[0].apiType(); 769 switch (apiType) 770 { 771 case MFn::kFloatAngleAttribute: 772 { 773 MAngle angles[numChildren]; 774 for (unsigned int i = 0; i < numChildren; ++i) { 775 angles[i] = childPlugs[i].asMAngle(MDGContext::fsNormal, &status); 776 if (!status) return; 777 } 778 onAngle3(plug, name, angles); 779 } 780 break; 781 case MFn::kFloatLinearAttribute: 782 { 783 MDistance distances[numChildren]; 784 for (unsigned int i = 0; i < numChildren; ++i) { 785 distances[i] = childPlugs[i].asMDistance(MDGContext::fsNormal, &status); 786 if (!status) return; 787 } 788 onDistance3(plug, name, distances); 789 } 790 break; 791 default: 792 { 793 float values[numChildren]; 794 for (unsigned int i = 0; i < numChildren; ++i) { 795 values[i] = childPlugs[i].asFloat(MDGContext::fsNormal, &status); 796 if (!status) return; 797 } 798 onFloat3(plug, name, values); 799 } 800 break; 801 } 802 } 803 break; 804 case MFnNumericData::kDouble: //!< One double. 805 { 806 MFn::Type apiType = attrObj.apiType(); 807 switch (apiType) 808 { 809 case MFn::kDoubleAngleAttribute: 810 { 811 MAngle angle = plug.asMAngle(MDGContext::fsNormal, &status); 812 if (!status) return; 813 onAngle(plug, name, angle); 814 } 815 break; 816 case MFn::kDoubleLinearAttribute: 817 { 818 MDistance distance = plug.asMDistance(MDGContext::fsNormal, &status); 819 if (!status) return; 820 onDistance(plug, name, distance); 821 } 822 break; 823 default: 824 { 825 double value = plug.asDouble(MDGContext::fsNormal, &status); 826 if (!status) return; 827 onDouble(plug, name, value); 828 } 829 break; 830 } 831 } 832 break; 833 case MFnNumericData::k2Double: //!< Two doubles. 834 { 835 const unsigned int numChildren = 2; 836 837 MPlug childPlugs[numChildren]; 838 for (unsigned int i = 0; i < numChildren; ++i) { 839 childPlugs[i] = plug.child(i, &status); 840 if (!status) return; 841 } 842 843 MObject childAttr[numChildren]; 844 for (unsigned int i = 0; i < numChildren; ++i) { 845 childAttr[i] = childPlugs[i].attribute(&status); 846 if (!status) return; 847 } 848 849 MFn::Type apiType = childAttr[0].apiType(); 850 switch (apiType) 851 { 852 case MFn::kDoubleAngleAttribute: 853 { 854 MAngle angles[numChildren]; 855 for (unsigned int i = 0; i < numChildren; ++i) { 856 angles[i] = childPlugs[i].asMAngle(MDGContext::fsNormal, &status); 857 if (!status) return; 858 } 859 onAngle2(plug, name, angles); 860 } 861 break; 862 case MFn::kDoubleLinearAttribute: 863 { 864 MDistance distances[numChildren]; 865 for (unsigned int i = 0; i < numChildren; ++i) { 866 distances[i] = childPlugs[i].asMDistance(MDGContext::fsNormal, &status); 867 if (!status) return; 868 } 869 onDistance2(plug, name, distances); 870 } 871 break; 872 default: 873 { 874 double values[numChildren]; 875 for (unsigned int i = 0; i < numChildren; ++i) { 876 values[i] = childPlugs[i].asDouble(MDGContext::fsNormal, &status); 877 if (!status) return; 878 } 879 onDouble2(plug, name, values); 880 } 881 break; 882 } 883 } 884 break; 885 case MFnNumericData::k3Double: //!< Three doubles. 886 { 887 const unsigned int numChildren = 3; 888 889 MPlug childPlugs[numChildren]; 890 for (unsigned int i = 0; i < numChildren; ++i) { 891 childPlugs[i] = plug.child(i, &status); 892 if (!status) return; 893 } 894 895 MObject childAttr[numChildren]; 896 for (unsigned int i = 0; i < numChildren; ++i) { 897 childAttr[i] = childPlugs[i].attribute(&status); 898 if (!status) return; 899 } 900 901 MFn::Type apiType = childAttr[0].apiType(); 902 switch (apiType) 903 { 904 case MFn::kDoubleAngleAttribute: 905 { 906 MAngle angles[numChildren]; 907 for (unsigned int i = 0; i < numChildren; ++i) { 908 angles[i] = childPlugs[i].asMAngle(MDGContext::fsNormal, &status); 909 if (!status) return; 910 } 911 onAngle3(plug, name, angles); 912 } 913 break; 914 case MFn::kDoubleLinearAttribute: 915 { 916 MDistance distances[numChildren]; 917 for (unsigned int i = 0; i < numChildren; ++i) { 918 distances[i] = childPlugs[i].asMDistance(MDGContext::fsNormal, &status); 919 if (!status) return; 920 } 921 onDistance3(plug, name, distances); 922 } 923 break; 924 default: 925 { 926 double values[numChildren]; 927 for (unsigned int i = 0; i < numChildren; ++i) { 928 values[i] = childPlugs[i].asDouble(MDGContext::fsNormal, &status); 929 if (!status) return; 930 } 931 onDouble3(plug, name, values); 932 } 933 break; 934 } 935 } 936 break; 937 case MFnNumericData::k4Double: //!< Four doubles. 938 { 939 const unsigned int numChildren = 4; 940 941 MPlug childPlugs[numChildren]; 942 for (unsigned int i = 0; i < numChildren; ++i) { 943 childPlugs[i] = plug.child(i, &status); 944 if (!status) return; 945 } 946 947 MObject childAttr[numChildren]; 948 for (unsigned int i = 0; i < numChildren; ++i) { 949 childAttr[i] = childPlugs[i].attribute(&status); 950 if (!status) return; 951 } 952 953 MFn::Type apiType = childAttr[0].apiType(); 954 switch (apiType) 955 { 956 case MFn::kDoubleAngleAttribute: 957 { 958 MAngle angles[numChildren]; 959 for (unsigned int i = 0; i < numChildren; ++i) { 960 angles[i] = childPlugs[i].asMAngle(MDGContext::fsNormal, &status); 961 if (!status) return; 962 } 963 onAngle4(plug, name, angles); 964 } 965 break; 966 case MFn::kDoubleLinearAttribute: 967 { 968 MDistance distances[numChildren]; 969 for (unsigned int i = 0; i < numChildren; ++i) { 970 distances[i] = childPlugs[i].asMDistance(MDGContext::fsNormal, &status); 971 if (!status) return; 972 } 973 onDistance4(plug, name, distances); 974 } 975 break; 976 default: 977 { 978 double values[numChildren]; 979 for (unsigned int i = 0; i < numChildren; ++i) { 980 values[i] = childPlugs[i].asDouble(MDGContext::fsNormal, &status); 981 if (!status) return; 982 } 983 onDouble4(plug, name, values); 984 } 985 break; 986 } 987 } 988 break; 989 case MFnNumericData::kAddr: //!< An address. 990 // TODO 991 break; 992 default: 993 break; 994 } 995 } 996 parseStringData(MPlug & plug)997 void AttributeParser::parseStringData(MPlug & plug) 998 { 999 MString value; 1000 MStatus status = plug.getValue(value); 1001 if (!status) return; 1002 1003 MObject attr = plug.attribute(&status); 1004 if (!status) return; 1005 1006 MFnAttribute fnAttr(attr, &status); 1007 if (!status) return; 1008 1009 MString name = fnAttr.name(&status); 1010 if (!status) return; 1011 1012 onString(plug, name, value); 1013 } 1014 parseMeshData(MPlug & plug)1015 void AttributeParser::parseMeshData(MPlug & plug) 1016 { 1017 MStatus status; 1018 1019 MObject meshNode; 1020 MPlugArray plugArray; 1021 bool success = plug.connectedTo(plugArray, true, false, &status); 1022 if (!status) return; 1023 if (success) 1024 { 1025 MPlug extPlug = plugArray[0]; 1026 bool hasConnection = !extPlug.isNull(&status); 1027 if (!status) return; 1028 if (hasConnection) 1029 { 1030 meshNode = extPlug.node(&status); 1031 if (!status) return; 1032 } 1033 } 1034 1035 //MDataHandle dataHandle; 1036 //status = plug.getValue(dataHandle); 1037 //if (!status) return; 1038 1039 //MObject meshData; 1040 //status = plug.getValue(meshData); 1041 //if (!status) return; 1042 1043 //MFnMesh fnMesh(meshData, &status); 1044 //if (!status) return; 1045 1046 //MDagPath dagPath = fnMesh.dagPath(&status); 1047 //if (!status) return; 1048 1049 //MObject meshNode = dagPath.node(&status); 1050 1051 MObject attr = plug.attribute(&status); 1052 if (!status) return; 1053 1054 MFnAttribute fnAttr(attr, &status); 1055 if (!status) return; 1056 1057 MString name = fnAttr.name(&status); 1058 if (!status) return; 1059 1060 onMesh(plug, name, meshNode); 1061 } 1062 parseComponentListData(MPlug & plug)1063 void AttributeParser::parseComponentListData(MPlug & plug) 1064 { 1065 MStatus status; 1066 1067 MFnComponentListData componentListData; 1068 1069 MObject objectData = componentListData.create(&status); 1070 if (!status) return; 1071 1072 status = plug.getValue(objectData); 1073 if (!status) return; 1074 1075 status = componentListData.setObject(objectData); 1076 if (!status) return; 1077 1078 unsigned int length = componentListData.length(&status); 1079 if (!status) return; 1080 1081 for (unsigned int i = 0; i < length; ++i) { 1082 MObject object = componentListData[i]; 1083 } 1084 1085 // TODO 1086 } 1087 IsNumericCompoundAttribute(const MObject & attr,MFnNumericData::Type & type)1088 bool AttributeParser::IsNumericCompoundAttribute(const MObject& attr, MFnNumericData::Type& type) 1089 { 1090 MFn::Type apiType = attr.apiType(); 1091 switch (apiType) 1092 { 1093 case MFn::kAttribute2Double: 1094 type = MFnNumericData::k2Double; 1095 return true; 1096 case MFn::kAttribute2Float: 1097 type = MFnNumericData::k2Float; 1098 return true; 1099 case MFn::kAttribute2Int: 1100 type = MFnNumericData::k2Int; 1101 return true; 1102 case MFn::kAttribute2Short: 1103 type = MFnNumericData::k2Short; 1104 return true; 1105 case MFn::kAttribute3Double: 1106 type = MFnNumericData::k3Double; 1107 return true; 1108 case MFn::kAttribute3Float: 1109 type = MFnNumericData::k3Float; 1110 return true; 1111 case MFn::kAttribute3Int: 1112 type = MFnNumericData::k3Int; 1113 return true; 1114 case MFn::kAttribute3Short: 1115 type = MFnNumericData::k3Short; 1116 return true; 1117 case MFn::kAttribute4Double: 1118 type = MFnNumericData::k4Double; 1119 return true; 1120 } 1121 return false; 1122 } 1123 } 1124