// Helper function to make reading from dictionaries easier static bool _GetKey(const JsObject &dict, const std::string &key, JsObject *value) { JsObject::const_iterator i = dict.find(key); if (i != dict.end() && i->second.IsObject()) { *value = i->second.GetObject(); return true; } return false; }
ExpOperation* ExpWrapper::copy(Mutex* mtx) const { JsObject* jso = YOBJECT(JsObject,m_object); if (!jso) return ExpOperation::clone(); XDebug(DebugInfo,"ExpWrapper::copy(%p) [%p]",mtx,this); ExpWrapper* op = new ExpWrapper(jso->copy(mtx),name()); static_cast<String&>(*op) = *this; op->lineNumber(lineNumber()); return op; }
static std::string _GetExportAttributeMetadata( const JsObject& attrMetadata, const TfToken& keyToken) { std::string value; JsObject::const_iterator attrMetadataIter = attrMetadata.find(keyToken); if (attrMetadataIter != attrMetadata.end()) { value = attrMetadataIter->second.GetString(); } return value; }
static bool _GetExportAttributeMetadata( const JsObject& attrMetadata, const TfToken& keyToken, const bool defaultValue) { bool value = defaultValue; JsObject::const_iterator attrMetadataIter = attrMetadata.find(keyToken); if (attrMetadataIter != attrMetadata.end()) { value = attrMetadataIter->second.GetBool(); } return value; }
void KindRegistry::_RegisterDefaults() { // Initialize builtin kind hierarchy. _Register(KindTokens->subcomponent); _Register(KindTokens->model); _Register(KindTokens->component, KindTokens->model); _Register(KindTokens->group, KindTokens->model); _Register(KindTokens->assembly, KindTokens->group); // Check plugInfo for extensions to the kind hierarchy. // // XXX We only do this once, and do not re-build the kind hierarchy // if someone manages to add more plugins while the app is running. // This allows the KindRegistry to be threadsafe without locking. const PlugPluginPtrVector& plugins = PlugRegistry::GetInstance().GetAllPlugins(); TF_FOR_ALL(plug, plugins){ JsObject kinds; const JsObject &metadata = (*plug)->GetMetadata(); if (!_GetKey(metadata, _tokens->PluginKindsKey, &kinds)) continue; TF_FOR_ALL(kindEntry, kinds){ // Each entry is a map from kind -> metadata dict. TfToken kind(kindEntry->first); JsObject kindDict; if (!_GetKey(kinds, kind, &kindDict)){ TF_RUNTIME_ERROR("Expected dict for kind '%s'", kind.GetText()); continue; } // Check for baseKind. TfToken baseKind; JsObject::const_iterator i = kindDict.find("baseKind"); if (i != kindDict.end()) { if (i->second.IsString()) { baseKind = TfToken(i->second.GetString()); } else { TF_RUNTIME_ERROR("Expected string for baseKind"); continue; } } _Register(kind, baseKind); }
PXR_NAMESPACE_OPEN_SCOPE JsOptionalValue JsFindValue( const JsObject& object, const std::string& key, const JsOptionalValue& defaultValue) { if (key.empty()) { TF_CODING_ERROR("Key is empty"); return boost::none; } JsObject::const_iterator i = object.find(key); if (i != object.end()) return i->second; return defaultValue; }
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; }
// This method inspects the JSON blob stored in the 'USD_UserExportedAttributesJson' // attribute on the Maya node at dagPath and exports any attributes specified // there onto usdPrim at time usdTime. The JSON should contain an object that // maps Maya attribute names to other JSON objects that contain metadata about // how to export the attribute into USD. For example: // // { // "myMayaAttributeOne": { // }, // "myMayaAttributeTwo": { // "usdAttrName": "my:namespace:attributeTwo" // } // } // // If the attribute metadata contains a value for "usdAttrName", the attribute // will be given that name in USD. Otherwise, the Maya attribute name will be // used. Maya attributes in the JSON will be processed in sorted order, and any // USD attribute name collisions will be resolved by using the first attribute // visited and warning about subsequent attribute tags. // bool PxrUsdMayaWriteUtil::WriteUserExportedAttributes( const MDagPath& dagPath, const UsdPrim& usdPrim, const UsdTimeCode& usdTime) { MStatus status; MFnDependencyNode depFn(dagPath.node()); MPlug exportedAttrsJsonPlug = depFn.findPlug( _tokens->USD_UserExportedAttributesJson.GetText(), true, &status); if (status != MS::kSuccess || exportedAttrsJsonPlug.isNull()) { // No attributes specified for export on this node. return false; } std::string exportedAttrsJsonString(exportedAttrsJsonPlug.asString().asChar()); if (exportedAttrsJsonString.empty()) { return false; } JsParseError jsError; JsValue jsValue = JsParseString(exportedAttrsJsonString, &jsError); if (not jsValue) { MString errorMsg(TfStringPrintf( "Failed to parse USD exported attributes JSON on node at dagPath '%s'" " at line %d, column %d: %s", dagPath.fullPathName().asChar(), jsError.line, jsError.column, jsError.reason.c_str()).c_str()); MGlobal::displayError(errorMsg); return false; } // Maintain a set of USD attribute names that have been processed. 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> exportedUsdAttrNames; JsObject exportedAttrs = jsValue.GetObject(); for (JsObject::const_iterator iter = exportedAttrs.begin(); iter != exportedAttrs.end(); ++iter) { const std::string mayaAttrName = iter->first; const MPlug attrPlug = depFn.findPlug(mayaAttrName.c_str(), true, &status); if (status != MS::kSuccess || attrPlug.isNull()) { MString errorMsg(TfStringPrintf( "Could not find attribute '%s' for USD export on node at dagPath '%s'", mayaAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); MGlobal::displayError(errorMsg); continue; } const JsObject attrMetadata = iter->second.GetObject(); // Check the metadata to see if the USD attribute name should be // different than the Maya attribute name. std::string usdAttrName = mayaAttrName; JsObject::const_iterator usdAttrValueIter = attrMetadata.find(_tokens->usdAttrName); if (usdAttrValueIter != attrMetadata.end()) { std::string nameValue = usdAttrValueIter->second.GetString(); if (not nameValue.empty()) { usdAttrName = nameValue; } } const auto& insertIter = exportedUsdAttrNames.insert(usdAttrName); if (not insertIter.second) { MString errorMsg(TfStringPrintf( "Ignoring duplicate USD export tag for attribute '%s' on node at dagPath '%s'", usdAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); MGlobal::displayError(errorMsg); continue; } UsdAttribute usdAttr = PxrUsdMayaWriteUtil::GetOrCreateUsdAttr( attrPlug, usdPrim, usdAttrName, true); if (usdAttr) { PxrUsdMayaWriteUtil::SetUsdAttr(attrPlug, usdAttr, usdTime); } } return true; }