UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdAttr( const MPlug& plg, const UsdPrim& usdPrim, const std::string &attrName, bool custom) { MObject attrObj(plg.attribute()); TfToken usdAttrName(attrName); if (usdAttrName.IsEmpty()) { printf("Invalid attrName '%s' for %s\n", attrName.c_str(), plg.name().asChar()); return UsdAttribute(); } // See if usdAttr already exists. If so, return. UsdAttribute usdAttr = usdPrim.GetAttribute(usdAttrName); if (usdAttr) { return usdAttr; } SdfValueTypeName attrType = PxrUsdMayaWriteUtil::GetUsdTypeName(plg); // --------------------- // CreateAttribute on USD Prim if specified above if (attrType) { usdAttr = usdPrim.CreateAttribute(usdAttrName, attrType, custom); } else { // Skipping. Unsupported type. } return usdAttr; }
/* static */ UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdRiAttribute( const MPlug& attrPlug, const UsdPrim& usdPrim, const std::string& attrName, const std::string& nameSpace, const bool translateMayaDoubleToUsdSinglePrecision) { UsdAttribute usdAttr; if (!usdPrim) { return usdAttr; } MObject attrObj(attrPlug.attribute()); TfToken riAttrNameToken(attrName); if (riAttrNameToken.IsEmpty()) { MGlobal::displayError( TfStringPrintf("Invalid UsdRi attribute name '%s' for Maya plug '%s'", attrName.c_str(), attrPlug.name().asChar()).c_str()); return usdAttr; } UsdRiStatements riStatements(usdPrim); if (!riStatements) { return usdAttr; } // See if a UsdRi attribute with this name already exists. If so, return it. // XXX: There isn't currently API for looking for a specific UsdRi attribute // by name, so we have to get them all and then see if one matches. const std::vector<UsdProperty>& riAttrs = riStatements.GetRiAttributes(nameSpace); TF_FOR_ALL(iter, riAttrs) { if (iter->GetBaseName() == riAttrNameToken) { // Re-get the attribute from the prim so we can return it as a // UsdAttribute rather than a UsdProperty. return usdPrim.GetAttribute(iter->GetName()); } } const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug, translateMayaDoubleToUsdSinglePrecision); if (typeName) { usdAttr = riStatements.CreateRiAttribute(riAttrNameToken, typeName.GetType(), nameSpace); } return usdAttr; }
/* static */ UsdGeomPrimvar PxrUsdMayaWriteUtil::GetOrCreatePrimvar( const MPlug& attrPlug, UsdGeomImageable& imageable, const std::string& primvarName, const TfToken& interpolation, const int elementSize, const bool custom, const bool translateMayaDoubleToUsdSinglePrecision) { UsdGeomPrimvar primvar; if (!imageable) { return primvar; } MObject attrObj(attrPlug.attribute()); TfToken primvarNameToken(primvarName); if (primvarNameToken.IsEmpty()) { MGlobal::displayError( TfStringPrintf("Invalid primvar name '%s' for Maya plug '%s'", primvarName.c_str(), attrPlug.name().asChar()).c_str()); return primvar; } // See if the primvar already exists. If so, return it. primvar = imageable.GetPrimvar(primvarNameToken); if (primvar) { return primvar; } const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug, translateMayaDoubleToUsdSinglePrecision); if (typeName) { primvar = imageable.CreatePrimvar(primvarNameToken, typeName, interpolation, elementSize, custom); } return primvar; }
PXR_NAMESPACE_OPEN_SCOPE static bool _GetMayaAttributeNumericTypedAndUnitDataTypes( const MPlug& attrPlug, MFnNumericData::Type& numericDataType, MFnData::Type& typedDataType, MFnUnitAttribute::Type& unitDataType) { numericDataType = MFnNumericData::kInvalid; typedDataType = MFnData::kInvalid; unitDataType = MFnUnitAttribute::kInvalid; MObject attrObj(attrPlug.attribute()); if (attrObj.isNull()) { return false; } if (attrObj.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute numericAttrFn(attrObj); numericDataType = numericAttrFn.unitType(); } else if (attrObj.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute typedAttrFn(attrObj); typedDataType = typedAttrFn.attrType(); if (typedDataType == MFnData::kNumeric) { // Inspect the type of the data itself to find the actual type. MObject plugObj = attrPlug.asMObject(); if (plugObj.hasFn(MFn::kNumericData)) { MFnNumericData numericDataFn(plugObj); numericDataType = numericDataFn.numericType(); } } } else if (attrObj.hasFn(MFn::kUnitAttribute)) { MFnUnitAttribute unitAttrFn(attrObj); unitDataType = unitAttrFn.unitType(); } return true; }
/* static */ UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdAttr( const MPlug& attrPlug, const UsdPrim& usdPrim, const std::string& attrName, const bool custom, const bool translateMayaDoubleToUsdSinglePrecision) { UsdAttribute usdAttr; if (!usdPrim) { return usdAttr; } MObject attrObj(attrPlug.attribute()); TfToken usdAttrNameToken(attrName); if (usdAttrNameToken.IsEmpty()) { MGlobal::displayError( TfStringPrintf("Invalid USD attribute name '%s' for Maya plug '%s'", attrName.c_str(), attrPlug.name().asChar()).c_str()); return usdAttr; } // See if the USD attribute already exists. If so, return it. usdAttr = usdPrim.GetAttribute(usdAttrNameToken); if (usdAttr) { return usdAttr; } const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug, translateMayaDoubleToUsdSinglePrecision); if (typeName) { usdAttr = usdPrim.CreateAttribute(usdAttrNameToken, typeName, custom); } return usdAttr; }
bool PxrUsdMayaWriteUtil::SetUsdAttr( const MPlug& attrPlug, const UsdAttribute& usdAttr, const UsdTimeCode& usdTime, const bool translateMayaDoubleToUsdSinglePrecision) { if (!usdAttr || attrPlug.isNull()) { return false; } bool isAnimated = attrPlug.isDestination(); if (usdTime.IsDefault() == isAnimated) { return true; } // We perform a similar set of type-infererence acrobatics here as we do up // above in GetUsdTypeName(). See the comments there for more detail on a // few type-related oddities. MObject attrObj(attrPlug.attribute()); if (attrObj.hasFn(MFn::kEnumAttribute)) { MFnEnumAttribute enumAttrFn(attrObj); const short enumIndex = attrPlug.asShort(); const TfToken enumToken(enumAttrFn.fieldName(enumIndex).asChar()); return usdAttr.Set(enumToken, usdTime); } MFnNumericData::Type numericDataType; MFnData::Type typedDataType; MFnUnitAttribute::Type unitDataType; _GetMayaAttributeNumericTypedAndUnitDataTypes(attrPlug, numericDataType, typedDataType, unitDataType); if (attrObj.hasFn(MFn::kMatrixAttribute)) { typedDataType = MFnData::kMatrix; } switch (typedDataType) { case MFnData::kString: { MFnStringData stringDataFn(attrPlug.asMObject()); const std::string usdVal(stringDataFn.string().asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kMatrix: { MFnMatrixData matrixDataFn(attrPlug.asMObject()); const GfMatrix4d usdVal(matrixDataFn.matrix().matrix); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kStringArray: { MFnStringArrayData stringArrayDataFn(attrPlug.asMObject()); VtStringArray usdVal(stringArrayDataFn.length()); for (unsigned int i = 0; i < stringArrayDataFn.length(); ++i) { usdVal[i] = std::string(stringArrayDataFn[i].asChar()); } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kDoubleArray: { MFnDoubleArrayData doubleArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtFloatArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = (float)doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } else { VtDoubleArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kFloatArray: { MFnFloatArrayData floatArrayDataFn(attrPlug.asMObject()); VtFloatArray usdVal(floatArrayDataFn.length()); for (unsigned int i = 0; i < floatArrayDataFn.length(); ++i) { usdVal[i] = floatArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kIntArray: { MFnIntArrayData intArrayDataFn(attrPlug.asMObject()); VtIntArray usdVal(intArrayDataFn.length()); for (unsigned int i = 0; i < intArrayDataFn.length(); ++i) { usdVal[i] = intArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kPointArray: { MFnPointArrayData pointArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kVectorArray: { MFnVectorArrayData vectorArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } default: break; } switch (numericDataType) { case MFnNumericData::kBoolean: { const bool usdVal(attrPlug.asBool()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kByte: case MFnNumericData::kChar: { const int usdVal(attrPlug.asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kShort: { const int usdVal(attrPlug.asShort()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kInt: { const int usdVal(attrPlug.asInt()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Short: { short tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k2Int: { int tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Short: { short tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k3Int: { int tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kFloat: { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Float: { float tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2f(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Float: { float tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return _SetVec(usdAttr, GfVec3f(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kDouble: { const double usdVal(attrPlug.asDouble()); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set((float)usdVal, usdTime); } else { return usdAttr.Set(usdVal, usdTime); } break; } case MFnNumericData::k2Double: { double tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set(GfVec2f((float)tmp1, (float)tmp2), usdTime); } else { return usdAttr.Set(GfVec2d(tmp1, tmp2), usdTime); } break; } case MFnNumericData::k3Double: { double tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec3f((float)tmp1, (float)tmp2, (float)tmp3), usdTime); } else { return _SetVec(usdAttr, GfVec3d(tmp1, tmp2, tmp3), usdTime); } break; } case MFnNumericData::k4Double: { double tmp1, tmp2, tmp3, tmp4; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3, tmp4); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec4f((float)tmp1, (float)tmp2, (float)tmp3, (float)tmp4), usdTime); } else { return _SetVec(usdAttr, GfVec4d(tmp1, tmp2, tmp3, tmp4), usdTime); } break; } default: break; } switch (unitDataType) { case MFnUnitAttribute::kAngle: case MFnUnitAttribute::kDistance: if (translateMayaDoubleToUsdSinglePrecision) { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); } else { const double usdVal(attrPlug.asDouble()); return usdAttr.Set(usdVal, usdTime); } break; default: break; } return false; }
SdfValueTypeName PxrUsdMayaWriteUtil::GetUsdTypeName( const MPlug& attrPlug, const bool translateMayaDoubleToUsdSinglePrecision) { // The various types of Maya attributes that can be created are spread // across a handful of MFn function sets. Some are a straightforward // translation such as MFnEnumAttributes or MFnMatrixAttributes, but others // are interesting mixes of function sets. For example, an attribute created // with addAttr and 'double' as the type results in an MFnNumericAttribute // while 'double2' as the type results in an MFnTypedAttribute that has // MFnData::Type kNumeric. MObject attrObj(attrPlug.attribute()); if (attrObj.isNull()) { return SdfValueTypeName(); } if (attrObj.hasFn(MFn::kEnumAttribute)) { return SdfValueTypeNames->Token; } MFnNumericData::Type numericDataType; MFnData::Type typedDataType; MFnUnitAttribute::Type unitDataType; _GetMayaAttributeNumericTypedAndUnitDataTypes(attrPlug, numericDataType, typedDataType, unitDataType); if (attrObj.hasFn(MFn::kMatrixAttribute)) { // Using type "fltMatrix" with addAttr results in an MFnMatrixAttribute // while using type "matrix" results in an MFnTypedAttribute with type // kMatrix, but the data is extracted the same way for both. typedDataType = MFnData::kMatrix; } // Deal with the MFnTypedAttribute attributes first. If it is numeric, it // will fall through to the numericDataType switch below. switch (typedDataType) { case MFnData::kString: return SdfValueTypeNames->String; break; case MFnData::kMatrix: // This must be a Matrix4d even if // translateMayaDoubleToUsdSinglePrecision is true, since Matrix4f // is not supported in Sdf. return SdfValueTypeNames->Matrix4d; break; case MFnData::kStringArray: return SdfValueTypeNames->StringArray; break; case MFnData::kDoubleArray: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->FloatArray; } else { return SdfValueTypeNames->DoubleArray; } break; case MFnData::kFloatArray: return SdfValueTypeNames->FloatArray; break; case MFnData::kIntArray: return SdfValueTypeNames->IntArray; break; case MFnData::kPointArray: // Sdf does not have a 4-float point type, so we'll divide out W // and export the points as 3 floats. if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Point3fArray; } else { return SdfValueTypeNames->Point3dArray; } break; case MFnData::kVectorArray: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Vector3fArray; } else { return SdfValueTypeNames->Vector3dArray; } break; default: break; } switch (numericDataType) { case MFnNumericData::kBoolean: return SdfValueTypeNames->Bool; break; case MFnNumericData::kByte: case MFnNumericData::kChar: case MFnNumericData::kShort: // Maya treats longs the same as ints, since long is not // platform-consistent. The Maya constants MFnNumericData::kInt and // MFnNumericData::kLong have the same value. The same is true of // k2Int/k2Long and k3Int/k3Long. case MFnNumericData::kInt: return SdfValueTypeNames->Int; break; case MFnNumericData::k2Short: case MFnNumericData::k2Int: return SdfValueTypeNames->Int2; break; case MFnNumericData::k3Short: case MFnNumericData::k3Int: return SdfValueTypeNames->Int3; break; case MFnNumericData::kFloat: return SdfValueTypeNames->Float; break; case MFnNumericData::k2Float: return SdfValueTypeNames->Float2; break; case MFnNumericData::k3Float: if (MFnAttribute(attrObj).isUsedAsColor()) { return SdfValueTypeNames->Color3f; } else { return SdfValueTypeNames->Float3; } break; case MFnNumericData::kDouble: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Float; } else { return SdfValueTypeNames->Double; } break; case MFnNumericData::k2Double: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Float2; } else { return SdfValueTypeNames->Double2; } break; case MFnNumericData::k3Double: if (MFnAttribute(attrObj).isUsedAsColor()) { if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Color3f; } else { return SdfValueTypeNames->Color3d; } } else { if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Float3; } else { return SdfValueTypeNames->Double3; } } break; case MFnNumericData::k4Double: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Float4; } else { return SdfValueTypeNames->Double4; } break; default: break; } switch (unitDataType) { case MFnUnitAttribute::kAngle: case MFnUnitAttribute::kDistance: if (translateMayaDoubleToUsdSinglePrecision) { return SdfValueTypeNames->Float; } else { return SdfValueTypeNames->Double; } break; default: break; } return SdfValueTypeName(); }
SdfValueTypeName PxrUsdMayaWriteUtil::GetUsdTypeName( const MPlug& plg) { MObject attrObj(plg.attribute()); SdfValueTypeName attrType; if (attrObj.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute attrNumericFn(attrObj); switch (attrNumericFn.unitType()) { case MFnNumericData::kBoolean: attrType = SdfValueTypeNames->Bool; break; case MFnNumericData::kByte: case MFnNumericData::kChar: case MFnNumericData::kShort: case MFnNumericData::kInt: attrType = SdfValueTypeNames->Int; break; /* We could do these, but there doesn't seem to be a good way of extracting the data later on. For a Maya expert to solve... case MFnNumericData::kLong: attrType = SdfValueTypeNames->Int64; break; case MFnNumericData::kAddr: attrType = SdfValueTypeNames->UInt64; break; */ case MFnNumericData::kFloat: attrType = SdfValueTypeNames->Float; break; case MFnNumericData::kDouble: attrType = SdfValueTypeNames->Double; break; case MFnNumericData::k2Short: case MFnNumericData::k2Int: //case MFnNumericData::k2Long: attrType = SdfValueTypeNames->Int2; break; case MFnNumericData::k3Short: case MFnNumericData::k3Int: //case MFnNumericData::k3Long: attrType = SdfValueTypeNames->Int3; break; case MFnNumericData::k2Float: attrType = SdfValueTypeNames->Float2; break; case MFnNumericData::k3Float: if (MFnAttribute(attrObj).isUsedAsColor()) { attrType = SdfValueTypeNames->Color3f; } else { attrType = SdfValueTypeNames->Float3; } break; case MFnNumericData::k2Double: attrType = SdfValueTypeNames->Double2; break; case MFnNumericData::k3Double: if (MFnAttribute(attrObj).isUsedAsColor()) { attrType = SdfValueTypeNames->Color3d; } else { attrType = SdfValueTypeNames->Double3; } break; case MFnNumericData::k4Double: attrType = SdfValueTypeNames->Double4; break; default: break; } } else if (attrObj.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute attrTypedFn(attrObj); switch (attrTypedFn.attrType()) { case MFnData::kString: attrType = SdfValueTypeNames->String; break; case MFnData::kMatrix: attrType = SdfValueTypeNames->Matrix4d; break; case MFnData::kStringArray: attrType = SdfValueTypeNames->StringArray; break; case MFnData::kIntArray: attrType = SdfValueTypeNames->IntArray; break; case MFnData::kFloatArray: attrType = SdfValueTypeNames->FloatArray; break; case MFnData::kDoubleArray: attrType = SdfValueTypeNames->DoubleArray; break; case MFnData::kVectorArray: attrType = SdfValueTypeNames->Vector3dArray; break; case MFnData::kPointArray: attrType = SdfValueTypeNames->Point3dArray; break; default: break; } } else if (attrObj.hasFn(MFn::kUnitAttribute)) { //MFnUnitAttribute attrUnitFn(attrObj); } else if (attrObj.hasFn(MFn::kEnumAttribute)) { attrType = SdfValueTypeNames->Token; } return attrType; }