1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2013,
4 // Sony Pictures Imageworks Inc. and
5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // * Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic, nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36
37 #include "AttributesWriter.h"
38 #include "MayaUtility.h"
39
40 namespace Abc = Alembic::Abc;
41 namespace AbcGeom = Alembic::AbcGeom;
42 namespace AbcA = Alembic::AbcCoreAbstract;
43
44 namespace {
45
46 static const char * cAttrScope = "_AbcGeomScope";
47 static const char * cAttrType = "_AbcType";
48
scopeToString(AbcGeom::GeometryScope input)49 std::string scopeToString( AbcGeom::GeometryScope input )
50 {
51 switch(input)
52 {
53 case AbcGeom::kConstantScope: return "kConstantScope";
54 case AbcGeom::kFacevaryingScope:return "kFacevaryingScope";
55 case AbcGeom::kUniformScope: return "kUniformScope";
56 case AbcGeom::kUnknownScope: return "kUnknownScope";
57 case AbcGeom::kVaryingScope: return "kVaryingScope";
58 case AbcGeom::kVertexScope: return "kVertexScope";
59 }
60 return "kUnknownScope";
61 }
62
63 // returns true if a plug is of a simple numeric data type
isDataAttr(const MPlug & iParent)64 bool isDataAttr(const MPlug & iParent)
65 {
66 MObject obj = iParent.asMObject();
67 switch (obj.apiType())
68 {
69 case MFn::kData2Double:
70 case MFn::kData3Double:
71 case MFn::kData4Double:
72 case MFn::kData2Float:
73 case MFn::kData3Float:
74 case MFn::kData2Int:
75 case MFn::kData3Int:
76 case MFn::kData2Short:
77 case MFn::kData3Short:
78 case MFn::kStringData:
79 case MFn::kStringArrayData:
80 case MFn::kFloatVectorArrayData:
81 case MFn::kVectorArrayData:
82 case MFn::kFloatArrayData:
83 case MFn::kDoubleArrayData:
84 case MFn::kIntArrayData:
85 case MFn::kPointArrayData:
86 case MFn::kUInt64ArrayData:
87 return true;
88
89 default:
90 return false;
91 }
92 return false;
93 }
94
strToScope(MString iStr)95 AbcGeom::GeometryScope strToScope(MString iStr)
96 {
97 iStr.toLowerCase();
98 if (iStr == "vtx")
99 {
100 return AbcGeom::kVertexScope;
101 }
102 else if (iStr == "fvr")
103 {
104 return AbcGeom::kFacevaryingScope;
105 }
106 else if (iStr == "uni")
107 {
108 return AbcGeom::kUniformScope;
109 }
110 else if (iStr == "var")
111 {
112 return AbcGeom::kVaryingScope;
113 }
114
115 return AbcGeom::kConstantScope;
116 }
117
118 // returns true if the string ends with _AbcGeomScope or _AbcType
endsWithArbAttr(const std::string & iStr)119 bool endsWithArbAttr(const std::string & iStr)
120 {
121 size_t len = iStr.size();
122
123 return (len >= 13 && iStr.compare(len - 13, 13, cAttrScope) == 0) ||
124 (len >= 8 && iStr.compare(len - 8, 8, cAttrType) == 0);
125 }
126
createUserPropertyFromNumeric(MFnNumericData::Type iType,const MObject & iAttr,const MPlug & iPlug,Abc::OCompoundProperty & iParent,Alembic::Util::uint32_t iTimeIndex,AbcGeom::GeometryScope iScope,std::vector<PlugAndObjScalar> & oScalars,std::vector<PlugAndObjArray> & oArrays)127 void createUserPropertyFromNumeric(MFnNumericData::Type iType,
128 const MObject& iAttr,
129 const MPlug& iPlug,
130 Abc::OCompoundProperty & iParent,
131 Alembic::Util::uint32_t iTimeIndex,
132 AbcGeom::GeometryScope iScope,
133 std::vector < PlugAndObjScalar > & oScalars,
134 std::vector < PlugAndObjArray > & oArrays)
135 {
136 std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar();
137 switch (iType)
138 {
139 case MFnNumericData::kBoolean:
140 {
141 PlugAndObjScalar p;
142 p.plug = iPlug;
143 p.obj = iAttr;
144 Abc::OBoolProperty up(iParent, plugName, iTimeIndex);
145 p.prop = up;
146 oScalars.push_back(p);
147 }
148 break;
149
150 case MFnNumericData::kByte:
151 case MFnNumericData::kChar:
152 {
153 PlugAndObjScalar p;
154 p.plug = iPlug;
155 p.obj = iAttr;
156 Abc::OCharProperty up(iParent, plugName, iTimeIndex);
157 p.prop = up;
158 oScalars.push_back(p);
159 }
160 break;
161
162 case MFnNumericData::kShort:
163 {
164 PlugAndObjScalar p;
165 p.plug = iPlug;
166 p.obj = iAttr;
167 Abc::OInt16Property up(iParent, plugName, iTimeIndex);
168 p.prop = up;
169 oScalars.push_back(p);
170 }
171 break;
172
173 case MFnNumericData::kInt:
174 {
175 PlugAndObjScalar p;
176 p.plug = iPlug;
177 p.obj = iAttr;
178 Abc::OInt32Property up(iParent, plugName, iTimeIndex);
179 p.prop = up;
180 oScalars.push_back(p);
181 }
182 break;
183
184 case MFnNumericData::kFloat:
185 {
186 PlugAndObjScalar p;
187 p.plug = iPlug;
188 p.obj = iAttr;
189 Abc::OFloatProperty up(iParent, plugName, iTimeIndex);
190 p.prop = up;
191 oScalars.push_back(p);
192 }
193 break;
194
195 case MFnNumericData::kDouble:
196 {
197 PlugAndObjScalar p;
198 p.plug = iPlug;
199 p.obj = iAttr;
200 Abc::ODoubleProperty up(iParent, plugName, iTimeIndex);
201 p.prop = up;
202 oScalars.push_back(p);
203 }
204 break;
205
206 case MFnNumericData::k2Short:
207 {
208 PlugAndObjScalar p;
209 p.plug = iPlug;
210 p.obj = iAttr;
211 Abc::OV2sProperty up(iParent, plugName, iTimeIndex);
212 p.prop = up;
213 oScalars.push_back(p);
214 }
215 break;
216
217 case MFnNumericData::k3Short:
218 {
219 PlugAndObjScalar p;
220 p.plug = iPlug;
221 p.obj = iAttr;
222 Abc::OV3sProperty up(iParent, plugName, iTimeIndex);
223 p.prop = up;
224 oScalars.push_back(p);
225 }
226 break;
227
228 case MFnNumericData::k2Int:
229 {
230 PlugAndObjScalar p;
231 p.plug = iPlug;
232 p.obj = iAttr;
233 Abc::OV2iProperty up(iParent, plugName, iTimeIndex);
234 p.prop = up;
235 oScalars.push_back(p);
236 }
237 break;
238
239 case MFnNumericData::k3Int:
240 {
241 PlugAndObjScalar p;
242 p.plug = iPlug;
243 p.obj = iAttr;
244 Abc::OV3iProperty up(iParent, plugName, iTimeIndex);
245 p.prop = up;
246 oScalars.push_back(p);
247 }
248 break;
249
250 case MFnNumericData::k2Float:
251 {
252 PlugAndObjScalar p;
253 p.plug = iPlug;
254 p.obj = iAttr;
255 Abc::OV2fProperty up(iParent, plugName, iTimeIndex);
256 p.prop = up;
257 oScalars.push_back(p);
258 }
259 break;
260
261 case MFnNumericData::k3Float:
262 {
263 PlugAndObjScalar p;
264 p.plug = iPlug;
265 p.obj = iAttr;
266 Abc::OV3fProperty up(iParent, plugName, iTimeIndex);
267 p.prop = up;
268 oScalars.push_back(p);
269 }
270 break;
271
272 case MFnNumericData::k2Double:
273 {
274 PlugAndObjScalar p;
275 p.plug = iPlug;
276 p.obj = iAttr;
277 Abc::OV2dProperty up(iParent, plugName, iTimeIndex);
278 p.prop = up;
279 oScalars.push_back(p);
280 }
281 break;
282
283 case MFnNumericData::k3Double:
284 {
285 PlugAndObjScalar p;
286 p.plug = iPlug;
287 p.obj = iAttr;
288 Abc::OV3dProperty up(iParent, plugName, iTimeIndex);
289 p.prop = up;
290 oScalars.push_back(p);
291 }
292 break;
293
294 case MFnNumericData::k4Double:
295 {
296 PlugAndObjArray p;
297 p.plug = iPlug;
298 p.obj = iAttr;
299 AbcA::DataType dtype(Alembic::Util::kFloat64POD, 4);
300 Abc::OArrayProperty up(iParent, plugName, dtype, iTimeIndex);
301 p.prop = up;
302 oArrays.push_back(p);
303 }
304 break;
305
306 default:
307 break;
308 }
309 }
310
createGeomPropertyFromNumeric(MFnNumericData::Type iType,const MObject & iAttr,const MPlug & iPlug,Abc::OCompoundProperty & iParent,Alembic::Util::uint32_t iTimeIndex,AbcGeom::GeometryScope iScope,std::vector<PlugAndObjArray> & oArrayVec)311 void createGeomPropertyFromNumeric(MFnNumericData::Type iType, const MObject& iAttr,
312 const MPlug& iPlug, Abc::OCompoundProperty & iParent,
313 Alembic::Util::uint32_t iTimeIndex,
314 AbcGeom::GeometryScope iScope,
315 std::vector < PlugAndObjArray > & oArrayVec)
316 {
317 std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar();
318 switch (iType)
319 {
320 case MFnNumericData::kBoolean:
321 {
322 PlugAndObjArray p;
323 p.plug = iPlug;
324 p.obj = iAttr;
325 AbcGeom::OBoolGeomParam gp(iParent, plugName, false, iScope, 1,
326 iTimeIndex);
327 p.prop = gp.getValueProperty();
328 oArrayVec.push_back(p);
329 }
330 break;
331
332 case MFnNumericData::kByte:
333 case MFnNumericData::kChar:
334 {
335 PlugAndObjArray p;
336 p.plug = iPlug;
337 p.obj = iAttr;
338 AbcGeom::OCharGeomParam gp(iParent, plugName, false, iScope, 1,
339 iTimeIndex);
340 p.prop = gp.getValueProperty();
341 oArrayVec.push_back(p);
342 }
343 break;
344
345 case MFnNumericData::kShort:
346 {
347 PlugAndObjArray p;
348 p.plug = iPlug;
349 p.obj = iAttr;
350 AbcGeom::OInt16GeomParam gp(iParent, plugName, false, iScope, 1,
351 iTimeIndex);
352 p.prop = gp.getValueProperty();
353 oArrayVec.push_back(p);
354 }
355 break;
356
357 case MFnNumericData::kInt:
358 {
359 PlugAndObjArray p;
360 p.plug = iPlug;
361 p.obj = iAttr;
362 AbcGeom::OInt32GeomParam gp(iParent, plugName, false, iScope, 1,
363 iTimeIndex);
364 p.prop = gp.getValueProperty();
365 oArrayVec.push_back(p);
366 }
367 break;
368
369 case MFnNumericData::kFloat:
370 {
371 PlugAndObjArray p;
372 p.plug = iPlug;
373 p.obj = iAttr;
374 AbcGeom::OFloatGeomParam gp(iParent, plugName, false, iScope, 1,
375 iTimeIndex);
376 p.prop = gp.getValueProperty();
377 oArrayVec.push_back(p);
378 }
379 break;
380
381 case MFnNumericData::kDouble:
382 {
383 PlugAndObjArray p;
384 p.plug = iPlug;
385 p.obj = iAttr;
386 AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope, 1,
387 iTimeIndex);
388 p.prop = gp.getValueProperty();
389 oArrayVec.push_back(p);
390 }
391 break;
392
393 case MFnNumericData::k2Short:
394 {
395 PlugAndObjArray p;
396 p.plug = iPlug;
397 p.obj = iAttr;
398 AbcGeom::OV2sGeomParam gp(iParent, plugName, false, iScope, 1,
399 iTimeIndex);
400 p.prop = gp.getValueProperty();
401 oArrayVec.push_back(p);
402 }
403 break;
404
405 case MFnNumericData::k3Short:
406 {
407 PlugAndObjArray p;
408 p.plug = iPlug;
409 p.obj = iAttr;
410 AbcGeom::OV3sGeomParam gp(iParent, plugName, false, iScope, 1,
411 iTimeIndex);
412 p.prop = gp.getValueProperty();
413 oArrayVec.push_back(p);
414 }
415 break;
416
417 case MFnNumericData::k2Int:
418 {
419 PlugAndObjArray p;
420 p.plug = iPlug;
421 p.obj = iAttr;
422 AbcGeom::OV2iGeomParam gp(iParent, plugName, false, iScope, 1,
423 iTimeIndex);
424 p.prop = gp.getValueProperty();
425 oArrayVec.push_back(p);
426 }
427 break;
428
429 case MFnNumericData::k3Int:
430 {
431 PlugAndObjArray p;
432 p.plug = iPlug;
433 p.obj = iAttr;
434 AbcGeom::OV3iGeomParam gp(iParent, plugName, false, iScope, 1,
435 iTimeIndex);
436 p.prop = gp.getValueProperty();
437 oArrayVec.push_back(p);
438 }
439 break;
440
441 case MFnNumericData::k2Float:
442 {
443 PlugAndObjArray p;
444 p.plug = iPlug;
445 p.obj = iAttr;
446 AbcGeom::OV2fGeomParam gp(iParent, plugName, false, iScope, 1,
447 iTimeIndex);
448 p.prop = gp.getValueProperty();
449 oArrayVec.push_back(p);
450 }
451 break;
452
453 case MFnNumericData::k3Float:
454 {
455 PlugAndObjArray p;
456 p.plug = iPlug;
457 p.obj = iAttr;
458
459 MFnAttribute mfnAttr(iAttr);
460 if (mfnAttr.isUsedAsColor())
461 {
462 AbcGeom::OC3fGeomParam gp(iParent, plugName, false, iScope, 1,
463 iTimeIndex);
464 p.prop = gp.getValueProperty();
465 }
466 else
467 {
468 AbcGeom::OV3fGeomParam gp(iParent, plugName, false, iScope, 1,
469 iTimeIndex);
470 p.prop = gp.getValueProperty();
471 }
472
473 oArrayVec.push_back(p);
474 }
475 break;
476
477 case MFnNumericData::k2Double:
478 {
479 PlugAndObjArray p;
480 p.plug = iPlug;
481 p.obj = iAttr;
482 AbcGeom::OV2dGeomParam gp(iParent, plugName, false, iScope, 1,
483 iTimeIndex);
484 p.prop = gp.getValueProperty();
485 oArrayVec.push_back(p);
486 }
487 break;
488
489 case MFnNumericData::k3Double:
490 {
491 PlugAndObjArray p;
492 p.plug = iPlug;
493 p.obj = iAttr;
494 AbcGeom::OV3dGeomParam gp(iParent, plugName, false, iScope, 1,
495 iTimeIndex);
496 p.prop = gp.getValueProperty();
497 oArrayVec.push_back(p);
498 }
499 break;
500
501 case MFnNumericData::k4Double:
502 {
503 PlugAndObjArray p;
504 p.plug = iPlug;
505 p.obj = iAttr;
506 AbcA::DataType dtype(Alembic::Util::kFloat64POD, 4);
507 p.prop = Abc::OArrayProperty(iParent, plugName, dtype, iTimeIndex);
508 oArrayVec.push_back(p);
509 }
510 break;
511
512 default:
513 break;
514 }
515 }
516
MFnNumericDataToSample(MFnNumericData::Type iType,const MPlug & iPlug,Abc::OScalarProperty & oProp)517 bool MFnNumericDataToSample(MFnNumericData::Type iType,
518 const MPlug& iPlug,
519 Abc::OScalarProperty & oProp)
520 {
521 int ival;
522 float fval;
523 double dval;
524 bool bval;
525 Alembic::Util::int16_t sval;
526 Alembic::Util::int8_t cval;
527
528 Alembic::Util::int16_t v2sVal[2];
529 Alembic::Util::int16_t v3sVal[3];
530
531 Alembic::Util::int32_t v2iVal[2];
532 Alembic::Util::int32_t v3iVal[3];
533
534 float v2fVal[2];
535 float v3fVal[3];
536
537 double v2dVal[2];
538 double v3dVal[3];
539
540 switch (iType)
541 {
542 case MFnNumericData::kBoolean:
543 {
544 bval = iPlug.asBool();
545 oProp.set(&bval);
546 }
547 break;
548
549 case MFnNumericData::kByte:
550 case MFnNumericData::kChar:
551 {
552 cval = iPlug.asChar();
553 oProp.set(&cval);
554 }
555 break;
556
557 case MFnNumericData::kShort:
558 {
559 sval = iPlug.asShort();
560 oProp.set(&sval);
561 }
562 break;
563
564 case MFnNumericData::kInt:
565 {
566 ival = iPlug.asInt();
567 oProp.set(&ival);
568 }
569 break;
570
571 case MFnNumericData::kFloat:
572 {
573 fval = iPlug.asFloat();
574 oProp.set(&fval);
575 }
576 break;
577
578 case MFnNumericData::kDouble:
579 {
580 dval = iPlug.asDouble();
581 oProp.set(&dval);
582 }
583 break;
584
585 case MFnNumericData::k2Short:
586 {
587 MFnNumericData numdFn(iPlug.asMObject());
588 numdFn.getData2Short(v2sVal[0], v2sVal[1]);
589
590 oProp.set(&v2sVal[0]);
591 }
592 break;
593
594 case MFnNumericData::k3Short:
595 {
596 MFnNumericData numdFn(iPlug.asMObject());
597 numdFn.getData3Short(v3sVal[0], v3sVal[1], v3sVal[2]);
598
599 oProp.set(&v3sVal[0]);
600 }
601 break;
602
603 case MFnNumericData::k2Int:
604 {
605 int val0, val1;
606 MFnNumericData numdFn(iPlug.asMObject());
607 numdFn.getData2Int(val0, val1);
608 v2iVal[0] = Alembic::Util::int32_t(val0);
609 v2iVal[1] = Alembic::Util::int32_t(val1);
610
611 oProp.set(&v2iVal[0]);
612 }
613 break;
614
615 case MFnNumericData::k3Int:
616 {
617 int val0, val1, val2;
618 MFnNumericData numdFn(iPlug.asMObject());
619 numdFn.getData3Int(val0, val1, val2);
620 v3iVal[0] = Alembic::Util::int32_t(val0);
621 v3iVal[1] = Alembic::Util::int32_t(val1);
622 v3iVal[2] = Alembic::Util::int32_t(val2);
623
624 oProp.set(&v3iVal[0]);
625 }
626 break;
627
628 case MFnNumericData::k2Float:
629 {
630 MFnNumericData numdFn(iPlug.asMObject());
631 numdFn.getData2Float(v2fVal[0], v2fVal[1]);
632
633 oProp.set(&v2fVal[0]);
634 }
635 break;
636
637 case MFnNumericData::k3Float:
638 {
639 MFnNumericData numdFn(iPlug.asMObject());
640 numdFn.getData3Float(v3fVal[0], v3fVal[1], v3fVal[2]);
641
642 oProp.set(&v3fVal[0]);
643 }
644 break;
645
646 case MFnNumericData::k2Double:
647 {
648 MFnNumericData numdFn(iPlug.asMObject());
649 numdFn.getData2Double(v2dVal[0], v3dVal[1]);
650
651 oProp.set(&v2dVal[0]);
652 }
653 break;
654
655 case MFnNumericData::k3Double:
656 {
657 MFnNumericData numdFn(iPlug.asMObject());
658 numdFn.getData3Double(v3dVal[0], v3dVal[1], v3dVal[2]);
659
660 oProp.set(&v3dVal[0]);
661 }
662 break;
663
664 default:
665 return false;
666 break;
667 }
668
669 return true;
670 }
671
MFnNumericDataToSample(MFnNumericData::Type iType,const MPlug & iPlug,Abc::OArrayProperty & oProp)672 bool MFnNumericDataToSample(MFnNumericData::Type iType,
673 const MPlug& iPlug,
674 Abc::OArrayProperty & oProp)
675 {
676 unsigned int numElements = iPlug.numElements();
677 bool isArray = iPlug.isArray();
678
679 unsigned int dimSize = numElements;
680 if (!isArray)
681 dimSize = 1;
682
683 switch (iType)
684 {
685 case MFnNumericData::kBoolean:
686 {
687 std::vector< Alembic::Util::bool_t > val(dimSize);
688 if (!isArray)
689 {
690 val[0] = iPlug.asBool();
691 }
692 else
693 {
694 for (unsigned int i = 0; i < numElements; ++i)
695 {
696 val[i] = iPlug[i].asBool();
697 }
698 }
699 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
700 Alembic::Util::Dimensions(dimSize));
701 oProp.set(samp);
702 }
703 break;
704
705 case MFnNumericData::kByte:
706 case MFnNumericData::kChar:
707 {
708 std::vector< Alembic::Util::int8_t > val(dimSize);
709 if (!isArray)
710 {
711 val[0] = iPlug.asChar();
712 }
713 else
714 {
715 for (unsigned int i = 0; i < numElements; ++i)
716 {
717 val[i] = iPlug[i].asChar();
718 }
719 }
720 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
721 Alembic::Util::Dimensions(dimSize));
722 oProp.set(samp);
723 }
724 break;
725
726 case MFnNumericData::kShort:
727 {
728 std::vector< Alembic::Util::int16_t > val(dimSize);
729 if (!isArray)
730 {
731 val[0] = iPlug.asShort();
732 }
733 else
734 {
735 for (unsigned int i = 0; i < numElements; ++i)
736 {
737 val[i] = iPlug[i].asShort();
738 }
739 }
740 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
741 Alembic::Util::Dimensions(dimSize));
742 oProp.set(samp);
743 }
744 break;
745
746 case MFnNumericData::kInt:
747 {
748 std::vector< Alembic::Util::int32_t > val(dimSize);
749 if (!isArray)
750 {
751 val[0] = iPlug.asInt();
752 }
753 else
754 {
755 for (unsigned int i = 0; i < numElements; ++i)
756 {
757 val[i] = iPlug[i].asInt();
758 }
759 }
760 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
761 Alembic::Util::Dimensions(dimSize));
762 oProp.set(samp);
763 }
764 break;
765
766 case MFnNumericData::kFloat:
767 {
768 std::vector<float> val(dimSize);
769 if (!isArray)
770 {
771 val[0] = iPlug.asFloat();
772 }
773 else
774 {
775 for (unsigned int i = 0; i < numElements; ++i)
776 {
777 val[i] = iPlug[i].asFloat();
778 }
779 }
780 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
781 Alembic::Util::Dimensions(dimSize));
782 oProp.set(samp);
783 }
784 break;
785
786 case MFnNumericData::kDouble:
787 {
788 std::vector<double> val(dimSize);
789 if (!isArray)
790 {
791 val[0] = iPlug.asDouble();
792 }
793 else
794 {
795 for (unsigned int i = 0; i < numElements; ++i)
796 {
797 val[i] = iPlug[i].asDouble();
798 }
799 }
800 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
801 Alembic::Util::Dimensions(dimSize));
802 oProp.set(samp);
803 }
804 break;
805
806 case MFnNumericData::k2Short:
807 {
808 std::vector< Alembic::Util::int16_t > val(dimSize*2);
809 if (!isArray)
810 {
811 MFnNumericData numdFn(iPlug.asMObject());
812 numdFn.getData2Short(val[0], val[1]);
813 }
814 else
815 {
816 for (unsigned int i = 0; i < numElements; ++i)
817 {
818 MFnNumericData numdFn(iPlug[i].asMObject());
819 numdFn.getData2Short(val[2*i], val[2*i+1]);
820 }
821 }
822 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
823 Alembic::Util::Dimensions(dimSize));
824 oProp.set(samp);
825 }
826 break;
827
828 case MFnNumericData::k3Short:
829 {
830 std::vector< Alembic::Util::int16_t > val(dimSize*3);
831 if (!isArray)
832 {
833 MFnNumericData numdFn(iPlug.asMObject());
834 numdFn.getData3Short(val[0], val[1], val[2]);
835 }
836 else
837 {
838 for (unsigned int i = 0; i < numElements; ++i)
839 {
840 MFnNumericData numdFn(iPlug[i].asMObject());
841 numdFn.getData3Short(val[3*i], val[3*i+1], val[3*i+2]);
842 }
843 }
844 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
845 Alembic::Util::Dimensions(dimSize));
846 oProp.set(samp);
847 }
848 break;
849
850 case MFnNumericData::k2Int:
851 {
852 std::vector< Alembic::Util::int32_t > val(dimSize*2);
853 if (!isArray)
854 {
855 int val0, val1;
856 MFnNumericData numdFn(iPlug.asMObject());
857 numdFn.getData2Int(val0, val1);
858 val[0] = Alembic::Util::int32_t(val0);
859 val[1] = Alembic::Util::int32_t(val1);
860 }
861 else
862 {
863 for (unsigned int i = 0; i < numElements; ++i)
864 {
865 int val0, val1;
866 MFnNumericData numdFn(iPlug[i].asMObject());
867 numdFn.getData2Int(val0, val1);
868 val[2*i] = Alembic::Util::int32_t(val0);
869 val[2*i+1] = Alembic::Util::int32_t(val1);
870 }
871 }
872 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
873 Alembic::Util::Dimensions(dimSize));
874 oProp.set(samp);
875 }
876 break;
877
878 case MFnNumericData::k3Int:
879 {
880 std::vector< Alembic::Util::int32_t > val(dimSize*3);
881 if (!isArray)
882 {
883 int val0, val1, val2;
884 MFnNumericData numdFn(iPlug.asMObject());
885 numdFn.getData3Int(val0, val1, val2);
886 val[0] = Alembic::Util::int32_t(val0);
887 val[1] = Alembic::Util::int32_t(val1);
888 val[2] = Alembic::Util::int32_t(val2);
889 }
890 else
891 {
892 for (unsigned int i = 0; i < numElements; ++i)
893 {
894 int val0, val1, val2;
895 MFnNumericData numdFn(iPlug[i].asMObject());
896 numdFn.getData3Int(val0, val1, val2);
897 val[3*i] = Alembic::Util::int32_t(val0);
898 val[3*i+1] = Alembic::Util::int32_t(val1);
899 val[3*i+2] = Alembic::Util::int32_t(val2);
900 }
901 }
902 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
903 Alembic::Util::Dimensions(dimSize));
904 oProp.set(samp);
905 }
906 break;
907
908 case MFnNumericData::k2Float:
909 {
910 std::vector<float> val(dimSize*2);
911 if (!isArray)
912 {
913 MFnNumericData numdFn(iPlug.asMObject());
914 numdFn.getData2Float(val[0], val[1]);
915 }
916 else
917 {
918 for (unsigned int i = 0; i < numElements; ++i)
919 {
920 MFnNumericData numdFn(iPlug[i].asMObject());
921 numdFn.getData2Float(val[2*i], val[2*i+1]);
922 }
923 }
924 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
925 Alembic::Util::Dimensions(dimSize));
926 oProp.set(samp);
927 }
928 break;
929
930 case MFnNumericData::k3Float:
931 {
932 std::vector<float> val(dimSize*3);
933 if (!isArray)
934 {
935 MFnNumericData numdFn(iPlug.asMObject());
936 numdFn.getData3Float(val[0], val[1], val[2]);
937 }
938 else
939 {
940 for (unsigned int i = 0; i < numElements; ++i)
941 {
942 MFnNumericData numdFn(iPlug[i].asMObject());
943 numdFn.getData3Float(val[3*i], val[3*i+1], val[3*i+2]);
944 }
945 }
946 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
947 Alembic::Util::Dimensions(dimSize));
948 oProp.set(samp);
949 }
950 break;
951
952 case MFnNumericData::k2Double:
953 {
954 std::vector<double> val(dimSize*2);
955 if (!isArray)
956 {
957 MFnNumericData numdFn(iPlug.asMObject());
958 numdFn.getData2Double(val[0], val[1]);
959 }
960 else
961 {
962 for (unsigned int i = 0; i < numElements; ++i)
963 {
964 MFnNumericData numdFn(iPlug[i].asMObject());
965 numdFn.getData2Double(val[2*i], val[2*i+1]);
966 }
967 }
968 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
969 Alembic::Util::Dimensions(dimSize));
970 oProp.set(samp);
971 }
972 break;
973
974 case MFnNumericData::k3Double:
975 {
976 std::vector<double> val(dimSize*3);
977 if (!isArray)
978 {
979 MFnNumericData numdFn(iPlug.asMObject());
980 numdFn.getData3Double(val[0], val[1], val[2]);
981 }
982 else
983 {
984 for (unsigned int i = 0; i < numElements; ++i)
985 {
986 MFnNumericData numdFn(iPlug[i].asMObject());
987 numdFn.getData3Double(val[3*i], val[3*i+1], val[3*i+2]);
988 }
989 }
990 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
991 Alembic::Util::Dimensions(dimSize));
992 oProp.set(samp);
993 }
994 break;
995
996 case MFnNumericData::k4Double:
997 {
998 std::vector<double> val(dimSize*4);
999 if (!isArray)
1000 {
1001 MFnNumericData numdFn(iPlug.asMObject());
1002 numdFn.getData4Double(val[0], val[1], val[2], val[3]);
1003 }
1004 else
1005 {
1006 for (unsigned int i = 0; i < numElements; ++i)
1007 {
1008 MFnNumericData numdFn(iPlug[i].asMObject());
1009 numdFn.getData4Double(val[4*i], val[4*i+1], val[4*i+2],
1010 val[4*i+3]);
1011 }
1012 }
1013 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1014 Alembic::Util::Dimensions(dimSize));
1015 oProp.set(samp);
1016 }
1017 break;
1018
1019 default:
1020 return false;
1021 break;
1022 }
1023
1024 return true;
1025 }
1026
MFnTypedDataToSample(MFnData::Type iType,const MPlug & iPlug,Abc::OScalarProperty & oProp)1027 bool MFnTypedDataToSample(MFnData::Type iType,
1028 const MPlug& iPlug,
1029 Abc::OScalarProperty & oProp)
1030 {
1031 switch (iType)
1032 {
1033 case MFnData::kNumeric:
1034 {
1035 MFnNumericData numObj(iPlug.asMObject());
1036 return MFnNumericDataToSample(numObj.numericType(), iPlug,
1037 oProp);
1038 }
1039 break;
1040
1041 case MFnData::kString:
1042 {
1043 Abc::OStringProperty strProp( oProp.getPtr(), Abc::kWrapExisting );
1044 std::string val = iPlug.asString().asChar();
1045 strProp.set(val);
1046 }
1047 break;
1048
1049 case MFnData::kMatrix:
1050 {
1051 MFnMatrixData arr(iPlug.asMObject());
1052 MMatrix mat = arr.matrix();
1053 double val[16];
1054
1055 unsigned int i = 0;
1056 for (unsigned int r = 0; r < 4; r++)
1057 {
1058 for (unsigned int c = 0; c < 4; c++, i++)
1059 {
1060 val[i] = mat[r][c];
1061 }
1062 }
1063
1064 oProp.set(&val);
1065 }
1066 break;
1067
1068 default:
1069 return false;
1070 break;
1071 }
1072
1073 return true;
1074 }
1075
MFnTypedDataToSample(MFnData::Type iType,const MPlug & iPlug,Abc::OArrayProperty & oProp)1076 bool MFnTypedDataToSample(MFnData::Type iType,
1077 const MPlug& iPlug,
1078 Abc::OArrayProperty & oProp)
1079 {
1080 switch (iType)
1081 {
1082 case MFnData::kNumeric:
1083 {
1084 MFnNumericData numObj(iPlug.asMObject());
1085 return MFnNumericDataToSample(numObj.numericType(), iPlug,
1086 oProp);
1087 }
1088 break;
1089
1090 case MFnData::kString:
1091 {
1092 std::vector< std::string > val(1);
1093 val[0] = iPlug.asString().asChar();
1094 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1095 Alembic::Util::Dimensions(1));
1096 oProp.set(samp);
1097 }
1098 break;
1099
1100 case MFnData::kStringArray:
1101 {
1102 MFnStringArrayData arr(iPlug.asMObject());
1103
1104 unsigned int length = arr.length();
1105 std::vector< std::string > val(length);
1106 for (unsigned int i = 0; i < length; i++)
1107 {
1108 val[i] = arr[i].asChar();
1109 }
1110 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1111 Alembic::Util::Dimensions(length));
1112 oProp.set(samp);
1113 }
1114 break;
1115
1116 case MFnData::kDoubleArray:
1117 {
1118 MFnDoubleArrayData arr(iPlug.asMObject());
1119
1120 unsigned int length = arr.length();
1121 std::vector< double > val(length);
1122 for (unsigned int i = 0; i < length; i++)
1123 {
1124 val[i] = arr[i];
1125 }
1126 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1127 Alembic::Util::Dimensions(length));
1128 oProp.set(samp);
1129 }
1130 break;
1131
1132 case MFnData::kFloatArray:
1133 {
1134 MFnFloatArrayData arr(iPlug.asMObject());
1135
1136 unsigned int length = arr.length();
1137 std::vector< float > val(length);
1138 for (unsigned int i = 0; i < length; i++)
1139 {
1140 val[i] = arr[i];
1141 }
1142 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1143 Alembic::Util::Dimensions(length));
1144 oProp.set(samp);
1145 }
1146 break;
1147
1148 case MFnData::kIntArray:
1149 {
1150 MFnIntArrayData arr(iPlug.asMObject());
1151
1152 unsigned int length = arr.length();
1153 std::vector< Alembic::Util::int32_t > val(length);
1154 for (unsigned int i = 0; i < length; i++)
1155 {
1156 val[i] = arr[i];
1157 }
1158 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1159 Alembic::Util::Dimensions(length));
1160 oProp.set(samp);
1161 }
1162 break;
1163
1164 case MFnData::kPointArray:
1165 {
1166 MFnPointArrayData arr(iPlug.asMObject());
1167
1168 unsigned int length = arr.length();
1169 unsigned int extent = oProp.getDataType().getExtent();
1170 std::vector< double > val(length*extent);
1171 for (unsigned int i = 0; i < length; i++)
1172 {
1173 MPoint pt(arr[i]);
1174 val[extent*i] = pt.x;
1175 val[extent*i+1] = pt.y;
1176
1177 if (extent > 2)
1178 val[extent*i+2] = pt.z;
1179
1180 if (extent > 3)
1181 val[extent*i+3] = pt.w;
1182 }
1183 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1184 Alembic::Util::Dimensions(length));
1185 oProp.set(samp);
1186 }
1187 break;
1188
1189 case MFnData::kVectorArray:
1190 {
1191 MFnVectorArrayData arr(iPlug.asMObject());
1192
1193 unsigned int length = arr.length();
1194 unsigned int extent = oProp.getDataType().getExtent();
1195 std::vector< double > val(length*extent);
1196 for (unsigned int i = 0; i < length; i++)
1197 {
1198 MVector v(arr[i]);
1199 val[extent*i] = v.x;
1200 val[extent*i+1] = v.y;
1201
1202 if (extent > 2)
1203 val[extent*i+2] = v.z;
1204 }
1205 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1206 Alembic::Util::Dimensions(length));
1207 oProp.set(samp);
1208 }
1209 break;
1210
1211 case MFnData::kMatrix:
1212 {
1213 MFnMatrixData arr(iPlug.asMObject());
1214 MMatrix mat = arr.matrix();
1215 std::vector<double> val(16);
1216
1217 unsigned int i = 0;
1218 for (unsigned int r = 0; r < 4; r++)
1219 {
1220 for (unsigned int c = 0; c < 4; c++, i++)
1221 {
1222 val[i] = mat[r][c];
1223 }
1224 }
1225 AbcA::ArraySample samp(&(val.front()), oProp.getDataType(),
1226 Alembic::Util::Dimensions(1));
1227 oProp.set(samp);
1228 }
1229 break;
1230
1231 default:
1232 return false;
1233 break;
1234 }
1235
1236 return true;
1237 }
1238
attributeToScalarPropertyPair(const MObject & iAttr,const MPlug & iPlug,Abc::OScalarProperty & oProp)1239 bool attributeToScalarPropertyPair(const MObject& iAttr,
1240 const MPlug& iPlug,
1241 Abc::OScalarProperty & oProp)
1242 {
1243 if (iAttr.hasFn(MFn::kTypedAttribute))
1244 {
1245 MFnTypedAttribute typedAttr(iAttr);
1246 return MFnTypedDataToSample(typedAttr.attrType(), iPlug, oProp);
1247 }
1248 else if (iAttr.hasFn(MFn::kNumericAttribute))
1249 {
1250 MFnNumericAttribute numAttr(iAttr);
1251 return MFnNumericDataToSample(numAttr.unitType(), iPlug, oProp);
1252 }
1253 else if (iAttr.hasFn(MFn::kUnitAttribute))
1254 {
1255 double dval = iPlug.asDouble();
1256 oProp.set(&dval);
1257 return true;
1258 }
1259 else if (iAttr.hasFn(MFn::kEnumAttribute))
1260 {
1261 Alembic::Util::int16_t val = iPlug.asShort();
1262 oProp.set(&val);
1263 return true;
1264 }
1265
1266 return false;
1267 }
1268
1269
attributeToArrayPropertyPair(const MObject & iAttr,const MPlug & iPlug,Abc::OArrayProperty & oProp)1270 bool attributeToArrayPropertyPair(const MObject& iAttr,
1271 const MPlug& iPlug,
1272 Abc::OArrayProperty & oProp)
1273 {
1274 if (iAttr.hasFn(MFn::kTypedAttribute))
1275 {
1276 MFnTypedAttribute typedAttr(iAttr);
1277 return MFnTypedDataToSample(typedAttr.attrType(), iPlug,
1278 oProp);
1279 }
1280 else if (iAttr.hasFn(MFn::kNumericAttribute))
1281 {
1282 MFnNumericAttribute numAttr(iAttr);
1283 return MFnNumericDataToSample(numAttr.unitType(), iPlug,
1284 oProp);
1285 }
1286 else if (iAttr.hasFn(MFn::kUnitAttribute))
1287 {
1288 double val = iPlug.asDouble();
1289 AbcA::ArraySample samp(&val, oProp.getDataType(),
1290 Alembic::Util::Dimensions(1));
1291 oProp.set(samp);
1292 return true;
1293 }
1294 else if (iAttr.hasFn(MFn::kEnumAttribute))
1295 {
1296 Alembic::Util::int16_t val = iPlug.asShort();
1297 AbcA::ArraySample samp(&val, oProp.getDataType(),
1298 Alembic::Util::Dimensions(1));
1299 oProp.set(samp);
1300 return true;
1301 }
1302
1303 return false;
1304 }
1305
createUserPropertyFromMFnAttr(const MObject & iAttr,const MPlug & iPlug,Abc::OCompoundProperty & iParent,Alembic::Util::uint32_t iTimeIndex,AbcGeom::GeometryScope iScope,const MString & iTypeStr,std::vector<PlugAndObjScalar> & oScalars,std::vector<PlugAndObjArray> & oArrays)1306 void createUserPropertyFromMFnAttr(const MObject& iAttr,
1307 const MPlug& iPlug,
1308 Abc::OCompoundProperty & iParent,
1309 Alembic::Util::uint32_t iTimeIndex,
1310 AbcGeom::GeometryScope iScope,
1311 const MString & iTypeStr,
1312 std::vector < PlugAndObjScalar > & oScalars,
1313 std::vector < PlugAndObjArray > & oArrays)
1314 {
1315 MStatus stat;
1316 std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar();
1317
1318 if (iAttr.hasFn(MFn::kNumericAttribute))
1319 {
1320 MFnNumericAttribute numFn(iAttr, &stat);
1321
1322 if (!stat)
1323 {
1324 MString err = "Couldn't instantiate MFnNumericAttribute\n\tType: ";
1325 err += iAttr.apiTypeStr();
1326 MGlobal::displayError(err);
1327
1328 return;
1329 }
1330
1331 createUserPropertyFromNumeric(numFn.unitType(), iAttr, iPlug,
1332 iParent, iTimeIndex, iScope,
1333 oScalars, oArrays);
1334 }
1335 else if (iAttr.hasFn(MFn::kTypedAttribute))
1336 {
1337 MFnTypedAttribute typeFn(iAttr, &stat);
1338
1339 if (!stat)
1340 {
1341 MString err = "Couldn't instantiate MFnTypedAttribute\n\tType: ";
1342 err += iAttr.apiTypeStr();
1343
1344 MGlobal::displayError(err);
1345
1346 return;
1347 }
1348
1349 switch (typeFn.attrType())
1350 {
1351 case MFnData::kString:
1352 {
1353 PlugAndObjScalar p;
1354 p.plug = iPlug;
1355 p.obj = iAttr;
1356 p.prop = Abc::OStringProperty(iParent, plugName, iTimeIndex);
1357 oScalars.push_back(p);
1358 }
1359 break;
1360
1361 case MFnData::kStringArray:
1362 {
1363 PlugAndObjArray p;
1364 p.plug = iPlug;
1365 p.obj = iAttr;
1366 p.prop = Abc::OStringArrayProperty(iParent, plugName, iTimeIndex);
1367 oArrays.push_back(p);
1368 }
1369 break;
1370
1371 case MFnData::kDoubleArray:
1372 {
1373 PlugAndObjArray p;
1374 p.plug = iPlug;
1375 p.obj = iAttr;
1376 p.prop = Abc::ODoubleArrayProperty(iParent, plugName, iTimeIndex);
1377 oArrays.push_back(p);
1378 }
1379 break;
1380
1381 case MFnData::kFloatArray:
1382 {
1383 PlugAndObjArray p;
1384 p.plug = iPlug;
1385 p.obj = iAttr;
1386 p.prop = Abc::OFloatArrayProperty(iParent, plugName, iTimeIndex);
1387 oArrays.push_back(p);
1388 }
1389 break;
1390
1391 case MFnData::kIntArray:
1392 {
1393 PlugAndObjArray p;
1394 p.plug = iPlug;
1395 p.obj = iAttr;
1396 p.prop = Abc::OInt32ArrayProperty(iParent, plugName, iTimeIndex);
1397 oArrays.push_back(p);
1398 }
1399 break;
1400
1401 case MFnData::kPointArray:
1402 {
1403 PlugAndObjArray p;
1404 p.plug = iPlug;
1405 p.obj = iAttr;
1406 if (iTypeStr == "point2")
1407 p.prop = Abc::OP2dArrayProperty(iParent, plugName, iTimeIndex);
1408 else
1409 p.prop = Abc::OP3dArrayProperty(iParent, plugName, iTimeIndex);
1410
1411 oArrays.push_back(p);
1412 }
1413 break;
1414
1415 case MFnData::kVectorArray:
1416 {
1417 PlugAndObjArray p;
1418 p.plug = iPlug;
1419 p.obj = iAttr;
1420 if (iTypeStr == "vector2")
1421 p.prop = Abc::OV2dArrayProperty(iParent, plugName, iTimeIndex);
1422 else if (iTypeStr == "normal2")
1423 p.prop = Abc::ON2dArrayProperty(iParent, plugName, iTimeIndex);
1424 else if (iTypeStr == "normal3")
1425 p.prop = Abc::ON3dArrayProperty(iParent, plugName, iTimeIndex);
1426 else
1427 p.prop = Abc::OV3dArrayProperty(iParent, plugName, iTimeIndex);
1428
1429 oArrays.push_back(p);
1430 }
1431 break;
1432
1433 case MFnData::kMatrix:
1434 {
1435 PlugAndObjScalar p;
1436 p.plug = iPlug;
1437 p.obj = iAttr;
1438 p.prop = Abc::OM44dProperty(iParent, plugName, iTimeIndex);
1439 oScalars.push_back(p);
1440 }
1441 break;
1442
1443 case MFnData::kNumeric:
1444 {
1445 MFnNumericAttribute numAttr(iPlug.asMObject());
1446 createUserPropertyFromNumeric(numAttr.unitType(), iAttr,
1447 iPlug, iParent, iTimeIndex, iScope, oScalars, oArrays);
1448 }
1449 break;
1450
1451 default:
1452 {
1453 // get the full property name for the warning
1454 MString msg = "WARNING: Couldn't convert ";
1455 msg += iPlug.partialName(1, 0, 0, 0, 1, 1);
1456 msg += " to a property, so skipping.";
1457 MGlobal::displayWarning(msg);
1458 }
1459 break;
1460 }
1461 }
1462 else if (iAttr.hasFn(MFn::kUnitAttribute))
1463 {
1464 PlugAndObjScalar p;
1465 p.plug = iPlug;
1466 p.obj = iAttr;
1467 p.prop = Abc::ODoubleProperty(iParent, plugName, iTimeIndex);
1468 oScalars.push_back(p);
1469 }
1470 else if (iAttr.hasFn(MFn::kEnumAttribute))
1471 {
1472 PlugAndObjScalar p;
1473 p.plug = iPlug;
1474 p.obj = iAttr;
1475 p.prop = Abc::OInt16Property(iParent, plugName, iTimeIndex);
1476 oScalars.push_back(p);
1477 }
1478 }
1479
createGeomPropertyFromMFnAttr(const MObject & iAttr,const MPlug & iPlug,Abc::OCompoundProperty & iParent,Alembic::Util::uint32_t iTimeIndex,AbcGeom::GeometryScope iScope,const MString & iTypeStr,std::vector<PlugAndObjArray> & oArrayVec)1480 void createGeomPropertyFromMFnAttr(const MObject& iAttr,
1481 const MPlug& iPlug,
1482 Abc::OCompoundProperty & iParent,
1483 Alembic::Util::uint32_t iTimeIndex,
1484 AbcGeom::GeometryScope iScope,
1485 const MString & iTypeStr,
1486 std::vector < PlugAndObjArray > & oArrayVec)
1487 {
1488 // for some reason we have just 1 of the elements of an array, bail
1489 if (iPlug.isElement())
1490 return;
1491
1492 MStatus stat;
1493
1494 std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar();
1495
1496 if (iAttr.hasFn(MFn::kNumericAttribute))
1497 {
1498 MFnNumericAttribute numFn(iAttr, &stat);
1499
1500 if (!stat)
1501 {
1502 MString err = "Couldn't instantiate MFnNumericAttribute\n\tType: ";
1503 err += iAttr.apiTypeStr();
1504 MGlobal::displayError(err);
1505
1506 return;
1507 }
1508
1509 createGeomPropertyFromNumeric(numFn.unitType(), iAttr, iPlug, iParent,
1510 iTimeIndex, iScope, oArrayVec);
1511 }
1512 else if (iAttr.hasFn(MFn::kTypedAttribute))
1513 {
1514 MFnTypedAttribute typeFn(iAttr, &stat);
1515 if (!stat)
1516 {
1517 MString err = "Couldn't instantiate MFnTypedAttribute\n\tType: ";
1518 err += iAttr.apiTypeStr();
1519
1520 MGlobal::displayError(err);
1521
1522 return;
1523 }
1524
1525 Alembic::AbcCoreAbstract::MetaData md;
1526 md.set("isArray", "1");
1527
1528 switch (typeFn.attrType())
1529 {
1530 case MFnData::kString:
1531 {
1532 PlugAndObjArray p;
1533 p.plug = iPlug;
1534 p.obj = iAttr;
1535 AbcGeom::OStringGeomParam gp(iParent, plugName, false, iScope,
1536 1, iTimeIndex);
1537 p.prop = gp.getValueProperty();
1538 oArrayVec.push_back(p);
1539 }
1540 break;
1541
1542 case MFnData::kStringArray:
1543 {
1544 PlugAndObjArray p;
1545 p.plug = iPlug;
1546 p.obj = iAttr;
1547 AbcGeom::OStringGeomParam gp(iParent, plugName, false, iScope,
1548 1, iTimeIndex, md);
1549 p.prop = gp.getValueProperty();
1550 oArrayVec.push_back(p);
1551 }
1552 break;
1553
1554 case MFnData::kDoubleArray:
1555 {
1556 PlugAndObjArray p;
1557 p.plug = iPlug;
1558 p.obj = iAttr;
1559 AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope,
1560 1, iTimeIndex, md);
1561 p.prop = gp.getValueProperty();
1562 oArrayVec.push_back(p);
1563 }
1564 break;
1565
1566 case MFnData::kFloatArray:
1567 {
1568 PlugAndObjArray p;
1569 p.plug = iPlug;
1570 p.obj = iAttr;
1571 AbcGeom::OFloatGeomParam gp(iParent, plugName, false, iScope,
1572 1, iTimeIndex, md);
1573 p.prop = gp.getValueProperty();
1574 oArrayVec.push_back(p);
1575 }
1576 break;
1577
1578 case MFnData::kIntArray:
1579 {
1580 PlugAndObjArray p;
1581 p.plug = iPlug;
1582 p.obj = iAttr;
1583 AbcGeom::OInt32GeomParam gp(iParent, plugName, false, iScope,
1584 1, iTimeIndex, md);
1585 p.prop = gp.getValueProperty();
1586 oArrayVec.push_back(p);
1587 }
1588 break;
1589
1590 case MFnData::kPointArray:
1591 {
1592 PlugAndObjArray p;
1593 p.plug = iPlug;
1594 p.obj = iAttr;
1595 if (iTypeStr == "point2")
1596 {
1597 AbcGeom::OP2dGeomParam gp(iParent, plugName, false, iScope,
1598 1, iTimeIndex, md);
1599 p.prop = gp.getValueProperty();
1600 }
1601 else
1602 {
1603 AbcGeom::OP3dGeomParam gp(iParent, plugName, false, iScope,
1604 1, iTimeIndex);
1605 p.prop = gp.getValueProperty();
1606 }
1607 oArrayVec.push_back(p);
1608 }
1609 break;
1610
1611 case MFnData::kVectorArray:
1612 {
1613 PlugAndObjArray p;
1614 p.plug = iPlug;
1615 p.obj = iAttr;
1616 if (iTypeStr == "vector2")
1617 {
1618 AbcGeom::OV2dGeomParam gp(iParent, plugName, false, iScope,
1619 1, iTimeIndex, md);
1620 p.prop = gp.getValueProperty();
1621 }
1622 else if (iTypeStr == "normal2")
1623 {
1624 AbcGeom::ON2dGeomParam gp(iParent, plugName, false, iScope,
1625 1, iTimeIndex, md);
1626 p.prop = gp.getValueProperty();
1627 }
1628 else if (iTypeStr == "normal3")
1629 {
1630 AbcGeom::ON3dGeomParam gp(iParent, plugName, false, iScope,
1631 1, iTimeIndex, md);
1632 p.prop = gp.getValueProperty();
1633 }
1634 else
1635 {
1636 AbcGeom::OV3dGeomParam gp(iParent, plugName, false, iScope,
1637 1, iTimeIndex, md);
1638 p.prop = gp.getValueProperty();
1639 }
1640 oArrayVec.push_back(p);
1641 }
1642 break;
1643
1644 case MFnData::kMatrix:
1645 {
1646 PlugAndObjArray p;
1647 p.plug = iPlug;
1648 p.obj = iAttr;
1649 AbcGeom::OM44dGeomParam gp(iParent, plugName, false, iScope, 1,
1650 iTimeIndex);
1651 p.prop = gp.getValueProperty();
1652 oArrayVec.push_back(p);
1653 }
1654 break;
1655
1656 case MFnData::kNumeric:
1657 {
1658 MFnNumericAttribute numAttr(iPlug.asMObject());
1659 createGeomPropertyFromNumeric(numAttr.unitType(), iAttr,
1660 iPlug, iParent, iTimeIndex, iScope, oArrayVec);
1661 }
1662 break;
1663
1664 default:
1665 {
1666 // get the full property name for the warning
1667 MString msg = "WARNING: Couldn't convert ";
1668 msg += iPlug.partialName(1, 0, 0, 0, 1, 1);
1669 msg += " to a property, so skipping.";
1670 MGlobal::displayWarning(msg);
1671 }
1672 break;
1673 }
1674 }
1675 else if (iAttr.hasFn(MFn::kUnitAttribute))
1676 {
1677 PlugAndObjArray p;
1678 p.plug = iPlug;
1679 p.obj = iAttr;
1680 AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope, 1,
1681 iTimeIndex);
1682 p.prop = gp.getValueProperty();
1683 oArrayVec.push_back(p);
1684 }
1685 else if (iAttr.hasFn(MFn::kEnumAttribute))
1686 {
1687 PlugAndObjArray p;
1688 p.plug = iPlug;
1689 p.obj = iAttr;
1690 AbcGeom::OInt16GeomParam gp(iParent, plugName, false, iScope, 1,
1691 iTimeIndex);
1692 p.prop = gp.getValueProperty();
1693 oArrayVec.push_back(p);
1694 }
1695 }
1696
1697
isPerParticleAttributes(const MFnDependencyNode & iNode,MObject attrObj)1698 bool isPerParticleAttributes( const MFnDependencyNode &iNode, MObject attrObj )
1699 {
1700 MStatus status(MS::kSuccess);
1701
1702 if ( !iNode.object().hasFn(MFn::kParticle))
1703 {
1704 return false;
1705 }
1706
1707 if ( !attrObj.hasFn(MFn::kTypedAttribute))
1708 {
1709 return false;
1710 }
1711
1712 MFnTypedAttribute attr( attrObj );
1713 MString attrName = attr.name();
1714
1715 if (attrName == "radiusPP")
1716 {
1717 // radiusPP was handled as IPointGeom Width
1718 return false;
1719 }
1720
1721 if ( attr.isHidden() ||
1722 !attr.isReadable() ||
1723 attr.isArray() ||
1724 attr.internal() )
1725 {
1726 return false;
1727 }
1728 if ( attr.attrType() != MFnData::kDoubleArray && attr.attrType() != MFnData::kVectorArray )
1729 {
1730 return false;
1731 }
1732
1733 // Perform a few name filtering to avoid useless attribute
1734 // we only filter non user created attribute
1735 if ( !attr.isDynamic() )
1736 {
1737 // manualy filter a few attributes
1738 if ( attrName.substring(0, 7) == "internal" ||
1739 attrName.toLowerCase().substring(attrName.length() - 5, attrName.length()) == "cache" ||
1740 attrName.substring( attrName.length() - 1, attrName.length()) == "0" )
1741 {
1742 return false;
1743 }
1744
1745 }
1746
1747 MFnParticleSystem particle( iNode.object() );
1748
1749 if ( particle.isPerParticleDoubleAttribute(attrName, &status) ||
1750 particle.isPerParticleVectorAttribute(attrName, &status)
1751 )
1752 {
1753 return true;
1754 }
1755
1756
1757 return false;
1758 }
1759
1760 } // namespace
1761
AttributesWriter(Alembic::Abc::OCompoundProperty & iArbGeom,Alembic::Abc::OCompoundProperty & iUserProps,Alembic::Abc::OObject & iParentObj,const MFnDependencyNode & iNode,Alembic::Util::uint32_t iTimeIndex,const JobArgs & iArgs,bool isShape)1762 AttributesWriter::AttributesWriter(
1763 Alembic::Abc::OCompoundProperty & iArbGeom,
1764 Alembic::Abc::OCompoundProperty & iUserProps,
1765 Alembic::Abc::OObject & iParentObj,
1766 const MFnDependencyNode & iNode,
1767 Alembic::Util::uint32_t iTimeIndex,
1768 const JobArgs & iArgs,
1769 bool isShape)
1770 {
1771 PlugAndObjScalar visPlug;
1772
1773 unsigned int attrCount = iNode.attributeCount();
1774 unsigned int i;
1775
1776 std::vector< PlugAndObjArray > staticPlugObjArrayVec;
1777 std::vector< PlugAndObjScalar > staticPlugObjScalarVec;
1778
1779 for (i = 0; i < attrCount; i++)
1780 {
1781 MObject attr = iNode.attribute(i);
1782
1783 MFnAttribute mfnAttr(attr);
1784 MPlug plug = iNode.findPlug(attr, true);
1785
1786 // if it is not readable, then bail without any more checking
1787 if (!mfnAttr.isReadable() || plug.isNull())
1788 {
1789 continue;
1790 }
1791
1792 MString propName = plug.partialName(0, 0, 0, 0, 0, 1);
1793
1794 std::string propStr = propName.asChar();
1795
1796 // we handle visibility in a special way
1797 if (propStr == "visibility")
1798 {
1799 if (iArgs.writeVisibility)
1800 {
1801 visPlug.plug = plug;
1802 visPlug.obj = attr;
1803 }
1804 continue;
1805 }
1806
1807 bool userAttr = false;
1808 bool userPerParticleAttr = false;
1809
1810 bool isPerParticle = isPerParticleAttributes(iNode, attr);
1811
1812 if (!matchFilterOrAttribs(plug, iArgs, userAttr) && !isPerParticle)
1813 continue;
1814
1815 // When someone set user attribute on a particleShape, we want to write it to arbGeom
1816 // This enable the attribute to be correctly considered as point cloud data
1817 if (userAttr && isPerParticle)
1818 {
1819 // The code will continue with the current attribute, but will write it to arbGeom
1820 userAttr = false;
1821 userPerParticleAttr = true;
1822 }
1823
1824 if (userAttr && !iUserProps.valid())
1825 continue;
1826 if (!userAttr && !iArbGeom.valid())
1827 continue;
1828
1829 int sampType = util::getSampledType(plug) || isPerParticle; // Per particle is always animated
1830
1831
1832 MPlug scopePlug = iNode.findPlug(propName + cAttrScope, true);
1833 AbcGeom::GeometryScope scope = AbcGeom::kUnknownScope;
1834
1835
1836 if (isPerParticle) // PerParticle is always kVaryingScope
1837 {
1838 scope = AbcGeom::kVaryingScope;
1839 }
1840 else if (!scopePlug.isNull())
1841 {
1842 scope = strToScope(scopePlug.asString());
1843 }
1844 else if (userPerParticleAttr)
1845 {
1846 // We need to find the scope we will write
1847 // The attribute was not found to be a perParticle attribute, so it cannot be kVarying
1848 if (sampType == 0)
1849 scope = AbcGeom::kConstantScope;
1850 else if (sampType == 1)
1851 scope = AbcGeom::kUniformScope;
1852 }
1853
1854 MString typeStr;
1855 MPlug typePlug = iNode.findPlug(propName + cAttrType, true);
1856 if (!typePlug.isNull())
1857 {
1858 typeStr= typePlug.asString();
1859 }
1860
1861 if (userAttr)
1862 {
1863 switch (sampType)
1864 {
1865 // static
1866 case 0:
1867 {
1868 //
1869 // Fills in the static plug to OScalarProperty OR
1870 // OArrayProperty correspondence, used for the writing
1871 // below.
1872 //
1873 createUserPropertyFromMFnAttr(attr, plug, iUserProps, 0,
1874 scope, typeStr, staticPlugObjScalarVec,
1875 staticPlugObjArrayVec);
1876 }
1877 break;
1878
1879 // sampled
1880 case 1:
1881 // curve treat like sampled
1882 case 2:
1883 {
1884 //
1885 // Fill in the mPlugUserPropertyVec, used for the writing
1886 // below as well as in the write() method for animated
1887 // values.
1888 //
1889 createUserPropertyFromMFnAttr(attr, plug, iUserProps,
1890 iTimeIndex, scope, typeStr, mPlugObjScalarVec,
1891 mPlugObjArrayVec);
1892 }
1893 break;
1894 }
1895 }
1896 else
1897 {
1898 switch (sampType)
1899 {
1900 // static
1901 case 0:
1902 {
1903 //
1904 // Fills in the plug to OArrayProperty correspondence,
1905 // used for the writing below.
1906 //
1907 createGeomPropertyFromMFnAttr(attr, plug, iArbGeom, 0,
1908 scope, typeStr, staticPlugObjArrayVec);
1909 }
1910 break;
1911
1912 // sampled
1913 case 1:
1914 // curve treat like sampled
1915 case 2:
1916 {
1917 //
1918 // mPlugObjArrayVec
1919 //
1920 // member variable used by isAnimated and when sampling
1921 // the animated data.
1922 //
1923 createGeomPropertyFromMFnAttr(attr, plug, iArbGeom,
1924 iTimeIndex, scope, typeStr, mPlugObjArrayVec);
1925 }
1926 break;
1927 }
1928 }
1929 }
1930
1931 // handle visibility
1932 if (!visPlug.plug.isNull())
1933 {
1934 int retVis = util::getVisibilityType(visPlug.plug);
1935
1936 // visible will go on the top most compound
1937 Abc::OCompoundProperty parent = iParentObj.getProperties();
1938
1939 switch (retVis)
1940 {
1941 // static visibility 0 case
1942 case 1:
1943 {
1944 Alembic::Util::int8_t visVal =
1945 Alembic::AbcGeom::kVisibilityHidden;
1946
1947 Abc::OCharProperty bp =
1948 Alembic::AbcGeom::CreateVisibilityProperty(
1949 iParentObj, 0);
1950 bp.set(visVal);
1951 }
1952 break;
1953
1954 // animated visibility 0 case
1955 case 2:
1956 {
1957 Alembic::Util::int8_t visVal =
1958 Alembic::AbcGeom::kVisibilityHidden;
1959
1960 Abc::OCharProperty bp =
1961 Alembic::AbcGeom::CreateVisibilityProperty(
1962 iParentObj, iTimeIndex);
1963
1964 bp.set(visVal);
1965 visPlug.prop = bp;
1966 mAnimVisibility = visPlug;
1967 }
1968 break;
1969
1970 // animated visibility 1 case
1971 case 3:
1972 {
1973 // dont add if we are forcing static (no frame range specified)
1974 if (iTimeIndex == 0)
1975 {
1976 break;
1977 }
1978
1979 mAnimVisibility = visPlug;
1980
1981 Alembic::Util::int8_t visVal =
1982 Alembic::AbcGeom::kVisibilityDeferred;
1983
1984 Abc::OCharProperty bp =
1985 Alembic::AbcGeom::CreateVisibilityProperty(
1986 iParentObj, iTimeIndex);
1987
1988 bp.set(visVal);
1989 visPlug.prop = bp;
1990 mAnimVisibility = visPlug;
1991
1992 }
1993 break;
1994
1995 // dont write any visibility
1996 default:
1997 break;
1998 }
1999 }
2000
2001 // write the static scalar props
2002 std::vector< PlugAndObjScalar >::iterator k =
2003 staticPlugObjScalarVec.begin();
2004 std::vector< PlugAndObjScalar >::iterator kend =
2005 staticPlugObjScalarVec.end();
2006
2007 for (; k != kend; k++)
2008 {
2009 MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1);
2010
2011 //
2012 // attributeTo[Scalar|Array]PropertyPair does the writing.
2013 bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug,
2014 k->prop);
2015
2016 if (!filledProp)
2017 {
2018 MString msg = "WARNING: Couldn't get static scalar property ";
2019 msg += k->plug.partialName(1, 0, 0, 0, 1, 1);
2020 msg += ", so skipping.";
2021 MGlobal::displayWarning(msg);
2022 continue;
2023 }
2024 }
2025
2026 // write the static array props
2027 std::vector< PlugAndObjArray >::iterator j =
2028 staticPlugObjArrayVec.begin();
2029 std::vector< PlugAndObjArray >::iterator jend =
2030 staticPlugObjArrayVec.end();
2031
2032 for (; j != jend; j++)
2033 {
2034 MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1);
2035 bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug,
2036 j->prop);
2037
2038 if (!filledProp)
2039 {
2040 MString msg = "WARNING: Couldn't get static array property ";
2041 msg += j->plug.partialName(1, 0, 0, 0, 1, 1);
2042 msg += ", so skipping.";
2043 MGlobal::displayWarning(msg);
2044 continue;
2045 }
2046 }
2047
2048 // we shouldn't set the animated channels so bail
2049 if (isShape && !iArgs.setFirstAnimShape)
2050 {
2051 return;
2052 }
2053
2054 // write the animated userProperties
2055 k = mPlugObjScalarVec.begin();
2056 kend = mPlugObjScalarVec.end();
2057
2058 for (; k != kend; ++k)
2059 {
2060 MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1);
2061
2062 bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug,
2063 k->prop);
2064
2065 if (!filledProp)
2066 {
2067 MString msg = "WARNING: Couldn't get scalar property ";
2068 msg += k->plug.partialName(1, 0, 0, 0, 1, 1);
2069 msg += ", so skipping.";
2070 MGlobal::displayWarning(msg);
2071 continue;
2072 }
2073 }
2074
2075 // write the animated arbGeomProps if appropriate
2076 j = mPlugObjArrayVec.begin();
2077 jend = mPlugObjArrayVec.end();
2078
2079 for (; j != jend; j++)
2080 {
2081 MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1);
2082 bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug,j->prop);
2083
2084 if (!filledProp)
2085 {
2086 MString msg = "WARNING: Couldn't get array property ";
2087 msg += j->plug.partialName(1, 0, 0, 0, 1, 1);
2088 msg += ", so skipping.";
2089 MGlobal::displayWarning(msg);
2090 continue;
2091 }
2092 }
2093
2094 }
2095
2096 //
2097 // Returns true if the attribute is:
2098 //
2099 // * Included by name via a -a or -u argument
2100 // * Matches by name via a -atp or -uatp argument
2101 //
2102 // If it's matched via -u or -uatp, userAttrOut is set to true.
2103 // These are intended to go in the .userProperties bucket on the
2104 // object.
2105 //
matchFilterOrAttribs(const MPlug & iPlug,const JobArgs & iArgs,bool & userAttrOut)2106 bool AttributesWriter::matchFilterOrAttribs(const MPlug & iPlug,
2107 const JobArgs & iArgs,
2108 bool& userAttrOut)
2109 {
2110
2111 MString propName = iPlug.partialName(0, 0, 0, 0, 0, 1);
2112 std::string name = propName.asChar();
2113
2114 if (name.find("[") != std::string::npos)
2115 {
2116 return false;
2117 }
2118
2119 // For .arbGeomParam bucket
2120 std::vector<std::string>::const_iterator f;
2121 std::vector<std::string>::const_iterator fEnd =
2122 iArgs.prefixFilters.end();
2123 for (f = iArgs.prefixFilters.begin(); f != fEnd; ++f)
2124 {
2125 // check the prefilter and ignore those that match but end with
2126 // arb attr
2127 if (f->length() > 0 &&
2128 name.compare(0, f->length(), *f) == 0 &&
2129 !endsWithArbAttr(name) &&
2130 ( !iPlug.isChild() || !isDataAttr(iPlug.parent()) ))
2131 {
2132 userAttrOut = false;
2133 return true;
2134 }
2135 }
2136
2137 //
2138 // For .userProperties bucket
2139 std::vector<std::string>::const_iterator it;
2140 std::vector<std::string>::const_iterator itEnd =
2141 iArgs.userPrefixFilters.end();
2142 for (it = iArgs.userPrefixFilters.begin(); it != itEnd; ++it)
2143 {
2144 // check the userprefilter and ignore those that match but end with
2145 // arb attr
2146 if (it->length() > 0 &&
2147 name.compare(0, it->length(), *it) == 0 &&
2148 !endsWithArbAttr(name) &&
2149 ( !iPlug.isChild() || !isDataAttr(iPlug.parent()) ))
2150 {
2151 userAttrOut = true;
2152 return true;
2153 }
2154 }
2155
2156 // check our specific list of attributes
2157 if (iArgs.attribs.find(name) != iArgs.attribs.end())
2158 {
2159 userAttrOut = false;
2160 return true;
2161 }
2162
2163 if (iArgs.userAttribs.find(name) != iArgs.userAttribs.end())
2164 {
2165 userAttrOut = true;
2166 return true;
2167 }
2168
2169 return false;
2170 }
2171
hasAnyAttr(const MFnDependencyNode & iNode,const JobArgs & iArgs)2172 bool AttributesWriter::hasAnyAttr(const MFnDependencyNode & iNode,
2173 const JobArgs & iArgs)
2174 {
2175 unsigned int attrCount = iNode.attributeCount();
2176 unsigned int i;
2177
2178 std::vector< PlugAndObjArray > staticPlugObjArrayVec;
2179
2180 if (iNode.object().hasFn(MFn::kParticle))
2181 {
2182 // Particles always have extra attributes
2183 return true;
2184 }
2185
2186 bool userAttr;
2187 for (i = 0; i < attrCount; i++)
2188 {
2189 MObject attr = iNode.attribute(i);
2190 MFnAttribute mfnAttr(attr);
2191 MPlug plug = iNode.findPlug(attr, true);
2192
2193 // if it is not readable, then bail without any more checking
2194 if (!mfnAttr.isReadable() || plug.isNull())
2195 {
2196 continue;
2197 }
2198
2199 if (matchFilterOrAttribs(plug, iArgs, userAttr))
2200 {
2201 return true;
2202 }
2203 }
2204
2205 return false;
2206 }
2207
~AttributesWriter()2208 AttributesWriter::~AttributesWriter()
2209 {
2210 }
2211
isAnimated()2212 bool AttributesWriter::isAnimated()
2213 {
2214 return !mPlugObjArrayVec.empty() || !mAnimVisibility.plug.isNull() ||
2215 !mPlugObjScalarVec.empty();
2216 }
2217
write()2218 void AttributesWriter::write()
2219 {
2220
2221 std::vector< PlugAndObjArray >::iterator j =
2222 mPlugObjArrayVec.begin();
2223 std::vector< PlugAndObjArray >::iterator jend =
2224 mPlugObjArrayVec.end();
2225
2226 for (; j != jend; j++)
2227 {
2228 MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1);
2229 bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug, j->prop);
2230
2231 if (!filledProp)
2232 {
2233 MString msg = "WARNING: Couldn't get sampled array property ";
2234 msg += j->plug.partialName(1, 0, 0, 0, 1, 1);
2235 msg += ", so skipping.";
2236 MGlobal::displayWarning(msg);
2237 continue;
2238 }
2239 }
2240
2241 std::vector< PlugAndObjScalar >::iterator k =
2242 mPlugObjScalarVec.begin();
2243 std::vector< PlugAndObjScalar >::iterator kend =
2244 mPlugObjScalarVec.end();
2245
2246 for (; k != kend; ++k)
2247 {
2248 MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1);
2249
2250 bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug,
2251 k->prop);
2252
2253 if (!filledProp)
2254 {
2255 MString msg = "WARNING: Couldn't get sampled scalar property ";
2256 msg += k->plug.partialName(1, 0, 0, 0, 1, 1);
2257 msg += ", so skipping.";
2258 MGlobal::displayWarning(msg);
2259 continue;
2260 }
2261 }
2262
2263 if (!mAnimVisibility.plug.isNull())
2264 {
2265 Alembic::Util::int8_t visVal = -1;
2266 if (!mAnimVisibility.plug.asBool())
2267 {
2268 visVal = 0;
2269 }
2270
2271 mAnimVisibility.prop.set(&visVal);
2272 }
2273
2274 }
2275
2276
2277