void Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim) { // Special-case the root (the only prim which has no parent) and // instancing masters. if (ARCH_UNLIKELY(not parent or isMasterPrim)) { _flags[Usd_PrimActiveFlag] = true; _flags[Usd_PrimLoadedFlag] = true; _flags[Usd_PrimModelFlag] = true; _flags[Usd_PrimGroupFlag] = true; _flags[Usd_PrimAbstractFlag] = false; _flags[Usd_PrimDefinedFlag] = true; _flags[Usd_PrimClipsFlag] = false; _flags[Usd_PrimInstanceFlag] = false; _flags[Usd_PrimMasterFlag] = isMasterPrim; } else { // Compose and cache 'active'. UsdPrim self(Usd_PrimDataIPtr(this)); bool active = true; self.GetMetadata(SdfFieldKeys->Active, &active); _flags[Usd_PrimActiveFlag] = active; // An active prim is loaded if it's loadable and in the load set, or // it's not loadable and its parent is loaded. _flags[Usd_PrimLoadedFlag] = active and (self.HasPayload() ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); // According to Model hierarchy rules, only Model Groups may have Model // children (groups or otherwise). So if our parent is not a Model // Group, then this prim cannot be a model (or a model group). // Otherwise we look up the kind metadata and consult the kind registry. _flags[Usd_PrimGroupFlag] = _flags[Usd_PrimModelFlag] = false; if (parent->IsGroup()) { static TfToken kindToken("kind"); TfToken kind; self.GetMetadata(kindToken, &kind); // Use the kind registry to determine model/groupness. if (not kind.IsEmpty()) { _flags[Usd_PrimGroupFlag] = KindRegistry::IsA(kind, KindTokens->group); _flags[Usd_PrimModelFlag] = _flags[Usd_PrimGroupFlag] or KindRegistry::IsA(kind, KindTokens->model); } } // Get specifier. SdfSpecifier specifier = GetSpecifier(); // This prim is abstract if its parent is or if it's a class. _flags[Usd_PrimAbstractFlag] = parent->IsAbstract() or specifier == SdfSpecifierClass; // This prim is defined if its parent is defined and its specifier is // defining. const bool specifierIsDefining = SdfIsDefiningSpecifier(specifier); _flags[Usd_PrimDefinedFlag] = parent->IsDefined() and specifierIsDefining; _flags[Usd_PrimHasDefiningSpecifierFlag] = specifierIsDefining; // The presence of clips that may affect attributes on this prim // is computed and set in UsdStage. Default to false. _flags[Usd_PrimClipsFlag] = false; // These flags indicate whether this prim is an instance or an // instance master. _flags[Usd_PrimInstanceFlag] = active and _primIndex->IsInstanceable(); _flags[Usd_PrimMasterFlag] = parent->IsInMaster(); } }
bool UsdRelationship::GetTargets(SdfPathVector* targets) const { TRACE_FUNCTION(); UsdStage *stage = _GetStage(); PcpErrorVector pcpErrors; std::vector<std::string> otherErrors; PcpTargetIndex targetIndex; { // Our intention is that the following code requires read-only // access to the PcpCache, so use a const-ref. const PcpCache& pcpCache(*stage->_GetPcpCache()); // In USD mode, Pcp does not cache property indexes, so we // compute one here ourselves and use that. First, we need // to get the prim index of the owning prim. const PcpPrimIndex &primIndex = _Prim()->GetPrimIndex(); // PERFORMANCE: Here we can't avoid constructing the full property path // without changing the Pcp API. We're about to do serious // composition/indexing, though, so the added expense may be neglible. const PcpSite propSite(pcpCache.GetLayerStackIdentifier(), GetPath()); PcpPropertyIndex propIndex; PcpBuildPrimPropertyIndex(propSite.path, pcpCache, primIndex, &propIndex, &pcpErrors); PcpBuildTargetIndex(propSite, propIndex, SdfSpecTypeRelationship, &targetIndex, &pcpErrors); } targets->swap(targetIndex.paths); if (!targets->empty() && _Prim()->IsInMaster()) { Usd_PrimDataConstPtr master = get_pointer(_Prim()); while (!master->IsMaster()) { master = master->GetParent(); } // Paths that point to an object under the master's source prim index // are internal to the master and need to be translated to either // the master or instance we're currently looking at. const SdfPath& masterSourcePrimIndexPath = master->GetSourcePrimIndex().GetPath(); if (GetPrim().IsInMaster()) { // Translate any paths that point to an object at or under the // source prim index to our master. for (SdfPath& target : *targets) { target = target.ReplacePrefix( masterSourcePrimIndexPath, master->GetPath()); } } else if (GetPrim().IsInstanceProxy()) { // Translate any paths that point to an object at or under the // source prim index to our instance. UsdPrim instance = GetPrim(); while (!instance.IsInstance()) { instance = instance.GetParent(); } for (SdfPath& target : *targets) { target = target.ReplacePrefix( masterSourcePrimIndexPath, instance.GetPath()); } } } // TODO: handle errors const bool hasErrors = !(pcpErrors.empty() && otherErrors.empty()); if (hasErrors) { stage->_ReportErrors( pcpErrors, otherErrors, TfStringPrintf("Getting targets for relationship <%s>", GetPath().GetText())); } return !hasErrors; }
void Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim) { // We do not have to clear _flags here since in the pseudo root or instance // master case the values never change, and in the ordinary prim case we set // every flag. // Special-case the root (the only prim which has no parent) and // instancing masters. if (ARCH_UNLIKELY(!parent || isMasterPrim)) { _flags[Usd_PrimActiveFlag] = true; _flags[Usd_PrimLoadedFlag] = true; _flags[Usd_PrimModelFlag] = true; _flags[Usd_PrimGroupFlag] = true; _flags[Usd_PrimDefinedFlag] = true; _flags[Usd_PrimMasterFlag] = isMasterPrim; } else { // Compose and cache 'active'. UsdPrim self(Usd_PrimDataIPtr(this), SdfPath()); bool active = true; self.GetMetadata(SdfFieldKeys->Active, &active); _flags[Usd_PrimActiveFlag] = active; // Cache whether or not this prim has a payload. bool hasPayload = _primIndex->HasPayload(); _flags[Usd_PrimHasPayloadFlag] = hasPayload; // An active prim is loaded if it's loadable and in the load set, or // it's not loadable and its parent is loaded. _flags[Usd_PrimLoadedFlag] = active && (hasPayload ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); // According to Model hierarchy rules, only Model Groups may have Model // children (groups or otherwise). So if our parent is not a Model // Group, then this prim cannot be a model (or a model group). // Otherwise we look up the kind metadata and consult the kind registry. bool isGroup = false, isModel = false; if (parent->IsGroup()) { static TfToken kindToken("kind"); TfToken kind; self.GetMetadata(kindToken, &kind); // Use the kind registry to determine model/groupness. if (!kind.IsEmpty()) { isGroup = KindRegistry::IsA(kind, KindTokens->group); isModel = isGroup || KindRegistry::IsA(kind, KindTokens->model); } } _flags[Usd_PrimGroupFlag] = isGroup; _flags[Usd_PrimModelFlag] = isModel; // Get specifier. SdfSpecifier specifier = GetSpecifier(); // This prim is abstract if its parent is or if it's a class. _flags[Usd_PrimAbstractFlag] = parent->IsAbstract() || specifier == SdfSpecifierClass; // Cache whether or not this prim has an authored defining specifier. const bool isDefiningSpec = SdfIsDefiningSpecifier(specifier); _flags[Usd_PrimHasDefiningSpecifierFlag] = isDefiningSpec; // This prim is defined if its parent is and its specifier is defining. _flags[Usd_PrimDefinedFlag] = isDefiningSpec && parent->IsDefined(); // The presence of clips that may affect attributes on this prim // is computed and set in UsdStage. Default to false. _flags[Usd_PrimClipsFlag] = false; // These flags indicate whether this prim is an instance or an // instance master. _flags[Usd_PrimInstanceFlag] = active && _primIndex->IsInstanceable(); _flags[Usd_PrimMasterFlag] = parent->IsInMaster(); } }