unsigned SetFilter::computeMatch( const ScenePlug *scene, const Gaffer::Context *context ) const { if( !scene ) { return NoMatch; } const ScenePlug::ScenePath &path = context->get<ScenePlug::ScenePath>( ScenePlug::scenePathContextName ); // See explanatory comments in hashMatch(). ContextPtr tmpContext = new Context( *context, Context::Borrowed ); tmpContext->remove( Filter::inputSceneContextName ); tmpContext->remove( ScenePlug::scenePathContextName ); Context::Scope scopedContext( tmpContext.get() ); ConstPathMatcherDataPtr set = scene->set( setPlug()->getValue() ); return set->readable().match( path ); }
void SetFilter::hashMatch( const ScenePlug *scene, const Gaffer::Context *context, IECore::MurmurHash &h ) const { if( !scene ) { return; } /// \todo It would be preferable to throw an exception if the scene path isn't /// available, as we really do require it for computing a match. Currently we /// can't do that because the Isolate and Prune must include the filter hash when /// hashing their sets, because they will use the filter to remap the sets as /// a global operation. In this case, we're lucky that the hash (minus the scene path) /// of the SetFilter is sufficient to uniquely identify the remapping that will occur - filters /// which access scene data using the path would not have a valid hash in this scenario, /// which is the reason we don't yet have AttributeFilter etc. If we had a hierarchyHash for /// the scene then we would be able to use that in these situations and have a broader range /// of filters. If we manage that, then we should go back to throwing an exception here if /// the context doesn't contain a path. We should then do the same in the PathFilter. typedef IECore::TypedData<ScenePlug::ScenePath> ScenePathData; const ScenePathData *pathData = context->get<ScenePathData>( ScenePlug::scenePathContextName, 0 ); if( pathData ) { const ScenePlug::ScenePath &path = pathData->readable(); h.append( &(path[0]), path.size() ); } // Remove unnecessary but frequently changed context entries. This // makes us friendlier to the hash caching mechanism in ValuePlug, // since it'll see fewer unnecessarily different contexts, and will // therefore get more cache hits. We do the same in computeMatch(). ContextPtr tmpContext = new Context( *context, Context::Borrowed ); tmpContext->remove( Filter::inputSceneContextName ); tmpContext->remove( ScenePlug::scenePathContextName ); Context::Scope scopedContext( tmpContext.get() ); h.append( scene->setHash( setPlug()->getValue() ) ); }
void Isolate::hashSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { FilteredSceneProcessor::hashSet( setName, context, parent, h ); inPlug()->setPlug()->hash( h ); fromPlug()->hash( h ); // The sets themselves do not depend on the "scene:path" // context entry - the whole point is that they're global. // However, the PathFilter is dependent on scene:path, so // we must remove the path before hashing in the filter in // case we're computed from multiple contexts with different // paths (from a SetFilter for instance). If we didn't do this, // our different hashes would lead to huge numbers of redundant // calls to computeSet() and a huge overhead in recomputing // the same sets repeatedly. // // See further comments in FilteredSceneProcessor::affects(). ContextPtr c = filterContext( context ); c->remove( ScenePlug::scenePathContextName ); Context::Scope s( c.get() ); filterPlug()->hash( h ); }