//-***************************************************************************** // // Copyright (c) 2009-2013, // Sony Pictures Imageworks Inc. and // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Sony Pictures Imageworks, nor // Industrial Light & Magic, nor the names of their contributors may be used // to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //-***************************************************************************** #include "AttributesWriter.h" #include "MayaUtility.h" namespace Abc = Alembic::Abc; namespace AbcGeom = Alembic::AbcGeom; namespace AbcA = Alembic::AbcCoreAbstract; namespace { static const char * cAttrScope = "_AbcGeomScope"; static const char * cAttrType = "_AbcType"; std::string scopeToString( AbcGeom::GeometryScope input ) { switch(input) { case AbcGeom::kConstantScope: return "kConstantScope"; case AbcGeom::kFacevaryingScope:return "kFacevaryingScope"; case AbcGeom::kUniformScope: return "kUniformScope"; case AbcGeom::kUnknownScope: return "kUnknownScope"; case AbcGeom::kVaryingScope: return "kVaryingScope"; case AbcGeom::kVertexScope: return "kVertexScope"; } return "kUnknownScope"; } // returns true if a plug is of a simple numeric data type bool isDataAttr(const MPlug & iParent) { MObject obj = iParent.asMObject(); switch (obj.apiType()) { case MFn::kData2Double: case MFn::kData3Double: case MFn::kData4Double: case MFn::kData2Float: case MFn::kData3Float: case MFn::kData2Int: case MFn::kData3Int: case MFn::kData2Short: case MFn::kData3Short: case MFn::kStringData: case MFn::kStringArrayData: case MFn::kFloatVectorArrayData: case MFn::kVectorArrayData: case MFn::kFloatArrayData: case MFn::kDoubleArrayData: case MFn::kIntArrayData: case MFn::kPointArrayData: case MFn::kUInt64ArrayData: return true; default: return false; } return false; } AbcGeom::GeometryScope strToScope(MString iStr) { iStr.toLowerCase(); if (iStr == "vtx") { return AbcGeom::kVertexScope; } else if (iStr == "fvr") { return AbcGeom::kFacevaryingScope; } else if (iStr == "uni") { return AbcGeom::kUniformScope; } else if (iStr == "var") { return AbcGeom::kVaryingScope; } return AbcGeom::kConstantScope; } // returns true if the string ends with _AbcGeomScope or _AbcType bool endsWithArbAttr(const std::string & iStr) { size_t len = iStr.size(); return (len >= 13 && iStr.compare(len - 13, 13, cAttrScope) == 0) || (len >= 8 && iStr.compare(len - 8, 8, cAttrType) == 0); } void 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) { std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar(); switch (iType) { case MFnNumericData::kBoolean: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OBoolProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::kByte: case MFnNumericData::kChar: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OCharProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::kShort: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OInt16Property up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::kInt: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OInt32Property up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::kFloat: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OFloatProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::kDouble: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::ODoubleProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k2Short: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV2sProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k3Short: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV3sProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k2Int: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV2iProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k3Int: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV3iProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k2Float: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV2fProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k3Float: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV3fProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k2Double: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV2dProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k3Double: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; Abc::OV3dProperty up(iParent, plugName, iTimeIndex); p.prop = up; oScalars.push_back(p); } break; case MFnNumericData::k4Double: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcA::DataType dtype(Alembic::Util::kFloat64POD, 4); Abc::OArrayProperty up(iParent, plugName, dtype, iTimeIndex); p.prop = up; oArrays.push_back(p); } break; default: break; } } void 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) { std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar(); switch (iType) { case MFnNumericData::kBoolean: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OBoolGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::kByte: case MFnNumericData::kChar: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OCharGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::kShort: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OInt16GeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::kInt: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OInt32GeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::kFloat: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OFloatGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::kDouble: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k2Short: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV2sGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k3Short: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV3sGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k2Int: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV2iGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k3Int: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV3iGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k2Float: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV2fGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k3Float: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; MFnAttribute mfnAttr(iAttr); if (mfnAttr.isUsedAsColor()) { AbcGeom::OC3fGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); } else { AbcGeom::OV3fGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); } oArrayVec.push_back(p); } break; case MFnNumericData::k2Double: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV2dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k3Double: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OV3dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnNumericData::k4Double: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcA::DataType dtype(Alembic::Util::kFloat64POD, 4); p.prop = Abc::OArrayProperty(iParent, plugName, dtype, iTimeIndex); oArrayVec.push_back(p); } break; default: break; } } bool MFnNumericDataToSample(MFnNumericData::Type iType, const MPlug& iPlug, Abc::OScalarProperty & oProp) { int ival; float fval; double dval; bool bval; Alembic::Util::int16_t sval; Alembic::Util::int8_t cval; Alembic::Util::int16_t v2sVal[2]; Alembic::Util::int16_t v3sVal[3]; Alembic::Util::int32_t v2iVal[2]; Alembic::Util::int32_t v3iVal[3]; float v2fVal[2]; float v3fVal[3]; double v2dVal[2]; double v3dVal[3]; switch (iType) { case MFnNumericData::kBoolean: { bval = iPlug.asBool(); oProp.set(&bval); } break; case MFnNumericData::kByte: case MFnNumericData::kChar: { cval = iPlug.asChar(); oProp.set(&cval); } break; case MFnNumericData::kShort: { sval = iPlug.asShort(); oProp.set(&sval); } break; case MFnNumericData::kInt: { ival = iPlug.asInt(); oProp.set(&ival); } break; case MFnNumericData::kFloat: { fval = iPlug.asFloat(); oProp.set(&fval); } break; case MFnNumericData::kDouble: { dval = iPlug.asDouble(); oProp.set(&dval); } break; case MFnNumericData::k2Short: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Short(v2sVal[0], v2sVal[1]); oProp.set(&v2sVal[0]); } break; case MFnNumericData::k3Short: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Short(v3sVal[0], v3sVal[1], v3sVal[2]); oProp.set(&v3sVal[0]); } break; case MFnNumericData::k2Int: { int val0, val1; MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Int(val0, val1); v2iVal[0] = Alembic::Util::int32_t(val0); v2iVal[1] = Alembic::Util::int32_t(val1); oProp.set(&v2iVal[0]); } break; case MFnNumericData::k3Int: { int val0, val1, val2; MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Int(val0, val1, val2); v3iVal[0] = Alembic::Util::int32_t(val0); v3iVal[1] = Alembic::Util::int32_t(val1); v3iVal[2] = Alembic::Util::int32_t(val2); oProp.set(&v3iVal[0]); } break; case MFnNumericData::k2Float: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Float(v2fVal[0], v2fVal[1]); oProp.set(&v2fVal[0]); } break; case MFnNumericData::k3Float: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Float(v3fVal[0], v3fVal[1], v3fVal[2]); oProp.set(&v3fVal[0]); } break; case MFnNumericData::k2Double: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Double(v2dVal[0], v3dVal[1]); oProp.set(&v2dVal[0]); } break; case MFnNumericData::k3Double: { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Double(v3dVal[0], v3dVal[1], v3dVal[2]); oProp.set(&v3dVal[0]); } break; default: return false; break; } return true; } bool MFnNumericDataToSample(MFnNumericData::Type iType, const MPlug& iPlug, Abc::OArrayProperty & oProp) { unsigned int numElements = iPlug.numElements(); bool isArray = iPlug.isArray(); unsigned int dimSize = numElements; if (!isArray) dimSize = 1; switch (iType) { case MFnNumericData::kBoolean: { std::vector< Alembic::Util::bool_t > val(dimSize); if (!isArray) { val[0] = iPlug.asBool(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asBool(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::kByte: case MFnNumericData::kChar: { std::vector< Alembic::Util::int8_t > val(dimSize); if (!isArray) { val[0] = iPlug.asChar(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asChar(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::kShort: { std::vector< Alembic::Util::int16_t > val(dimSize); if (!isArray) { val[0] = iPlug.asShort(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asShort(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::kInt: { std::vector< Alembic::Util::int32_t > val(dimSize); if (!isArray) { val[0] = iPlug.asInt(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asInt(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::kFloat: { std::vector val(dimSize); if (!isArray) { val[0] = iPlug.asFloat(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asFloat(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::kDouble: { std::vector val(dimSize); if (!isArray) { val[0] = iPlug.asDouble(); } else { for (unsigned int i = 0; i < numElements; ++i) { val[i] = iPlug[i].asDouble(); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k2Short: { std::vector< Alembic::Util::int16_t > val(dimSize*2); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Short(val[0], val[1]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData2Short(val[2*i], val[2*i+1]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k3Short: { std::vector< Alembic::Util::int16_t > val(dimSize*3); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Short(val[0], val[1], val[2]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData3Short(val[3*i], val[3*i+1], val[3*i+2]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k2Int: { std::vector< Alembic::Util::int32_t > val(dimSize*2); if (!isArray) { int val0, val1; MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Int(val0, val1); val[0] = Alembic::Util::int32_t(val0); val[1] = Alembic::Util::int32_t(val1); } else { for (unsigned int i = 0; i < numElements; ++i) { int val0, val1; MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData2Int(val0, val1); val[2*i] = Alembic::Util::int32_t(val0); val[2*i+1] = Alembic::Util::int32_t(val1); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k3Int: { std::vector< Alembic::Util::int32_t > val(dimSize*3); if (!isArray) { int val0, val1, val2; MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Int(val0, val1, val2); val[0] = Alembic::Util::int32_t(val0); val[1] = Alembic::Util::int32_t(val1); val[2] = Alembic::Util::int32_t(val2); } else { for (unsigned int i = 0; i < numElements; ++i) { int val0, val1, val2; MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData3Int(val0, val1, val2); val[3*i] = Alembic::Util::int32_t(val0); val[3*i+1] = Alembic::Util::int32_t(val1); val[3*i+2] = Alembic::Util::int32_t(val2); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k2Float: { std::vector val(dimSize*2); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Float(val[0], val[1]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData2Float(val[2*i], val[2*i+1]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k3Float: { std::vector val(dimSize*3); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Float(val[0], val[1], val[2]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData3Float(val[3*i], val[3*i+1], val[3*i+2]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k2Double: { std::vector val(dimSize*2); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData2Double(val[0], val[1]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData2Double(val[2*i], val[2*i+1]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k3Double: { std::vector val(dimSize*3); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData3Double(val[0], val[1], val[2]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData3Double(val[3*i], val[3*i+1], val[3*i+2]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; case MFnNumericData::k4Double: { std::vector val(dimSize*4); if (!isArray) { MFnNumericData numdFn(iPlug.asMObject()); numdFn.getData4Double(val[0], val[1], val[2], val[3]); } else { for (unsigned int i = 0; i < numElements; ++i) { MFnNumericData numdFn(iPlug[i].asMObject()); numdFn.getData4Double(val[4*i], val[4*i+1], val[4*i+2], val[4*i+3]); } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(dimSize)); oProp.set(samp); } break; default: return false; break; } return true; } bool MFnTypedDataToSample(MFnData::Type iType, const MPlug& iPlug, Abc::OScalarProperty & oProp) { switch (iType) { case MFnData::kNumeric: { MFnNumericData numObj(iPlug.asMObject()); return MFnNumericDataToSample(numObj.numericType(), iPlug, oProp); } break; case MFnData::kString: { Abc::OStringProperty strProp( oProp.getPtr(), Abc::kWrapExisting ); std::string val = iPlug.asString().asChar(); strProp.set(val); } break; case MFnData::kMatrix: { MFnMatrixData arr(iPlug.asMObject()); MMatrix mat = arr.matrix(); double val[16]; unsigned int i = 0; for (unsigned int r = 0; r < 4; r++) { for (unsigned int c = 0; c < 4; c++, i++) { val[i] = mat[r][c]; } } oProp.set(&val); } break; default: return false; break; } return true; } bool MFnTypedDataToSample(MFnData::Type iType, const MPlug& iPlug, Abc::OArrayProperty & oProp) { switch (iType) { case MFnData::kNumeric: { MFnNumericData numObj(iPlug.asMObject()); return MFnNumericDataToSample(numObj.numericType(), iPlug, oProp); } break; case MFnData::kString: { std::vector< std::string > val(1); val[0] = iPlug.asString().asChar(); AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(1)); oProp.set(samp); } break; case MFnData::kStringArray: { MFnStringArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); std::vector< std::string > val(length); for (unsigned int i = 0; i < length; i++) { val[i] = arr[i].asChar(); } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kDoubleArray: { MFnDoubleArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); std::vector< double > val(length); for (unsigned int i = 0; i < length; i++) { val[i] = arr[i]; } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kFloatArray: { MFnFloatArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); std::vector< float > val(length); for (unsigned int i = 0; i < length; i++) { val[i] = arr[i]; } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kIntArray: { MFnIntArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); std::vector< Alembic::Util::int32_t > val(length); for (unsigned int i = 0; i < length; i++) { val[i] = arr[i]; } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kPointArray: { MFnPointArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); unsigned int extent = oProp.getDataType().getExtent(); std::vector< double > val(length*extent); for (unsigned int i = 0; i < length; i++) { MPoint pt(arr[i]); val[extent*i] = pt.x; val[extent*i+1] = pt.y; if (extent > 2) val[extent*i+2] = pt.z; if (extent > 3) val[extent*i+3] = pt.w; } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kVectorArray: { MFnVectorArrayData arr(iPlug.asMObject()); unsigned int length = arr.length(); unsigned int extent = oProp.getDataType().getExtent(); std::vector< double > val(length*extent); for (unsigned int i = 0; i < length; i++) { MVector v(arr[i]); val[extent*i] = v.x; val[extent*i+1] = v.y; if (extent > 2) val[extent*i+2] = v.z; } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(length)); oProp.set(samp); } break; case MFnData::kMatrix: { MFnMatrixData arr(iPlug.asMObject()); MMatrix mat = arr.matrix(); std::vector val(16); unsigned int i = 0; for (unsigned int r = 0; r < 4; r++) { for (unsigned int c = 0; c < 4; c++, i++) { val[i] = mat[r][c]; } } AbcA::ArraySample samp(&(val.front()), oProp.getDataType(), Alembic::Util::Dimensions(1)); oProp.set(samp); } break; default: return false; break; } return true; } bool attributeToScalarPropertyPair(const MObject& iAttr, const MPlug& iPlug, Abc::OScalarProperty & oProp) { if (iAttr.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute typedAttr(iAttr); return MFnTypedDataToSample(typedAttr.attrType(), iPlug, oProp); } else if (iAttr.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute numAttr(iAttr); return MFnNumericDataToSample(numAttr.unitType(), iPlug, oProp); } else if (iAttr.hasFn(MFn::kUnitAttribute)) { double dval = iPlug.asDouble(); oProp.set(&dval); return true; } else if (iAttr.hasFn(MFn::kEnumAttribute)) { Alembic::Util::int16_t val = iPlug.asShort(); oProp.set(&val); return true; } return false; } bool attributeToArrayPropertyPair(const MObject& iAttr, const MPlug& iPlug, Abc::OArrayProperty & oProp) { if (iAttr.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute typedAttr(iAttr); return MFnTypedDataToSample(typedAttr.attrType(), iPlug, oProp); } else if (iAttr.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute numAttr(iAttr); return MFnNumericDataToSample(numAttr.unitType(), iPlug, oProp); } else if (iAttr.hasFn(MFn::kUnitAttribute)) { double val = iPlug.asDouble(); AbcA::ArraySample samp(&val, oProp.getDataType(), Alembic::Util::Dimensions(1)); oProp.set(samp); return true; } else if (iAttr.hasFn(MFn::kEnumAttribute)) { Alembic::Util::int16_t val = iPlug.asShort(); AbcA::ArraySample samp(&val, oProp.getDataType(), Alembic::Util::Dimensions(1)); oProp.set(samp); return true; } return false; } void 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) { MStatus stat; std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar(); if (iAttr.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute numFn(iAttr, &stat); if (!stat) { MString err = "Couldn't instantiate MFnNumericAttribute\n\tType: "; err += iAttr.apiTypeStr(); MGlobal::displayError(err); return; } createUserPropertyFromNumeric(numFn.unitType(), iAttr, iPlug, iParent, iTimeIndex, iScope, oScalars, oArrays); } else if (iAttr.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute typeFn(iAttr, &stat); if (!stat) { MString err = "Couldn't instantiate MFnTypedAttribute\n\tType: "; err += iAttr.apiTypeStr(); MGlobal::displayError(err); return; } switch (typeFn.attrType()) { case MFnData::kString: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OStringProperty(iParent, plugName, iTimeIndex); oScalars.push_back(p); } break; case MFnData::kStringArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OStringArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kDoubleArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::ODoubleArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kFloatArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OFloatArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kIntArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OInt32ArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kPointArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; if (iTypeStr == "point2") p.prop = Abc::OP2dArrayProperty(iParent, plugName, iTimeIndex); else p.prop = Abc::OP3dArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kVectorArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; if (iTypeStr == "vector2") p.prop = Abc::OV2dArrayProperty(iParent, plugName, iTimeIndex); else if (iTypeStr == "normal2") p.prop = Abc::ON2dArrayProperty(iParent, plugName, iTimeIndex); else if (iTypeStr == "normal3") p.prop = Abc::ON3dArrayProperty(iParent, plugName, iTimeIndex); else p.prop = Abc::OV3dArrayProperty(iParent, plugName, iTimeIndex); oArrays.push_back(p); } break; case MFnData::kMatrix: { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OM44dProperty(iParent, plugName, iTimeIndex); oScalars.push_back(p); } break; case MFnData::kNumeric: { MFnNumericAttribute numAttr(iPlug.asMObject()); createUserPropertyFromNumeric(numAttr.unitType(), iAttr, iPlug, iParent, iTimeIndex, iScope, oScalars, oArrays); } break; default: { // get the full property name for the warning MString msg = "WARNING: Couldn't convert "; msg += iPlug.partialName(1, 0, 0, 0, 1, 1); msg += " to a property, so skipping."; MGlobal::displayWarning(msg); } break; } } else if (iAttr.hasFn(MFn::kUnitAttribute)) { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::ODoubleProperty(iParent, plugName, iTimeIndex); oScalars.push_back(p); } else if (iAttr.hasFn(MFn::kEnumAttribute)) { PlugAndObjScalar p; p.plug = iPlug; p.obj = iAttr; p.prop = Abc::OInt16Property(iParent, plugName, iTimeIndex); oScalars.push_back(p); } } void 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) { // for some reason we have just 1 of the elements of an array, bail if (iPlug.isElement()) return; MStatus stat; std::string plugName = iPlug.partialName(0, 0, 0, 0, 0, 1).asChar(); if (iAttr.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute numFn(iAttr, &stat); if (!stat) { MString err = "Couldn't instantiate MFnNumericAttribute\n\tType: "; err += iAttr.apiTypeStr(); MGlobal::displayError(err); return; } createGeomPropertyFromNumeric(numFn.unitType(), iAttr, iPlug, iParent, iTimeIndex, iScope, oArrayVec); } else if (iAttr.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute typeFn(iAttr, &stat); if (!stat) { MString err = "Couldn't instantiate MFnTypedAttribute\n\tType: "; err += iAttr.apiTypeStr(); MGlobal::displayError(err); return; } Alembic::AbcCoreAbstract::MetaData md; md.set("isArray", "1"); switch (typeFn.attrType()) { case MFnData::kString: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OStringGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kStringArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OStringGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kDoubleArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kFloatArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OFloatGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kIntArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OInt32GeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kPointArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; if (iTypeStr == "point2") { AbcGeom::OP2dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); } else { AbcGeom::OP3dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); } oArrayVec.push_back(p); } break; case MFnData::kVectorArray: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; if (iTypeStr == "vector2") { AbcGeom::OV2dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); } else if (iTypeStr == "normal2") { AbcGeom::ON2dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); } else if (iTypeStr == "normal3") { AbcGeom::ON3dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); } else { AbcGeom::OV3dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex, md); p.prop = gp.getValueProperty(); } oArrayVec.push_back(p); } break; case MFnData::kMatrix: { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OM44dGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } break; case MFnData::kNumeric: { MFnNumericAttribute numAttr(iPlug.asMObject()); createGeomPropertyFromNumeric(numAttr.unitType(), iAttr, iPlug, iParent, iTimeIndex, iScope, oArrayVec); } break; default: { // get the full property name for the warning MString msg = "WARNING: Couldn't convert "; msg += iPlug.partialName(1, 0, 0, 0, 1, 1); msg += " to a property, so skipping."; MGlobal::displayWarning(msg); } break; } } else if (iAttr.hasFn(MFn::kUnitAttribute)) { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::ODoubleGeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } else if (iAttr.hasFn(MFn::kEnumAttribute)) { PlugAndObjArray p; p.plug = iPlug; p.obj = iAttr; AbcGeom::OInt16GeomParam gp(iParent, plugName, false, iScope, 1, iTimeIndex); p.prop = gp.getValueProperty(); oArrayVec.push_back(p); } } bool isPerParticleAttributes( const MFnDependencyNode &iNode, MObject attrObj ) { MStatus status(MS::kSuccess); if ( !iNode.object().hasFn(MFn::kParticle)) { return false; } if ( !attrObj.hasFn(MFn::kTypedAttribute)) { return false; } MFnTypedAttribute attr( attrObj ); MString attrName = attr.name(); if (attrName == "radiusPP") { // radiusPP was handled as IPointGeom Width return false; } if ( attr.isHidden() || !attr.isReadable() || attr.isArray() || attr.internal() ) { return false; } if ( attr.attrType() != MFnData::kDoubleArray && attr.attrType() != MFnData::kVectorArray ) { return false; } // Perform a few name filtering to avoid useless attribute // we only filter non user created attribute if ( !attr.isDynamic() ) { // manualy filter a few attributes if ( attrName.substring(0, 7) == "internal" || attrName.toLowerCase().substring(attrName.length() - 5, attrName.length()) == "cache" || attrName.substring( attrName.length() - 1, attrName.length()) == "0" ) { return false; } } MFnParticleSystem particle( iNode.object() ); if ( particle.isPerParticleDoubleAttribute(attrName, &status) || particle.isPerParticleVectorAttribute(attrName, &status) ) { return true; } return false; } } // namespace AttributesWriter::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) { PlugAndObjScalar visPlug; unsigned int attrCount = iNode.attributeCount(); unsigned int i; std::vector< PlugAndObjArray > staticPlugObjArrayVec; std::vector< PlugAndObjScalar > staticPlugObjScalarVec; for (i = 0; i < attrCount; i++) { MObject attr = iNode.attribute(i); MFnAttribute mfnAttr(attr); MPlug plug = iNode.findPlug(attr, true); // if it is not readable, then bail without any more checking if (!mfnAttr.isReadable() || plug.isNull()) { continue; } MString propName = plug.partialName(0, 0, 0, 0, 0, 1); std::string propStr = propName.asChar(); // we handle visibility in a special way if (propStr == "visibility") { if (iArgs.writeVisibility) { visPlug.plug = plug; visPlug.obj = attr; } continue; } bool userAttr = false; bool userPerParticleAttr = false; bool isPerParticle = isPerParticleAttributes(iNode, attr); if (!matchFilterOrAttribs(plug, iArgs, userAttr) && !isPerParticle) continue; // When someone set user attribute on a particleShape, we want to write it to arbGeom // This enable the attribute to be correctly considered as point cloud data if (userAttr && isPerParticle) { // The code will continue with the current attribute, but will write it to arbGeom userAttr = false; userPerParticleAttr = true; } if (userAttr && !iUserProps.valid()) continue; if (!userAttr && !iArbGeom.valid()) continue; int sampType = util::getSampledType(plug) || isPerParticle; // Per particle is always animated MPlug scopePlug = iNode.findPlug(propName + cAttrScope, true); AbcGeom::GeometryScope scope = AbcGeom::kUnknownScope; if (isPerParticle) // PerParticle is always kVaryingScope { scope = AbcGeom::kVaryingScope; } else if (!scopePlug.isNull()) { scope = strToScope(scopePlug.asString()); } else if (userPerParticleAttr) { // We need to find the scope we will write // The attribute was not found to be a perParticle attribute, so it cannot be kVarying if (sampType == 0) scope = AbcGeom::kConstantScope; else if (sampType == 1) scope = AbcGeom::kUniformScope; } MString typeStr; MPlug typePlug = iNode.findPlug(propName + cAttrType, true); if (!typePlug.isNull()) { typeStr= typePlug.asString(); } if (userAttr) { switch (sampType) { // static case 0: { // // Fills in the static plug to OScalarProperty OR // OArrayProperty correspondence, used for the writing // below. // createUserPropertyFromMFnAttr(attr, plug, iUserProps, 0, scope, typeStr, staticPlugObjScalarVec, staticPlugObjArrayVec); } break; // sampled case 1: // curve treat like sampled case 2: { // // Fill in the mPlugUserPropertyVec, used for the writing // below as well as in the write() method for animated // values. // createUserPropertyFromMFnAttr(attr, plug, iUserProps, iTimeIndex, scope, typeStr, mPlugObjScalarVec, mPlugObjArrayVec); } break; } } else { switch (sampType) { // static case 0: { // // Fills in the plug to OArrayProperty correspondence, // used for the writing below. // createGeomPropertyFromMFnAttr(attr, plug, iArbGeom, 0, scope, typeStr, staticPlugObjArrayVec); } break; // sampled case 1: // curve treat like sampled case 2: { // // mPlugObjArrayVec // // member variable used by isAnimated and when sampling // the animated data. // createGeomPropertyFromMFnAttr(attr, plug, iArbGeom, iTimeIndex, scope, typeStr, mPlugObjArrayVec); } break; } } } // handle visibility if (!visPlug.plug.isNull()) { int retVis = util::getVisibilityType(visPlug.plug); // visible will go on the top most compound Abc::OCompoundProperty parent = iParentObj.getProperties(); switch (retVis) { // static visibility 0 case case 1: { Alembic::Util::int8_t visVal = Alembic::AbcGeom::kVisibilityHidden; Abc::OCharProperty bp = Alembic::AbcGeom::CreateVisibilityProperty( iParentObj, 0); bp.set(visVal); } break; // animated visibility 0 case case 2: { Alembic::Util::int8_t visVal = Alembic::AbcGeom::kVisibilityHidden; Abc::OCharProperty bp = Alembic::AbcGeom::CreateVisibilityProperty( iParentObj, iTimeIndex); bp.set(visVal); visPlug.prop = bp; mAnimVisibility = visPlug; } break; // animated visibility 1 case case 3: { // dont add if we are forcing static (no frame range specified) if (iTimeIndex == 0) { break; } mAnimVisibility = visPlug; Alembic::Util::int8_t visVal = Alembic::AbcGeom::kVisibilityDeferred; Abc::OCharProperty bp = Alembic::AbcGeom::CreateVisibilityProperty( iParentObj, iTimeIndex); bp.set(visVal); visPlug.prop = bp; mAnimVisibility = visPlug; } break; // dont write any visibility default: break; } } // write the static scalar props std::vector< PlugAndObjScalar >::iterator k = staticPlugObjScalarVec.begin(); std::vector< PlugAndObjScalar >::iterator kend = staticPlugObjScalarVec.end(); for (; k != kend; k++) { MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1); // // attributeTo[Scalar|Array]PropertyPair does the writing. bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug, k->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get static scalar property "; msg += k->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } // write the static array props std::vector< PlugAndObjArray >::iterator j = staticPlugObjArrayVec.begin(); std::vector< PlugAndObjArray >::iterator jend = staticPlugObjArrayVec.end(); for (; j != jend; j++) { MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1); bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug, j->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get static array property "; msg += j->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } // we shouldn't set the animated channels so bail if (isShape && !iArgs.setFirstAnimShape) { return; } // write the animated userProperties k = mPlugObjScalarVec.begin(); kend = mPlugObjScalarVec.end(); for (; k != kend; ++k) { MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1); bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug, k->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get scalar property "; msg += k->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } // write the animated arbGeomProps if appropriate j = mPlugObjArrayVec.begin(); jend = mPlugObjArrayVec.end(); for (; j != jend; j++) { MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1); bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug,j->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get array property "; msg += j->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } } // // Returns true if the attribute is: // // * Included by name via a -a or -u argument // * Matches by name via a -atp or -uatp argument // // If it's matched via -u or -uatp, userAttrOut is set to true. // These are intended to go in the .userProperties bucket on the // object. // bool AttributesWriter::matchFilterOrAttribs(const MPlug & iPlug, const JobArgs & iArgs, bool& userAttrOut) { MString propName = iPlug.partialName(0, 0, 0, 0, 0, 1); std::string name = propName.asChar(); if (name.find("[") != std::string::npos) { return false; } // For .arbGeomParam bucket std::vector::const_iterator f; std::vector::const_iterator fEnd = iArgs.prefixFilters.end(); for (f = iArgs.prefixFilters.begin(); f != fEnd; ++f) { // check the prefilter and ignore those that match but end with // arb attr if (f->length() > 0 && name.compare(0, f->length(), *f) == 0 && !endsWithArbAttr(name) && ( !iPlug.isChild() || !isDataAttr(iPlug.parent()) )) { userAttrOut = false; return true; } } // // For .userProperties bucket std::vector::const_iterator it; std::vector::const_iterator itEnd = iArgs.userPrefixFilters.end(); for (it = iArgs.userPrefixFilters.begin(); it != itEnd; ++it) { // check the userprefilter and ignore those that match but end with // arb attr if (it->length() > 0 && name.compare(0, it->length(), *it) == 0 && !endsWithArbAttr(name) && ( !iPlug.isChild() || !isDataAttr(iPlug.parent()) )) { userAttrOut = true; return true; } } // check our specific list of attributes if (iArgs.attribs.find(name) != iArgs.attribs.end()) { userAttrOut = false; return true; } if (iArgs.userAttribs.find(name) != iArgs.userAttribs.end()) { userAttrOut = true; return true; } return false; } bool AttributesWriter::hasAnyAttr(const MFnDependencyNode & iNode, const JobArgs & iArgs) { unsigned int attrCount = iNode.attributeCount(); unsigned int i; std::vector< PlugAndObjArray > staticPlugObjArrayVec; if (iNode.object().hasFn(MFn::kParticle)) { // Particles always have extra attributes return true; } bool userAttr; for (i = 0; i < attrCount; i++) { MObject attr = iNode.attribute(i); MFnAttribute mfnAttr(attr); MPlug plug = iNode.findPlug(attr, true); // if it is not readable, then bail without any more checking if (!mfnAttr.isReadable() || plug.isNull()) { continue; } if (matchFilterOrAttribs(plug, iArgs, userAttr)) { return true; } } return false; } AttributesWriter::~AttributesWriter() { } bool AttributesWriter::isAnimated() { return !mPlugObjArrayVec.empty() || !mAnimVisibility.plug.isNull() || !mPlugObjScalarVec.empty(); } void AttributesWriter::write() { std::vector< PlugAndObjArray >::iterator j = mPlugObjArrayVec.begin(); std::vector< PlugAndObjArray >::iterator jend = mPlugObjArrayVec.end(); for (; j != jend; j++) { MString propName = j->plug.partialName(0, 0, 0, 0, 0, 1); bool filledProp = attributeToArrayPropertyPair(j->obj, j->plug, j->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get sampled array property "; msg += j->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } std::vector< PlugAndObjScalar >::iterator k = mPlugObjScalarVec.begin(); std::vector< PlugAndObjScalar >::iterator kend = mPlugObjScalarVec.end(); for (; k != kend; ++k) { MString propName = k->plug.partialName(0, 0, 0, 0, 0, 1); bool filledProp = attributeToScalarPropertyPair(k->obj, k->plug, k->prop); if (!filledProp) { MString msg = "WARNING: Couldn't get sampled scalar property "; msg += k->plug.partialName(1, 0, 0, 0, 1, 1); msg += ", so skipping."; MGlobal::displayWarning(msg); continue; } } if (!mAnimVisibility.plug.isNull()) { Alembic::Util::int8_t visVal = -1; if (!mAnimVisibility.plug.asBool()) { visVal = 0; } mAnimVisibility.prop.set(&visVal); } }