2277 lines
66 KiB
C++
2277 lines
66 KiB
C++
//-*****************************************************************************
|
|
//
|
|
// 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<float> 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<double> 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<float> 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<float> 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<double> 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<double> 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<double> 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<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];
|
|
}
|
|
}
|
|
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<std::string>::const_iterator f;
|
|
std::vector<std::string>::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<std::string>::const_iterator it;
|
|
std::vector<std::string>::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);
|
|
}
|
|
|
|
}
|
|
|
|
|