Exemple #1
0
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 );
}
Exemple #3
0
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;
}
Exemple #4
0
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);
}
Exemple #5
0
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 ) );
}
Exemple #6
0
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;
}
Exemple #7
0
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() );
	}
}
Exemple #8
0
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() );
	}
}
Exemple #9
0
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;
	}
}
Exemple #11
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 &params, 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 ) );
}
Exemple #15
0
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 &params )
{
	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 ) );
}
Exemple #17
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 );
	}
}
Exemple #18
0
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 );
	}
}