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