static rj::Value _JsValueToImplValue( const JsValue& value, Allocator& allocator) { switch (value.GetType()) { case JsValue::ObjectType: return _ToImplObjectValue(value.GetJsObject(), allocator); case JsValue::ArrayType: return _ToImplArrayValue(value.GetJsArray(), allocator); case JsValue::BoolType: return rj::Value(value.GetBool()); case JsValue::StringType: return rj::Value(value.GetString().c_str(), allocator); case JsValue::RealType: return rj::Value(value.GetReal()); case JsValue::IntType: return value.IsUInt64() ? rj::Value(value.GetUInt64()) : rj::Value(value.GetInt64()); case JsValue::NullType: return rj::Value(); default: { TF_CODING_ERROR("Unknown JsValue type"); return rj::Value(); } } }
static bool _ReadNestedDict( const JsObject& data, const std::vector<TfToken>& keys, JsObject* dict) { JsObject currDict = data; TF_FOR_ALL(iter, keys) { const TfToken& currKey = *iter; JsValue any; if (!TfMapLookup(currDict, currKey, &any)) { return false; } if (!any.IsObject()) { TF_CODING_ERROR("bad plugInfo data."); return false; } currDict = any.GetJsObject(); } *dict = currDict; return true; }
int main(int argc, char const *argv[]) { std::cout << "opening values.json" << std::endl; std::ifstream ifs("values.json"); if (!ifs) { TF_CODING_ERROR("Failed to open 'values.json' for reading"); return 1; } // Set up expected values. std::cout << "parsing input stream" << std::endl; const JsValue value = JsParseStream(ifs); TF_AXIOM(value); TF_AXIOM(value.IsObject()); std::cout << "unwrapping envelope" << std::endl; JsObject envelope = value.GetJsObject(); TF_AXIOM(envelope["Object"].IsObject()); JsObject object = envelope["Object"].GetJsObject(); TF_AXIOM(!object.empty()); // Convert the top-level value to another container type. std::cout << "converting container" << std::endl; const _Any result = JsConvertToContainerType<_Any, _Dictionary>(value); TF_AXIOM(!IsEmpty(result)); TF_AXIOM(IsHolding<_Dictionary>(result)); std::cout << "checking converted top-level object" << std::endl; const _Dictionary& dict = Get<_Dictionary>(result); _Dictionary::const_iterator i = dict.find("Object"); TF_AXIOM(i != dict.end()); TF_AXIOM(IsHolding<_Dictionary>(i->second)); const _Dictionary& aObject = Get<_Dictionary>(i->second); std::cout << "checking converted values" << std::endl; for (const auto& p : aObject) { const std::type_info* ti = GetType(p.second); indent << "key " << p.first << " typeid is " << (ti ? ArchGetDemangled(*ti) : "nil") << std::endl; IndenterScope scope(*indenter); if (p.first == "Array") { indent << "checking array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); // This array has heterogeneous values, so IsArrayOf<T> should // always return false. TF_AXIOM(!object[p.first].IsArrayOf<JsObject>()); TF_AXIOM(!object[p.first].IsArrayOf<JsArray>()); TF_AXIOM(!object[p.first].IsArrayOf<string>()); TF_AXIOM(!object[p.first].IsArrayOf<double>()); TF_AXIOM(!object[p.first].IsArrayOf<int>()); TF_AXIOM(!object[p.first].IsArrayOf<int64_t>()); TF_AXIOM(!object[p.first].IsArrayOf<uint64_t>()); } else if (p.first == "ArrayString") { indent << "checking string array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(object[p.first].Is<JsArray>()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); _CheckArrayOf<string>(object[p.first]); } else if (p.first == "ArrayInt64") { indent << "checking int64 array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(object[p.first].Is<JsArray>()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); _CheckArrayOf<int64_t>(object[p.first]); } else if (p.first == "ArrayUInt64") { indent << "checking uint array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(object[p.first].Is<JsArray>()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); _CheckArrayOf<uint64_t>(object[p.first]); } else if (p.first == "ArrayReal") { indent << "checking real array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(object[p.first].Is<JsArray>()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); _CheckArrayOf<double>(object[p.first]); } else if (p.first == "ArrayBool") { indent << "checking bool array conversion" << std::endl; TF_AXIOM(object[p.first].IsArray()); TF_AXIOM(object[p.first].Is<JsArray>()); TF_AXIOM(IsHolding<_AnyVector>(p.second)); _CheckArray(Get<_AnyVector>(p.second), object[p.first].GetJsArray()); _CheckArray(Get<_AnyVector>(p.second), object[p.first].Get<JsArray>()); _CheckArrayOf<bool>(object[p.first]); } else if (p.first == "String") { indent << "checking string conversion" << std::endl; TF_AXIOM(object[p.first].IsString()); TF_AXIOM(object[p.first].Is<string>()); TF_AXIOM(IsHolding<string>(p.second)); TF_AXIOM(Get<string>(p.second) == object[p.first].GetString()); TF_AXIOM(Get<string>(p.second) == object[p.first].Get<string>()); } else if (p.first == "Int64") { indent << "checking int conversion" << std::endl; TF_AXIOM(object[p.first].IsInt()); TF_AXIOM(object[p.first].Is<int64_t>()); TF_AXIOM(IsHolding<int64_t>(p.second)); TF_AXIOM(Get<int64_t>(p.second) == object[p.first].GetInt()); TF_AXIOM(Get<int64_t>(p.second) == object[p.first].Get<int64_t>()); } else if (p.first == "UInt64") { indent << "checking uint conversion" << std::endl; TF_AXIOM(object[p.first].IsInt()); TF_AXIOM(object[p.first].Is<uint64_t>()); TF_AXIOM(IsHolding<uint64_t>(p.second)); TF_AXIOM(Get<uint64_t>(p.second) == static_cast<uint64_t>(object[p.first].GetInt())); TF_AXIOM(Get<uint64_t>(p.second) == object[p.first].Get<uint64_t>()); } else if (p.first == "Real") { indent << "checking real conversion" << std::endl; TF_AXIOM(object[p.first].IsReal()); TF_AXIOM(object[p.first].Is<double>()); TF_AXIOM(IsHolding<double>(p.second)); TF_AXIOM(Get<double>(p.second) == object[p.first].GetReal()); TF_AXIOM(Get<double>(p.second) == object[p.first].Get<double>()); } else if (p.first == "BoolTrue") { indent << "checking bool(true) conversion" << std::endl; TF_AXIOM(object[p.first].IsBool()); TF_AXIOM(object[p.first].Is<bool>()); TF_AXIOM(IsHolding<bool>(p.second)); TF_AXIOM(Get<bool>(p.second)); TF_AXIOM(object[p.first].Get<bool>()); } else if (p.first == "BoolFalse") { indent << "checking bool(false) conversion" << std::endl; TF_AXIOM(object[p.first].IsBool()); TF_AXIOM(object[p.first].Is<bool>()); TF_AXIOM(IsHolding<bool>(p.second)); TF_AXIOM(!Get<bool>(p.second)); TF_AXIOM(!object[p.first].Get<bool>()); } else if (p.first == "Null") { indent << "checking null conversion" << std::endl; TF_AXIOM(object[p.first].IsNull()); TF_AXIOM(IsEmpty(p.second)); } } std::cout << "PASSED" << std::endl; return 0; }
/* static */ std::vector<UsdMayaUserTaggedAttribute> UsdMayaUserTaggedAttribute::GetUserTaggedAttributesForNode( const MObject& mayaNode) { std::vector<UsdMayaUserTaggedAttribute> result; MStatus status; const MFnDependencyNode depNodeFn(mayaNode, &status); if (status != MS::kSuccess) { return result; } const MPlug exportedAttrsJsonPlug = depNodeFn.findPlug( _tokens->USD_UserExportedAttributesJson.GetText(), true, &status); if (status != MS::kSuccess || exportedAttrsJsonPlug.isNull()) { // No attributes specified for export on this node. return result; } const std::string exportedAttrsJsonString( exportedAttrsJsonPlug.asString().asChar()); if (exportedAttrsJsonString.empty()) { return result; } JsParseError jsError; const JsValue jsValue = JsParseString(exportedAttrsJsonString, &jsError); if (!jsValue) { TF_RUNTIME_ERROR( "Failed to parse USD exported attributes JSON on node '%s' " "at line %d, column %d: %s", UsdMayaUtil::GetMayaNodeName(mayaNode).c_str(), jsError.line, jsError.column, jsError.reason.c_str()); return result; } // If an attribute is multiply-defined, we'll use the first tag encountered // and issue warnings for the subsequent definitions. JsObject is really // just a std::map, so we'll be considering attributes in sorted order. std::set<std::string> processedAttributeNames; const JsObject& exportedAttrs = jsValue.GetJsObject(); for (const auto& exportedAttr : exportedAttrs) { const std::string mayaAttrName = exportedAttr.first; const MPlug attrPlug = depNodeFn.findPlug(mayaAttrName.c_str(), true, &status); if (status != MS::kSuccess || attrPlug.isNull()) { TF_RUNTIME_ERROR( "Could not find attribute '%s' for USD export on node '%s'", mayaAttrName.c_str(), UsdMayaUtil::GetMayaNodeName(mayaNode).c_str()); continue; } const JsObject& attrMetadata = exportedAttr.second.GetJsObject(); // Check if this is a particular type of attribute (e.g. primvar or // usdRi attribute). If we don't recognize the type specified, we'll // fall back to a regular USD attribute. const TfToken usdAttrType( _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); // Check whether an interpolation type was specified. This is only // relevant for primvars. const TfToken interpolation( _GetExportAttributeMetadata(attrMetadata, UsdGeomTokens->interpolation)); // Check whether it was specified that the double precision Maya // attribute type should be mapped to a single precision USD type. // If it wasn't specified, use the fallback value. const bool translateMayaDoubleToUsdSinglePrecision( _GetExportAttributeMetadata( attrMetadata, _tokens->translateMayaDoubleToUsdSinglePrecision, GetFallbackTranslateMayaDoubleToUsdSinglePrecision())); // Check whether the USD attribute name should be different than the // Maya attribute name. std::string usdAttrName = _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); if (usdAttrName.empty()) { const auto& tokens = UsdMayaUserTaggedAttributeTokens; if (usdAttrType == tokens->USDAttrTypePrimvar || usdAttrType == tokens->USDAttrTypeUsdRi) { // Primvars and UsdRi attributes will be given a type-specific // namespace, so just use the Maya attribute name. usdAttrName = mayaAttrName; } else { // For regular USD attributes, when no name was specified we // prepend the userProperties namespace to the Maya attribute // name to get the USD attribute name. usdAttrName = _tokens->UserPropertiesNamespace.GetString() + mayaAttrName; } } const auto& insertIter = processedAttributeNames.emplace(usdAttrName); if (!insertIter.second) { TF_RUNTIME_ERROR( "Ignoring duplicate USD export tag for attribute '%s' " "on node '%s'", usdAttrName.c_str(), UsdMayaUtil::GetMayaNodeName(mayaNode).c_str()); continue; } result.emplace_back(attrPlug, usdAttrName, usdAttrType, interpolation, translateMayaDoubleToUsdSinglePrecision); } return result; }