static void loadSetWalk( const SceneInterface *s, const InternedString &setName, PathMatcher &set, const vector<InternedString> &path ) { if( s->hasTag( setName, SceneInterface::LocalTag ) ) { set.addPath( path ); } // Figure out if we need to recurse by querying descendant tags to see if they include // anything we're interested in. if( !s->hasTag( setName, SceneInterface::DescendantTag ) ) { return; } // Recurse to the children. SceneInterface::NameList childNames; s->childNames( childNames ); vector<InternedString> childPath( path ); childPath.push_back( InternedString() ); // room for the child name for( SceneInterface::NameList::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { ConstSceneInterfacePtr child = s->child( *it ); childPath.back() = *it; loadSetWalk( child.get(), setName, set, childPath ); } }
void SceneCacheNode<BaseType>::buildShapeFilterMenu( void *data, PRM_Name *menu, int maxSize, const PRM_SpareData *, const PRM_Parm * ) { SceneCacheNode<BaseType> *node = reinterpret_cast<SceneCacheNode<BaseType>*>( data ); if ( !node ) { return; } menu[0].setToken( "*" ); menu[0].setLabel( "*" ); std::string file; if ( !node->ensureFile( file ) ) { // mark the end of our menu menu[1].setToken( 0 ); return; } ConstSceneInterfacePtr scene = node->scene( file, node->getPath() ); if ( !scene ) { // mark the end of our menu menu[1].setToken( 0 ); return; } std::vector<std::string> objects; node->objectNames( scene.get(), objects ); std::sort( objects.begin(), objects.end() ); node->createMenu( menu, objects ); }
IECore::ConstCompoundObjectPtr SceneReader::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( ScenePath() ); if( !s ) { return parent->globalsPlug()->defaultValue(); } CompoundObjectPtr result = new CompoundObject; // figure out which tags we want to convert into sets vector<InternedString> allTags; s->readTags( allTags, SceneInterface::LocalTag | SceneInterface::DescendantTag ); const std::string setsString = setsPlug()->getValue(); Tokenizer setsTokenizer( setsString, boost::char_separator<char>( " " ) ); vector<InternedString> tagsToLoadAsSets; for( vector<InternedString>::const_iterator tIt = allTags.begin(), tEIt = allTags.end(); tIt != tEIt; ++tIt ) { for( Tokenizer::const_iterator sIt = setsTokenizer.begin(), sEIt = setsTokenizer.end(); sIt != sEIt; ++sIt ) { if( match( tIt->value(), *sIt ) ) { tagsToLoadAsSets.push_back( *tIt ); } } } // sort so that we can use lower_bound() in loadSetsWalk(). sort( tagsToLoadAsSets.begin(), tagsToLoadAsSets.end() ); // make sets for each of them, and then defer to loadSetsWalk() // to do the work. IECore::CompoundDataPtr sets = result->member<IECore::CompoundData>( "gaffer:sets", /* throwExceptions = */ false, /* createIfMissing = */ true ); vector<PathMatcher *> pathMatchers; for( vector<InternedString>::const_iterator it = tagsToLoadAsSets.begin(), eIt = tagsToLoadAsSets.end(); it != eIt; ++it ) { PathMatcherDataPtr d = sets->member<PathMatcherData>( *it, /* throwExceptions = */ false, /* createIfMissing = */ true ); pathMatchers.push_back( &(d->writable()) ); } loadSetsWalk( s.get(), tagsToLoadAsSets, pathMatchers, vector<InternedString>() ); return result; }
LinkedScene::LinkedScene( ConstSceneInterfacePtr mainScene ) : m_mainScene(const_cast<SceneInterface*>(mainScene.get())), m_linkedScene(0), m_rootLinkDepth(0), m_readOnly(true), m_atLink(false), m_timeRemapped(false) { if( SceneCachePtr scc = runTimeCast<SceneCache>( m_mainScene ) ) { m_readOnly = scc->readOnly(); } m_sampled = (runTimeCast<const SampledSceneInterface>(mainScene.get()) != NULL); }
ConstObjectPtr SceneShape::readSceneShapeLink( const MDagPath &p ) { MDagPath dagPath; SceneShape *sceneShape = findScene( p, true, &dagPath ); if ( !sceneShape ) { throw Exception("readSceneShapeLink: Could not find SceneShape!"); } ConstSceneInterfacePtr scene = sceneShape->getSceneInterface(); if ( !scene ) { throw Exception( "Empty scene!"); } MFnDagNode fnChildDag( dagPath ); MStatus st; MPlug timePlug = fnChildDag.findPlug( aTime, &st ); if( !st ) { throw Exception( "Could not find 'time' plug in SceneShape!"); } // if time plug is connected to maya global time, then we assume there's no time remapping between the Maya scene and the loaded scene. MPlugArray array; timePlug.connectedTo( array, true, false, &st ); if( !st ) { throw Exception( "Could not find 'time' plug connections in SceneShape!"); } for ( unsigned int i = 0; i < array.length(); i++ ) { if ( array[i].name() == "time1.outTime" ) { /// connected to time, so no time remapping between maya scene and loaded scene. return LinkedScene::linkAttributeData( scene.get() ); } } /// couldn't find connection to maya time, so this node is mapping the time some other way. MTime time; timePlug.getValue( time ); return LinkedScene::linkAttributeData( scene.get(), time.as( MTime::kSeconds ) ); }
GafferScene::ConstPathMatcherDataPtr SceneReader::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const { PathMatcherDataPtr result = new PathMatcherData; ConstSceneInterfacePtr rootScene = scene( ScenePath() ); if( rootScene ) { loadSetWalk( rootScene.get(), setName, result->writable(), ScenePath() ); } return result; }
void SceneReader::hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { FileSource::hashBound( path, context, parent, h ); ConstSceneInterfacePtr s = scene( path ); const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() ); if( !ss || ss->numBoundSamples() > 1 ) { h.append( context->getFrame() ); } }
void SceneReader::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { ConstSceneInterfacePtr s = scene( path ); if( !s || !s->hasObject() ) { // no object h = parent->objectPlug()->defaultValue()->hash(); return; } FileSource::hashObject( path, context, parent, h ); const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() ); if( !ss || ss->numObjectSamples() > 1 ) { h.append( context->getFrame() ); } }
void SceneReader::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } SceneInterface::NameList attributeNames; s->attributeNames( attributeNames ); SceneInterface::NameList tagNames; s->readTags( tagNames, IECore::SceneInterface::LocalTag ); if( !attributeNames.size() && !tagNames.size() ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } FileSource::hashAttributes( path, context, parent, h ); bool animated = false; const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() ); if( !ss ) { animated = true; } else { for( SceneInterface::NameList::iterator it = attributeNames.begin(); it != attributeNames.end(); ++it ) { if( ss->numAttributeSamples( *it ) > 1 ) { animated = true; break; } } } if( animated ) { h.append( context->getFrame() ); } }
IECore::ConstObjectPtr OBJ_SceneCacheTransform::readAttribute( const OP_Node *node, const SceneInterface::Name &name, double time ) { // make sure its a SceneCacheNode if ( !node->hasParm( pFile.getToken() ) || !node->hasParm( pRoot.getToken() ) ) { return 0; } const SceneCacheNode<OP_Node> *sceneNode = reinterpret_cast< const SceneCacheNode<OP_Node>* >( node ); /// \todo: do we need to ensure the file exists first? ConstSceneInterfacePtr scene = OBJ_SceneCacheTransform::scene( sceneNode->getFile(), sceneNode->getPath() ); if ( !scene ) { return 0; } if ( name == LinkedScene::linkAttribute ) { const char *expanded = pExpanded.getToken(); if ( node->hasParm( expanded ) && !node->evalInt( expanded, 0, 0 ) ) { return LinkedScene::linkAttributeData( scene.get(), time ); } return 0; } try { return scene->readAttribute( name, time ); } catch( ... ) { return 0; } }
SceneInterfacePtr LinkedScene::scene( const Path &path, MissingBehaviour missingBehaviour ) { if ( missingBehaviour == SceneInterface::CreateIfMissing ) { throw Exception( "createIfMissing is not supported!" ); } SceneInterfacePtr s = m_mainScene->scene( SceneInterface::rootPath ); Path::const_iterator pIt; /// first try to get as close as possible using the m_mainScene... for ( pIt = path.begin(); pIt != path.end(); pIt++ ) { SceneInterfacePtr n = s->child( *pIt, SceneInterface::NullIfMissing ); if ( !n ) { break; } s = n; } ConstSceneInterfacePtr l = 0; int linkDepth = 0; bool atLink = false; bool timeRemapped = false; if ( s->hasAttribute( fileNameLinkAttribute ) && s->hasAttribute( rootLinkAttribute ) ) { atLink = true; timeRemapped = s->hasAttribute( timeLinkAttribute ); ConstStringDataPtr fileName = runTimeCast< const StringData >( s->readAttribute( fileNameLinkAttribute, 0 ) ); ConstInternedStringVectorDataPtr root = runTimeCast< const InternedStringVectorData >( s->readAttribute( rootLinkAttribute, 0 ) ); l = expandLink( fileName.get(), root.get(), linkDepth ); if (!l) { atLink = false; timeRemapped = false; } } else if( s->hasAttribute( linkAttribute ) ) { atLink = true; ConstCompoundDataPtr d = runTimeCast< const CompoundData >( s->readAttribute( linkAttribute, 0 ) ); l = expandLink( d->member< const StringData >( g_fileName ), d->member< const InternedStringVectorData >( g_root ), linkDepth ); if ( !l ) { atLink = false; } } if ( pIt != path.end() ) { if ( !atLink ) { if ( missingBehaviour == SceneInterface::NullIfMissing ) { return 0; } throw Exception( "Could not find child '" + pIt->value() + "'" ); } for ( ; pIt != path.end(); pIt++ ) { l = l->child( *pIt, missingBehaviour ); if ( !l ) { return 0; } } atLink = false; } return new LinkedScene( s.get(), l.get(), linkDepth, m_readOnly, atLink, timeRemapped ); }
void SOP_SceneCacheSource::loadObjects( const IECore::SceneInterface *scene, Imath::M44d transform, double time, Space space, Parameters ¶ms, size_t rootSize ) { UT_Interrupt *progress = UTgetInterrupt(); progress->setLongOpText( ( "Loading " + scene->name().string() ).c_str() ); if ( progress->opInterrupt() ) { return; } if ( scene->hasObject() && UT_String( scene->name() ).multiMatch( params.shapeFilter ) && tagged( scene, params.tagFilter ) ) { std::string name = relativePath( scene, rootSize ); Imath::M44d currentTransform; if ( space == Local ) { currentTransform = scene->readTransformAsMatrix( time ); } else if ( space != Object ) { currentTransform = transform; } ConstObjectPtr object = 0; if ( params.geometryType == BoundingBox ) { Imath::Box3d bound = scene->readBound( time ); object = MeshPrimitive::createBox( Imath::Box3f( bound.min, bound.max ) ); params.hasAnimatedTopology = false; params.hasAnimatedPrimVars = true; params.animatedPrimVars.clear(); params.animatedPrimVars.push_back( "P" ); } else if ( params.geometryType == PointCloud ) { std::vector<Imath::V3f> point( 1, scene->readBound( time ).center() ); PointsPrimitivePtr points = new PointsPrimitive( new V3fVectorData( point ) ); std::vector<Imath::V3f> basis1( 1, Imath::V3f( currentTransform[0][0], currentTransform[0][1], currentTransform[0][2] ) ); std::vector<Imath::V3f> basis2( 1, Imath::V3f( currentTransform[1][0], currentTransform[1][1], currentTransform[1][2] ) ); std::vector<Imath::V3f> basis3( 1, Imath::V3f( currentTransform[2][0], currentTransform[2][1], currentTransform[2][2] ) ); points->variables["basis1"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis1 ) ); points->variables["basis2"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis2 ) ); points->variables["basis3"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis3 ) ); params.hasAnimatedTopology = false; params.hasAnimatedPrimVars = true; params.animatedPrimVars.clear(); params.animatedPrimVars.push_back( "P" ); params.animatedPrimVars.push_back( "basis1" ); params.animatedPrimVars.push_back( "basis2" ); params.animatedPrimVars.push_back( "basis3" ); object = points; } else { object = scene->readObject( time ); params.hasAnimatedTopology = scene->hasAttribute( SceneCache::animatedObjectTopologyAttribute ); params.hasAnimatedPrimVars = scene->hasAttribute( SceneCache::animatedObjectPrimVarsAttribute ); if ( params.hasAnimatedPrimVars ) { const ConstObjectPtr animatedPrimVarObj = scene->readAttribute( SceneCache::animatedObjectPrimVarsAttribute, 0 ); const InternedStringVectorData *animatedPrimVarData = IECore::runTimeCast<const InternedStringVectorData>( animatedPrimVarObj.get() ); if ( animatedPrimVarData ) { const std::vector<InternedString> &values = animatedPrimVarData->readable(); params.animatedPrimVars.clear(); params.animatedPrimVars.resize( values.size() ); std::copy( values.begin(), values.end(), params.animatedPrimVars.begin() ); } } } // modify the object if necessary object = modifyObject( object.get(), params ); // transform the object unless its an identity if ( currentTransform != Imath::M44d() ) { object = transformObject( object.get(), currentTransform, params ); } // convert the object to Houdini if ( !convertObject( object.get(), name, scene, params ) ) { std::string fullName; SceneInterface::Path path; scene->path( path ); SceneInterface::pathToString( path, fullName ); addWarning( SOP_MESSAGE, ( "Could not convert " + fullName + " to Houdini" ).c_str() ); } } if ( evalInt( pObjectOnly.getToken(), 0, 0 ) ) { return; } SceneInterface::NameList children; scene->childNames( children ); std::sort( children.begin(), children.end(), InternedStringSort() ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); if ( tagged( child.get(), params.tagFilter ) ) { loadObjects( child.get(), child->readTransformAsMatrix( time ) * transform, time, space, params, rootSize ); } } }
OP_ERROR SOP_SceneCacheSource::cookMySop( OP_Context &context ) { // make sure the state is valid if ( boost::indeterminate( m_static ) ) { sceneChanged(); } flags().setTimeDep( bool( !m_static ) ); std::string file; if ( !ensureFile( file ) ) { addError( SOP_ATTRIBUTE_INVALID, ( file + " is not a valid .scc" ).c_str() ); gdp->clearAndDestroy(); return error(); } std::string path = getPath(); Space space = getSpace(); GeometryType geometryType = (GeometryType)this->evalInt( pGeometryType.getToken(), 0, 0 ); UT_String tagFilterStr; getTagFilter( tagFilterStr ); UT_StringMMPattern tagFilter; tagFilter.compile( tagFilterStr ); UT_String shapeFilterStr; getShapeFilter( shapeFilterStr ); UT_StringMMPattern shapeFilter; shapeFilter.compile( shapeFilterStr ); UT_String p( "P" ); UT_String attributeFilter; getAttributeFilter( attributeFilter ); if ( !p.match( attributeFilter ) ) { attributeFilter += " P"; } UT_String attributeCopy; getAttributeCopy( attributeCopy ); UT_String fullPathName; getFullPathName( fullPathName ); ConstSceneInterfacePtr scene = this->scene( file, path ); if ( !scene ) { addError( SOP_ATTRIBUTE_INVALID, ( path + " is not a valid location in " + file ).c_str() ); gdp->clearAndDestroy(); return error(); } MurmurHash hash; hash.append( file ); hash.append( path ); hash.append( space ); hash.append( tagFilterStr ); hash.append( shapeFilterStr ); hash.append( attributeFilter ); hash.append( attributeCopy ); hash.append( fullPathName ); hash.append( geometryType ); hash.append( getObjectOnly() ); if ( !m_loaded || m_hash != hash ) { gdp->clearAndDestroy(); } double readTime = time( context ); Imath::M44d transform = ( space == World ) ? worldTransform( file, path, readTime ) : Imath::M44d(); SceneInterface::Path rootPath; scene->path( rootPath ); UT_Interrupt *progress = UTgetInterrupt(); if ( !progress->opStart( ( "Cooking objects for " + getPath() ).c_str() ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted before it started" ); gdp->clearAndDestroy(); return error(); } Parameters params; UT_String attribFilter; getAttributeFilter( attribFilter ); params.attributeFilter = attribFilter.toStdString(); params.attributeCopy = attributeCopy.toStdString(); params.fullPathName = fullPathName.toStdString(); params.geometryType = getGeometryType(); getShapeFilter( params.shapeFilter ); getTagFilter( params.tagFilter ); // Building a map from shape name to primitive range, which will be used during // convertObject() to do a lazy update of animated primvars where possible, and // to destroy changing topology shapes when necessary. GA_ROAttributeRef nameAttrRef = gdp->findStringTuple( GA_ATTRIB_PRIMITIVE, "name" ); if ( nameAttrRef.isValid() ) { const GA_Attribute *attr = nameAttrRef.getAttribute(); const GA_AIFSharedStringTuple *tuple = attr->getAIFSharedStringTuple(); std::map<std::string, GA_OffsetList> offsets; GA_Range primRange = gdp->getPrimitiveRange(); for ( GA_Iterator it = primRange.begin(); !it.atEnd(); ++it ) { std::string current = ""; if ( const char *value = tuple->getString( attr, it.getOffset() ) ) { current = value; } std::map<std::string, GA_OffsetList>::iterator oIt = offsets.find( current ); if ( oIt == offsets.end() ) { oIt = offsets.insert( std::pair<std::string, GA_OffsetList>( current, GA_OffsetList() ) ).first; } oIt->second.append( it.getOffset() ); } for ( std::map<std::string, GA_OffsetList>::iterator oIt = offsets.begin(); oIt != offsets.end(); ++oIt ) { params.namedRanges[oIt->first] = GA_Range( gdp->getPrimitiveMap(), oIt->second ); } } loadObjects( scene.get(), transform, readTime, space, params, rootPath.size() ); if ( progress->opInterrupt( 100 ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted" ); gdp->clearAndDestroy(); m_loaded = false; m_hash = MurmurHash(); } else { m_loaded = true; m_hash = hash; } progress->opEnd(); return error(); }
void SOP_SceneCacheSource::sceneChanged() { SceneCacheNode<SOP_Node>::sceneChanged(); std::string file; if ( !ensureFile( file ) ) { m_static = boost::indeterminate; return; } m_static = false; ConstSceneInterfacePtr scene = this->scene( file, getPath() ); const SampledSceneInterface *sampledScene = IECore::runTimeCast<const SampledSceneInterface>( scene.get() ); if ( sampledScene ) { bool objectOnly = this->evalInt( pObjectOnly.getToken(), 0, 0 ); m_static = ( objectOnly && sampledScene->hasObject() ) ? ( sampledScene->numObjectSamples() < 2 ) : ( sampledScene->numBoundSamples() < 2 ); } flags().setTimeDep( bool( !m_static ) ); }
void LinkedScene::writeAttribute( const Name &name, const Object *attribute, double time ) { if ( m_readOnly ) { throw Exception( "No write access to scene file!" ); } if ( name == linkAttribute ) { bool firstTime = !m_mainScene->hasAttribute( fileNameLinkAttribute ); if ( firstTime ) { // if it's the first time, we better check if this level already has objects, tags or children // and raise exceptions to prevent weird configurations... if ( m_mainScene->hasObject() ) { throw Exception( "Links to external scenes cannot be created on locations where there's already an object saved!" ); } NameList names; m_mainScene->childNames( names ); if ( names.size() ) { throw Exception( "Links to external scenes cannot be created on locations where there are already child locations!" ); } } // we are creating a link! const CompoundData *d = runTimeCast< const CompoundData >(attribute); if ( !d ) { throw Exception( "SceneInterface:link attribute must be of type CompoundData!" ); } // open the linked scene int linkDepth; ConstDoubleDataPtr timeData = d->member< const DoubleData >( g_time ); const StringData *fileName = d->member< const StringData >( g_fileName ); const InternedStringVectorData *sceneRoot = d->member< const InternedStringVectorData >( g_root ); ConstSceneInterfacePtr linkedScene = expandLink( fileName, sceneRoot, linkDepth ); if ( !linkedScene ) { throw Exception( "Trying to store a broken link!" ); } // get the bounds of the linked scene const SampledSceneInterface *sampledScene = runTimeCast< const SampledSceneInterface >(linkedScene.get()); if ( sampledScene && !timeData ) { // When there's no time remapping we get all the bounding box samples from the linked scene, using the same time. if ( firstTime ) { size_t bounds = sampledScene->numBoundSamples(); for ( size_t b = 0; b < bounds; b++ ) { m_mainScene->writeBound( sampledScene->readBoundAtSample(b), sampledScene->boundSampleTime(b) ); } } } else { /// we store just the current bounding box if ( timeData ) { m_mainScene->writeBound( linkedScene->readBound(timeData->readable()), time ); } else { m_mainScene->writeBound( linkedScene->readBound(time), time ); } } if ( firstTime ) { // save the tags from the linked file to the current location so it gets propagated to the root. NameList tags; // Check if the position of the file we are trying to link to, has ancestor tags. // This situation is undesirable, as it will make LinkedScene return inconsistent ancestor tags before and after the link location. linkedScene->readTags(tags, SceneInterface::AncestorTag ); if ( tags.size() ) { std::string pathStr; SceneInterface::pathToString( sceneRoot->readable(), pathStr ); msg( Msg::Warning, "LinkedScene::writeAttribute", ( boost::format( "Detected ancestor tags while creating link to file %s at location %s." ) % fileName->readable() % pathStr ).str() ); } tags.clear(); /// copy all descendent and local tags as descendent tags (so we can distinguish from tags added in the LinkedScene) linkedScene->readTags(tags, SceneInterface::LocalTag|SceneInterface::DescendantTag ); static_cast< SceneCache *>(m_mainScene.get())->writeTags(tags, true); m_mainScene->writeAttribute( fileNameLinkAttribute, d->member< const StringData >( g_fileName ), time ); m_mainScene->writeAttribute( rootLinkAttribute, d->member< const InternedStringVectorData >( g_root ), time ); } /// we keep the information this level has a link, so we can prevent attempts to /// create children or save objects at this level. m_atLink = true; if( timeData ) { m_mainScene->writeAttribute( timeLinkAttribute, timeData, time ); } return; } m_mainScene->writeAttribute(name,attribute,time); }
void OBJ_SceneCacheTransform::doExpandChildren( const SceneInterface *scene, OP_Network *parent, const Parameters ¶ms ) { UT_Interrupt *progress = UTgetInterrupt(); progress->setLongOpText( ( "Expanding " + scene->name().string() ).c_str() ); if ( progress->opInterrupt() ) { return; } OP_Network *inputNode = parent; if ( params.hierarchy == Parenting ) { parent = parent->getParent(); } SceneInterface::NameList children; scene->childNames( children ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); OBJ_Node *childNode = 0; if ( params.hierarchy == SubNetworks ) { childNode = doExpandChild( child.get(), parent, params ); if ( params.depth == AllDescendants && child->hasObject() && tagged( child.get(), params.tagFilter ) ) { Parameters childParams( params ); childParams.depth = Children; doExpandObject( child.get(), childNode, childParams ); } } else if ( params.hierarchy == Parenting ) { if ( child->hasObject() ) { Parameters childParams( params ); childParams.depth = Children; childNode = doExpandObject( child.get(), parent, childParams ); } else { childNode = doExpandChild( child.get(), parent, params ); } childNode->setInput( 0, inputNode ); } if ( params.depth == AllDescendants ) { if ( params.hierarchy == SubNetworks && !tagged( child.get(), params.tagFilter ) ) { // we don't expand non-tagged children for SubNetwork mode, but we // do for Parenting mode, because otherwise the hierarchy would be // stuck in an un-expandable state. continue; } doExpandChildren( child.get(), childNode, params ); childNode->setInt( pExpanded.getToken(), 0, 0, 1 ); } } OP_Layout layout( parent ); #if UT_MAJOR_VERSION_INT >= 16 OP_SubnetIndirectInput *parentInput = parent->getParentInput( 0 ); layout.addLayoutItem( parentInput->getInputItem() ); for ( int i=0; i < parent->getNchildren(); ++i ) { layout.addLayoutItem( parent->getChild( i ) ); } #else layout.addLayoutOp( parent->getParentInput( 0 ) ); for ( int i=0; i < parent->getNchildren(); ++i ) { layout.addLayoutOp( parent->getChild( i ) ); } #endif layout.layoutOps( OP_LAYOUT_TOP_TO_BOT, parent, parent->getParentInput( 0 ) ); }
static void loadSetsWalk( const SceneInterface *s, const vector<InternedString> &tags, const vector<PathMatcher *> &sets, const vector<InternedString> &path ) { // For each tag we wish to load, we need to determine if it exists at the current // location. The natural way to do this would be to call s->hasTag( tag ), but that // actually has pretty poor performance when calling hasTag() for many tags. So // we load all the local tags with readTags(), and then for each of them test to see // if they exist in the list of tags we wish to load. We test the local tags against // the tags because we're in control of the tags and can sort them beforehand for faster // searching, whereas the localTags just come as-is. Using binary search over linear // search isn't actually that big a win for a typical number of tags, simply because // InternedString equality tests are so quick, but there's a very slight benefit, which // should be more apparent should anyone create a very large number of tags at some point. vector<InternedString> sceneTags; s->readTags( sceneTags, SceneInterface::LocalTag ); for( vector<InternedString>::const_iterator it = sceneTags.begin(), eIt = sceneTags.end(); it != eIt; ++it ) { vector<InternedString>::const_iterator t = lower_bound( tags.begin(), tags.end(), *it ); if( t != tags.end() && *t == *it ) { /// \todo addPath() is doing a search to find the right node to insert at. /// If nodes were exposed by the PathMatcher, we could provide the right /// node to insert at by tracking it as we recurse the hierarchy. sets[t - tags.begin()]->addPath( path ); } } // Figure out if we need to recurse by querying descendant tags to see if they include // anything we're interested in. sceneTags.clear(); s->readTags( sceneTags, SceneInterface::DescendantTag ); bool recurse = false; for( vector<InternedString>::const_iterator it = sceneTags.begin(), eIt = sceneTags.end(); it != eIt; ++it ) { vector<InternedString>::const_iterator t = lower_bound( tags.begin(), tags.end(), *it ); if( t != tags.end() && *t == *it ) { recurse = true; break; } } if( !recurse ) { return; } // Recurse to the children. SceneInterface::NameList childNames; s->childNames( childNames ); vector<InternedString> childPath( path ); childPath.push_back( InternedString() ); // room for the child name for( SceneInterface::NameList::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { ConstSceneInterfacePtr child = s->child( *it ); childPath[path.size()] = *it; loadSetsWalk( child.get(), tags, sets, childPath ); } }
SceneInterfacePtr LinkedScene::child( const Name &name, MissingBehaviour missingBehaviour ) { if ( missingBehaviour == SceneInterface::CreateIfMissing ) { if ( m_readOnly ) { throw Exception( "No write access to scene file!" ); } if ( m_atLink ) { throw Exception( "Locations with links to external scene cannot have child locations themselves!" ); } } if ( m_linkedScene ) { ConstSceneInterfacePtr c = m_linkedScene->child( name, missingBehaviour ); if ( !c ) { return 0; } return new LinkedScene( m_mainScene.get(), c.get(), m_rootLinkDepth, m_readOnly, false, m_timeRemapped ); } else { SceneInterfacePtr c = m_mainScene->child( name, missingBehaviour ); if ( !c ) { return 0; } if ( m_readOnly ) { if( c->hasAttribute( fileNameLinkAttribute ) && c->hasAttribute( rootLinkAttribute ) ) { ConstStringDataPtr fileName = runTimeCast< const StringData >( c->readAttribute( fileNameLinkAttribute, 0 ) ); ConstInternedStringVectorDataPtr root = runTimeCast< const InternedStringVectorData >( c->readAttribute( rootLinkAttribute, 0 ) ); /// we found the link attribute... int linkDepth; bool timeRemapped = c->hasAttribute( timeLinkAttribute ); ConstSceneInterfacePtr l = expandLink( fileName.get(), root.get(), linkDepth ); if ( l ) { return new LinkedScene( c.get(), l.get(), linkDepth, m_readOnly, true, timeRemapped ); } } else if( c->hasAttribute( linkAttribute ) ) { // read from old school link attribute. // \todo: remove this when it doesn't break everyone's stuff! ConstCompoundDataPtr d = runTimeCast< const CompoundData >( c->readAttribute( linkAttribute, 0 ) ); /// we found the link attribute... int linkDepth; bool timeRemapped = false; ConstSceneInterfacePtr l = expandLink( d->member< const StringData >( g_fileName ), d->member< const InternedStringVectorData >( g_root ), linkDepth ); if ( l ) { return new LinkedScene( c.get(), l.get(), linkDepth, m_readOnly, true, timeRemapped ); } } } return new LinkedScene( c.get(), 0, 0, m_readOnly, false, false ); } }