예제 #1
0
파일: Plug.cpp 프로젝트: TRiGGER80/gaffer
void Plug::setInput( PlugPtr input )
{
    if( input.get()==m_input )
    {
        return;
    }
    if( input && !acceptsInput( input ) )
    {
        std::string what = boost::str(
                               boost::format( "Plug \"%s\" rejects input \"%s\"." )
                               % fullName()
                               % input->fullName()
                           );
        throw IECore::Exception( what );
    }
    if( refCount() )
    {
        // someone is referring to us, so we're definitely fully constructed and we may have a ScriptNode
        // above us, so we should do things in a way compatible with the undo system.
        Action::enact(
            this,
            boost::bind( &Plug::setInputInternal, PlugPtr( this ), input, true ),
            boost::bind( &Plug::setInputInternal, PlugPtr( this ), PlugPtr( m_input ), true )
        );
    }
    else
    {
        // noone is referring to us. we're probably still constructing, and undo is impossible anyway (we
        // have no ScriptNode ancestor), so we can't make a smart pointer
        // to ourselves (it will result in double destruction). so we just set the input directly.
        setInputInternal( input, false );
    }
}
예제 #2
0
ArrayPlug::ArrayPlug( const std::string &name, Direction direction, PlugPtr element, size_t minSize, size_t maxSize, unsigned flags )
	:	Plug( name, direction, flags ), m_minSize( std::max( minSize, size_t( 1 ) ) ), m_maxSize( std::max( maxSize, m_minSize ) )
{
	if( direction == Plug::Out )
	{
		throw IECore::Exception( "Output ArrayPlugs are currently unsupported." );
	}

	if( element )
	{
		// If we're dynamic ourselves, then serialisations will include a constructor
		// for us, but it will have element==None. In this case we make sure the first
		// element is dynamic, so that it too will have a constructor written out. But
		// if we're not dynamic, we expect to be passed the element again upon reconstruction,
		// so we don't need a constructor to be serialised for the element, and therefore
		// we must set it to be non-dynamic.
		element->setFlags( Gaffer::Plug::Dynamic, getFlags( Gaffer::Plug::Dynamic ) );
		addChild( element );

		for( size_t i = 1; i < m_minSize; ++i )
		{
			PlugPtr p = element->createCounterpart( element->getName(), Plug::In );
			addChild( p );
		}
	}

	parentChangedSignal().connect( boost::bind( &ArrayPlug::parentChanged, this ) );
}
예제 #3
0
void Expression::updatePlug( ValuePlug *parentPlug, size_t childIndex, ValuePlug *plug )
{
	if( parentPlug->children().size() > childIndex )
	{
		// See if we can reuse the existing plug
		Plug *existingChildPlug = parentPlug->getChild<Plug>( childIndex );
		if(
			( existingChildPlug->direction() == Plug::In && existingChildPlug->getInput<Plug>() == plug ) ||
			( existingChildPlug->direction() == Plug::Out && plug->getInput<Plug>() == existingChildPlug )
		)
		{
			return;
		}
	}

	// Existing plug not OK, so we need to create one. First we must remove all
	// plugs from childIndex onwards, so that when we add the new plug it gets
	// the right index.
	removeChildren( parentPlug, childIndex );

	// Finally we can add the plug we need.

	PlugPtr childPlug = plug->createCounterpart( "p0", parentPlug->direction() );
	childPlug->setFlags( Plug::Dynamic, true );
	parentPlug->addChild( childPlug );
	if( childPlug->direction() == Plug::In )
	{
		childPlug->setInput( plug );
	}
	else
	{
		plug->setInput( childPlug );
	}
}
예제 #4
0
void Expression::addPlug( ValuePlug *parentPlug, const std::string &plugPath )
{
	Node *p = parent<Node>();
	if( !p )
	{
		throw IECore::Exception( "No parent" );
	}

	ValuePlug *plug = p->descendant<ValuePlug>( plugPath );
	if( !plug )
	{
		throw IECore::Exception( boost::str( boost::format( "Plug \"%s\" does not exist" ) % plugPath ) );
	}

	PlugPtr childPlug = plug->createCounterpart( "p0", parentPlug->direction() );
	childPlug->setFlags( Plug::Dynamic, true );
	parentPlug->addChild( childPlug );
	if( childPlug->direction() == Plug::In )
	{
		childPlug->setInput( plug );
	}
	else
	{
		plug->setInput( childPlug );
	}
}
예제 #5
0
void ArrayPlug::inputChanged( Gaffer::Plug *plug )
{
	if( plug->parent<ArrayPlug>() != this )
	{
		return;
	}

	if( getInput() )
	{
		// When we ourselves have an input, we don't do any automatic addition or
		// removal of children, because the Plug base class itself manages
		// children to maintain the connection.
		return;
	}

	if( const ScriptNode *script = ancestor<ScriptNode>() )
	{
		if( script->currentActionStage() == Action::Undo ||
		    script->currentActionStage() == Action::Redo
		)
		{
			// If we're currently in an undo or redo, we don't
			// need to do anything, because our previous actions
			// will be in the undo queue and will be being replayed
			// for us automatically.
			return;
		}
	}

	if( plug->getInput() )
	{
		// Connection made. If it's the last plug
		// then we need to add one more.
		if( plug == children().back() && children().size() < m_maxSize )
		{
			PlugPtr p = getChild<Plug>( 0 )->createCounterpart( getChild<Plug>( 0 )->getName(), Plug::In );
			p->setFlags( Gaffer::Plug::Dynamic, true );
			addChild( p );
			MetadataAlgo::copyColors( getChild<Plug>( 0 ) , p.get() , /* overwrite = */ false );
		}
	}
	else
	{
		// Connection broken. We need to remove any
		// unneeded unconnected plugs so that we have
		// only one unconnected plug at the end.
		for( size_t i = children().size() - 1; i > m_minSize - 1; --i )
		{
			if( !getChild<Plug>( i )->getInput() && !getChild<Plug>( i - 1 )->getInput() )
			{
				removeChild( getChild<Plug>( i ) );
			}
			else
			{
				break;
			}
		}
	}
}
예제 #6
0
PlugPtr CompoundDataPlug::MemberPlug::createCounterpart( const std::string &name, Direction direction ) const
{
	PlugPtr result = new MemberPlug( name, direction, getFlags() );
	for( PlugIterator it( this ); it != it.end(); it++ )
	{
		result->addChild( (*it)->createCounterpart( (*it)->getName(), direction ) );
	}
	return result;
}
예제 #7
0
PlugPtr ValuePlug::createCounterpart( const std::string &name, Direction direction ) const
{
	PlugPtr result = new ValuePlug( name, direction, getFlags() );
	for( PlugIterator it( this ); !it.done(); ++it )
	{
		result->addChild( (*it)->createCounterpart( (*it)->getName(), direction ) );
	}
	return result;
}
예제 #8
0
파일: Box.cpp 프로젝트: Eryckz/gaffer
Plug *Box::promotePlug( Plug *descendantPlug )
{
	validatePromotability( descendantPlug, /* throwExceptions = */ true );

	PlugPtr externalPlug = descendantPlug->createCounterpart( promotedCounterpartName( descendantPlug ), descendantPlug->direction() );
	externalPlug->setFlags( Plug::Dynamic, true );
	// Flags are not automatically propagated to the children of compound plugs,
	// so we need to do that ourselves. We don't want to propagate them to the
	// children of plug types which create the children themselves during
	// construction though, hence the typeId checks for the base classes
	// which add no children during construction. I'm not sure this approach is
	// necessarily the best - the alternative would be to set everything dynamic
	// unconditionally and then implement Serialiser::childNeedsConstruction()
	// for types like CompoundNumericPlug that create children in their constructors.
	const Gaffer::TypeId compoundTypes[] = { PlugTypeId, ValuePlugTypeId, CompoundPlugTypeId, ArrayPlugTypeId };
	const Gaffer::TypeId *compoundTypesEnd = compoundTypes + 4;
	if( find( compoundTypes, compoundTypesEnd, (Gaffer::TypeId)externalPlug->typeId() ) != compoundTypesEnd )
	{
		for( RecursivePlugIterator it( externalPlug.get() ); it != it.end(); ++it )
		{
			(*it)->setFlags( Plug::Dynamic, true );
			if( find( compoundTypes, compoundTypesEnd, (Gaffer::TypeId)(*it)->typeId() ) != compoundTypesEnd )
			{
				it.prune();
			}
		}
	}

	if( externalPlug->direction() == Plug::In )
	{
		if( ValuePlug *externalValuePlug = IECore::runTimeCast<ValuePlug>( externalPlug.get() ) )
		{
			externalValuePlug->setFrom( static_cast<ValuePlug *>( descendantPlug ) );
		}
	}

	// Copy over the metadata for nodule position, so the nodule appears in the expected spot.
	// This must be done before parenting the new plug, as the nodule is created from childAddedSignal().
	copyMetadata( descendantPlug, externalPlug.get() );

	addChild( externalPlug );

	if( externalPlug->direction() == Plug::In )
	{
		descendantPlug->setInput( externalPlug );
	}
	else
	{
		externalPlug->setInput( descendantPlug );
	}

	return externalPlug.get();
}
예제 #9
0
ExecutableNode::ExecutableNode( const std::string &name )
	:	Node( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new ArrayPlug( "requirements", Plug::In, new RequirementPlug( "requirement0" ) ) );
	addChild( new RequirementPlug( "requirement", Plug::Out ) );

	PlugPtr dispatcherPlug = new Plug( "dispatcher", Plug::In );
	addChild( dispatcherPlug );

	Dispatcher::setupPlugs( dispatcherPlug.get() );
}
예제 #10
0
TaskNode::TaskNode( const std::string &name )
	:	DependencyNode( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new ArrayPlug( "preTasks", Plug::In, new TaskPlug( "preTask0" ) ) );
	addChild( new ArrayPlug( "postTasks", Plug::In, new TaskPlug( "postTask0" ) ) );
	addChild( new TaskPlug( "task", Plug::Out ) );

	PlugPtr dispatcherPlug = new Plug( "dispatcher", Plug::In );
	addChild( dispatcherPlug );

	Dispatcher::setupPlugs( dispatcherPlug.get() );
}
예제 #11
0
void CompoundPlug::setInput( PlugPtr input )
{
	if( input.get() == getInput<Plug>() )
	{
		return;
	}
	
	// unfortunately we have to duplicate the check in Plug::setInput()
	// ourselves as we delay calling Plug::setInput() until we've connected
	// the children, but need to do the check first.
	/// \todo I think there's a case for not having CompoundPlug at all,
	/// and having Plug have all its functionality.
	if( input && !acceptsInput( input ) )
	{
		std::string what = boost::str(
			boost::format( "Plug \"%s\" rejects input \"%s\"." )
			% fullName()
			% input->fullName()
		);
		throw IECore::Exception( what );
	}
	
	{
		// we use the plugInputChangedConnection to trigger calls to updateInputFromChildInputs()
		// when child inputs are changed by code elsewhere. it would be counterproductive for
		// us to call updateInputFromChildInputs() while we ourselves are changing those inputs,
		// so we temporarily block the connection.
		BlockedConnection block( m_plugInputChangedConnection );
	
		if( !input )
		{
			for( ChildContainer::const_iterator it = children().begin(); it!=children().end(); it++ )
			{
				IECore::staticPointerCast<Plug>( *it )->setInput( 0 );			
			}
		}
		else
		{
			CompoundPlugPtr p = IECore::staticPointerCast<CompoundPlug>( input );
			ChildContainer::const_iterator it1, it2;
			for( it1 = children().begin(), it2 = p->children().begin(); it1!=children().end(); it1++, it2++ )
			{
				IECore::staticPointerCast<Plug>( *it1 )->setInput( IECore::staticPointerCast<Plug>( *it2 ) );
			}
		}
	}
	
	// we connect ourselves last, so that all our child plugs are correctly connected
	// before we signal our own connection change.
	ValuePlug::setInput( input );
}
예제 #12
0
static void loadCoshaderParameter( Gaffer::CompoundPlug *parametersPlug, const std::string &name )
{
	Plug *existingPlug = parametersPlug->getChild<Plug>( name );
	if( existingPlug && existingPlug->typeId() == Plug::staticTypeId() )
	{
		return;
	}
	
	PlugPtr plug = new Plug( name, Plug::In, Plug::Default | Plug::Dynamic );
	if( existingPlug && existingPlug->getInput<Plug>() )
	{
		plug->setInput( existingPlug->getInput<Plug>() );
	}
	
	parametersPlug->setChild( name, plug );
}
예제 #13
0
void Expression::updatePlugs( const std::string &dstPlugPath, std::vector<std::string> &srcPlugPaths )
{
	Node *p = parent<Node>();

	// if the expression was invalid, remove our plugs
	if( !dstPlugPath.size() )
	{
		Plug *in = getChild<Plug>( "in" );
		if( in )
		{
			removeChild( in );
		}
		Plug *out = getChild<Plug>( "out" );
		if( out )
		{
			removeChild( out );
		}
		return;
	}

	// otherwise try to create connections to the plugs the expression wants

	ValuePlug *dstPlug = p->descendant<ValuePlug>( dstPlugPath );
	if( !dstPlug )
	{
		throw IECore::Exception( boost::str( boost::format( "Destination plug \"%s\" does not exist" ) % dstPlugPath ) );
	}

	CompoundPlugPtr inPlugs = new CompoundPlug( "in", Plug::In, Plug::Default | Plug::Dynamic );
	setChild( "in", inPlugs );
	for( std::vector<std::string>::const_iterator it = srcPlugPaths.begin(); it!=srcPlugPaths.end(); it++ )
	{
		ValuePlug *srcPlug = p->descendant<ValuePlug>( *it );
		if( !srcPlug )
		{
			throw IECore::Exception( boost::str( boost::format( "Source plug \"%s\" does not exist" ) % *it ) );
		}
		PlugPtr inPlug = srcPlug->createCounterpart( "plug", Plug::In );
		inPlugs->addChild( inPlug );
		inPlug->setInput( srcPlug );
	}

	PlugPtr outPlug = dstPlug->createCounterpart( "out", Plug::Out );
	setChild( "out", outPlug );
	dstPlug->setInput( outPlug );
}
예제 #14
0
static Plug *loadClosureParameter( const OSLQuery::Parameter *parameter, Gaffer::CompoundPlug *parent )
{	
	const string name = plugName( parameter );
	Plug *existingPlug = parent->getChild<Plug>( name );
	if(	existingPlug && existingPlug->typeId() == Plug::staticTypeId() )
	{
		return existingPlug;
	}
	
	PlugPtr plug = new Plug( name, parent->direction(), Plug::Default | Plug::Dynamic );
	
	transferConnectionOrValue( existingPlug, plug.get() );
	
	parent->setChild( name, plug );
	
	return plug;
}
예제 #15
0
		void addError( PlugPtr plug, const std::string &error )
		{
			PlugEntry &entry = m_errors[plug];
			entry.error = error;
			if( !entry.parentChangedConnection.connected() )
			{
				entry.parentChangedConnection = plug->parentChangedSignal().connect( boost::bind( &ErrorGadget::parentChanged, this, ::_1 ) );
			}
			m_image->setVisible( true );
		}
예제 #16
0
void ImageView::insertConverter( Gaffer::NodePtr converter )
{
	PlugPtr converterInput = converter->getChild<Plug>( "in" );
	if( !converterInput )
	{
		throw IECore::Exception( "Converter has no Plug named \"in\"" );
	}
	ImagePlugPtr converterOutput = converter->getChild<ImagePlug>( "out" );
	if( !converterOutput )
	{
		throw IECore::Exception( "Converter has no ImagePlug named \"out\"" );
	}

	PlugPtr newInput = converterInput->createCounterpart( "in", Plug::In );
	setChild( "in", newInput );

	NodePtr preprocessor = getPreprocessor<Node>();
	Plug::OutputContainer outputsToRestore = preprocessor->getChild<ImagePlug>( "in" )->outputs();

	PlugPtr newPreprocessorInput = converterInput->createCounterpart( "in", Plug::In );
	preprocessor->setChild( "in", newPreprocessorInput );
	newPreprocessorInput->setInput( newInput );

	preprocessor->setChild( "__converter", converter );
	converterInput->setInput( newPreprocessorInput );

	for( Plug::OutputContainer::const_iterator it = outputsToRestore.begin(), eIt = outputsToRestore.end(); it != eIt; ++it )
	{
		(*it)->setInput( converterOutput );
	}
}
예제 #17
0
static void loadCoshaderArrayParameter( Gaffer::CompoundPlug *parametersPlug, const std::string &name, const StringVectorData *defaultValue )
{
	const size_t minSize = std::max( defaultValue->readable().size(), (size_t)1 );
	const size_t maxSize = defaultValue->readable().size() ? defaultValue->readable().size() : Imath::limits<size_t>::max();
	
	PlugPtr existingPlug = parametersPlug->getChild<Plug>( name );
	ArrayPlug *existingArrayPlug = runTimeCast<ArrayPlug>( existingPlug );
	if( existingArrayPlug && existingArrayPlug->minSize() == minSize && existingArrayPlug->maxSize() == maxSize )
	{
		return;
	}

	std::string elementName = name;
	if( isdigit( *elementName.rbegin() ) )
	{
		elementName += "_0";
	}
	else
	{
		elementName += "0";		
	}
	
	ArrayPlugPtr plug = new ArrayPlug( name, Plug::In, new Plug( elementName ), minSize, maxSize, Plug::Default | Plug::Dynamic );
	parametersPlug->setChild( name, plug );
	
	if( existingPlug )
	{
		for( size_t i = 0, e = std::min( existingPlug->children().size(), maxSize ); i < e; ++i )
		{
			if( i < plug->children().size() )
			{
				plug->getChild<Plug>( i )->setInput( existingPlug->getChild<Plug>( i )->getInput<Plug>() );
			}
			else
			{
				plug->addChild( existingPlug->getChild<Plug>( i ) );
			}
		}
	}
}
예제 #18
0
		ColorInspector( ImageView *view )
			:	m_view( view ),
				m_sampler( new ImageSampler )
		{
			PlugPtr plug = new Plug( "colorInspector" );
			view->addChild( plug );

			plug->addChild( new V2iPlug( "pixel" ) );
			plug->addChild( new Color4fPlug( "color" ) );

			// We want to sample the image before the display transforms
			// are applied. We can't simply get this image from inPlug()
			// because derived classes may have called insertConverter(),
			// so we take it from the input to the display transform chain.
			ImagePlug *image = view->getPreprocessor<Node>()->getChild<Clamp>( "__clamp" )->inPlug();
			m_sampler->imagePlug()->setInput( image );

			plug->getChild<Color4fPlug>( "color" )->setInput( m_sampler->colorPlug() );

			m_view->viewportGadget()->mouseMoveSignal().connect( boost::bind( &ColorInspector::mouseMove, this, ::_2 ) );
			m_view->viewportGadget()->getPrimaryChild()->buttonPressSignal().connect( boost::bind( &ColorInspector::buttonPress, this,  ::_2 ) );
			m_view->viewportGadget()->getPrimaryChild()->dragBeginSignal().connect( boost::bind( &ColorInspector::dragBegin, this, ::_2 ) );
			m_view->viewportGadget()->getPrimaryChild()->dragEndSignal().connect( boost::bind( &ColorInspector::dragEnd, this, ::_2 ) );
		}
예제 #19
0
		void addError( PlugPtr plug, const std::string &error )
		{
			PlugEntry &entry = m_errors[plug];
			if( entry.error.empty() || !boost::ends_with( error, "Previous attempt to get item failed." ) )
			{
				// Update the error message. Unfortunately the IECore::LRUCache at the
				// heart of Gaffer's caching  does not remember the details of exceptions that
				// occurred when the cache entry is in error - instead it throws a different
				// exception saying "Previous attempt to get item failed.". We ignore these less
				// helpful messages in favour of a previous messages if one exists.
				/// \todo Improve LRUCache behaviour and remove this workaround.
				entry.error = error;
			}
			if( !entry.parentChangedConnection.connected() )
			{
				entry.parentChangedConnection = plug->parentChangedSignal().connect( boost::bind( &ErrorGadget::parentChanged, this, ::_1 ) );
			}
			m_image->setVisible( true );
		}
예제 #20
0
void Plug::setInputInternal( PlugPtr input, bool emit )
{
	if( m_input )
	{
		m_input->m_outputs.remove( this );
	}
	m_input = input.get();
	if( m_input )
	{
		m_input->m_outputs.push_back( this );
	}
	if( emit )
	{
		// We must emit inputChanged prior to propagating
		// dirtiness, because inputChanged slots may be
		// used to rewire the graph, and we want to emit
		// plugDirtied only after all the rewiring is done.
		emitInputChanged();
		propagateDirtiness( this );
	}
}
예제 #21
0
void ValuePlug::setInput( PlugPtr input )
{
	if( input.get() == getInput<Plug>() )
	{
		return;
	}

	// set value back to what it was before
	// we received a connection. we do that
	// before calling Plug::setInput, so that
	// we've got our new state set correctly before
	// the dirty signal is emitted. we don't emit
	// in the setValueInternal call, because we don't
	// want to double up on the signals that the Plug
	// is emitting for us in Plug::setInput().
	if( !input )
	{
		setValueInternal( m_staticValue, false );
	}

	Plug::setInput( input );
}
예제 #22
0
파일: Plug.cpp 프로젝트: TRiGGER80/gaffer
void Plug::setInputInternal( PlugPtr input, bool emit )
{
    if( m_input )
    {
        m_input->m_outputs.remove( this );
    }
    m_input = input.get();
    if( m_input )
    {
        m_input->m_outputs.push_back( this );
    }
    if( emit )
    {
        Node *n = node();
        if( n )
        {
            n->plugInputChangedSignal()( this );
        }
        emitDirtiness();
        propagateDirtiness();
    }
}
예제 #23
0
void Plug::setInput( PlugPtr input, bool setChildInputs, bool updateParentInput )
{
	if( input.get()==m_input )
	{
		return;
	}

	if( input && !acceptsInput( input.get() ) )
	{
		std::string what = boost::str(
			boost::format( "Plug \"%s\" rejects input \"%s\"." )
			% fullName()
			% input->fullName()
		);
		throw IECore::Exception( what );
	}

	// Connect our children first.
	// We use a dirty propagation scope to defer dirty signalling
	// until all connections have been made, when we're in our final
	// state.
	DirtyPropagationScope dirtyPropagationScope;

	if( setChildInputs )
	{
		if( !input )
		{
			for( PlugIterator it( this ); !it.done(); ++it )
			{
				(*it)->setInput( NULL, /* setChildInputs = */ true, /* updateParentInput = */ false );
			}
		}
		else
		{
			for( PlugIterator it1( this ), it2( input.get() ); !it1.done(); ++it1, ++it2 )
			{
				(*it1)->setInput( *it2, /* setChildInputs = */ true, /* updateParentInput = */ false );
			}
		}
	}

	// then connect ourselves

	if( refCount() )
	{
		// someone is referring to us, so we're definitely fully constructed and we may have a ScriptNode
		// above us, so we should do things in a way compatible with the undo system.
		Action::enact(
			this,
			boost::bind( &Plug::setInputInternal, PlugPtr( this ), input, true ),
			boost::bind( &Plug::setInputInternal, PlugPtr( this ), PlugPtr( m_input ), true )
		);
	}
	else
	{
		// noone is referring to us. we're probably still constructing, and undo is impossible anyway (we
		// have no ScriptNode ancestor), so we can't make a smart pointer
		// to ourselves (it will result in double destruction). so we just set the input directly.
		setInputInternal( input, false );
	}

	// finally, adjust our parent's connection to take account of
	// the changes to its child.

	if( updateParentInput )
	{
		if( Plug *parentPlug = parent<Plug>() )
		{
			parentPlug->updateInputFromChildInputs( this );
		}
	}

}
예제 #24
0
ArnoldMeshLight::ArnoldMeshLight( const std::string &name )
	:	GafferScene::FilteredSceneProcessor( name, IECore::PathMatcher::NoMatch )
{

	// ArnoldAttributesNode. This hides the objects from the majority
	// of ray types, since we don't want to add the poor sampling of the
	// object on top of the nice sampling of the light. The only visibility
	// option we don't turn off is camera visibility - instead we promote
	// so the user can decide whether or not the mesh should be visible in
	// the render.

	ArnoldAttributesPtr attributes = new ArnoldAttributes( "__attributes" );
	attributes->inPlug()->setInput( inPlug() );
	attributes->filterPlug()->setInput( filterPlug() );
	for( CompoundDataPlug::MemberPlugIterator it( attributes->attributesPlug() ); !it.done(); ++it )
	{
		if( boost::ends_with( (*it)->getName().string(), "Visibility" ) && (*it)->getName() != "cameraVisibility" )
		{
			(*it)->enabledPlug()->setValue( true );
			(*it)->valuePlug<BoolPlug>()->setValue( false );
		}
	}

	addChild( attributes );

	Plug *internalCameraVisibilityPlug = attributes->attributesPlug()->getChild<Plug>( "cameraVisibility" );
	PlugPtr cameraVisibilityPlug = internalCameraVisibilityPlug->createCounterpart( "cameraVisibility", Plug::In );
	addChild( cameraVisibilityPlug );
	internalCameraVisibilityPlug->setInput( cameraVisibilityPlug );

	// Shader node. This loads the Arnold mesh_light shader.

	ArnoldShaderPtr shader = new ArnoldShader( "__shader" );
	shader->loadShader( "mesh_light" );
	addChild( shader );

	PlugPtr parametersPlug = shader->parametersPlug()->createCounterpart( "parameters", Plug::In );
	addChild( parametersPlug );
	for( PlugIterator srcIt( parametersPlug.get() ), dstIt( shader->parametersPlug() ); !srcIt.done(); ++srcIt, ++dstIt )
	{
		(*dstIt)->setInput( *srcIt );
		// We don't need the parameters to be dynamic, because we create the
		// plugs in our constructor when calling `loadShader()`.
		(*srcIt)->setFlags( Plug::Dynamic, false );
	}

	// ShaderAssignment node. This assigns the mesh_light shader
	// to the objects chosen by the filter.

	ShaderAssignmentPtr shaderAssignment = new ShaderAssignment( "__shaderAssignment" );
	shaderAssignment->inPlug()->setInput( attributes->outPlug() );
	shaderAssignment->filterPlug()->setInput( filterPlug() );
	shaderAssignment->shaderPlug()->setInput( shader->outPlug() );
	addChild( shaderAssignment );

	// Set node. This adds the objects into the __lights set,
	// so they will be output correctly to the renderer.

	SetPtr set = new Set( "__set" );
	set->inPlug()->setInput( shaderAssignment->outPlug() );
	set->filterPlug()->setInput( filterPlug() );
	set->namePlug()->setValue( "__lights" );
	set->modePlug()->setValue( Set::Add );
	addChild( set );

	// Default lights Set node.

	BoolPlugPtr defaultLightPlug = new BoolPlug( "defaultLight", Plug::In, true );
	addChild( defaultLightPlug );

	SetPtr defaultLightsSet = new Set( "__defaultLightsSet" );
	defaultLightsSet->inPlug()->setInput( set->outPlug() );
	defaultLightsSet->filterPlug()->setInput( filterPlug() );
	defaultLightsSet->enabledPlug()->setInput( defaultLightPlug.get() );
	defaultLightsSet->namePlug()->setValue( "defaultLights" );
	defaultLightsSet->modePlug()->setValue( Set::Add );
	addChild( defaultLightsSet );

	// Switch for enabling/disabling

	SwitchPtr enabledSwitch = new Switch( "__switch" );
	enabledSwitch->setup( inPlug() );
	enabledSwitch->inPlugs()->getChild<ScenePlug>( 0 )->setInput( inPlug() );
	enabledSwitch->inPlugs()->getChild<ScenePlug>( 1 )->setInput( defaultLightsSet->outPlug() );
	enabledSwitch->indexPlug()->setValue( 1 );
	enabledSwitch->enabledPlug()->setInput( enabledPlug() );
	addChild( enabledSwitch );

	outPlug()->setInput( enabledSwitch->outPlug() );
	// We don't need to serialise the connection because we make
	// it upon construction.
	/// \todo Can we just do this in the SceneProcessor base class?
	outPlug()->setFlags( Plug::Serialisable, false );
}
예제 #25
0
void OSLShader::loadShader( const std::string &shaderName, bool keepExistingValues )
{
	Plug *existingOut = outPlug();
	if( shaderName.empty() )
	{
		parametersPlug()->clearChildren();
		namePlug()->setValue( "" );
		typePlug()->setValue( "" );
		if( existingOut )
		{
			existingOut->clearChildren();
		}
		return;
	}

	const char *searchPath = getenv( "OSL_SHADER_PATHS" );

	OSLQuery query;
	if( !query.open( shaderName, searchPath ? searchPath : "" ) )
	{
		throw Exception( query.geterror() );
	}

	const bool outPlugHadChildren = existingOut ? existingOut->children().size() : false;
	if( !keepExistingValues )
	{
		// If we're not preserving existing values then remove all existing
		// parameter plugs - the various plug creators above know that if a
		// plug exists then they should preserve its values.
		parametersPlug()->clearChildren();
		if( existingOut )
		{
			existingOut->clearChildren();
		}
	}

	m_metadata = NULL;
	namePlug()->setValue( shaderName );
	typePlug()->setValue( std::string( "osl:" ) + query.shadertype().c_str() );

	const IECore::CompoundData *metadata = OSLShader::metadata();
	const IECore::CompoundData *parameterMetadata = NULL;
	if( metadata )
	{
		parameterMetadata = metadata->member<IECore::CompoundData>( "parameter" );
	}


	loadShaderParameters( query, parametersPlug(), parameterMetadata );

	if( !existingOut || existingOut->typeId() != Plug::staticTypeId() )
	{
		PlugPtr outPlug = new Plug( "out", Plug::Out, Plug::Default | Plug::Dynamic );
		if( existingOut )
		{
			// We had an out plug but it was the wrong type (we used
			// to use a CompoundPlug before that was deprecated). Move
			// over any existing child plugs onto our replacement.
			for( PlugIterator it( existingOut ); !it.done(); ++it )
			{
				outPlug->addChild( *it );
			}
		}
		setChild( "out", outPlug );
	}

	if( query.shadertype() == "shader" )
	{
		loadShaderParameters( query, outPlug(), parameterMetadata );
	}
	else
	{
		outPlug()->clearChildren();
	}

	if( static_cast<bool>( outPlug()->children().size() ) != outPlugHadChildren )
	{
		// OSLShaderUI registers a dynamic metadata entry which depends on whether or
		// not the plug has children, so we must notify the world that the value will
		// have changed.
		Metadata::plugValueChangedSignal()( staticTypeId(), "out", "nodule:type", outPlug() );
	}
}
예제 #26
0
void Plug::parentChanging( Gaffer::GraphComponent *newParent )
{
	if( getFlags( Dynamic ) )
	{
		// When a dynamic plug is removed from a node, we
		// need to propagate dirtiness based on that. We
		// must call DependencyNode::affects() now, while the
		// plug is still a child of the node, but we push
		// scope so that the emission of plugDirtiedSignal()
		// is deferred until parentChanged() when the operation
		// is complete. It is essential that exceptions don't
		// prevent us getting to parentChanged() where we pop
		// scope, so propateDirtiness() takes care of handling
		// exceptions thrown by DependencyNode::affects().
		pushDirtyPropagationScope();
		if( node() )
		{
			propagateDirtinessForParentChange( this );
		}
	}

	// This method manages the connections between plugs when
	// additional child plugs are added or removed. We only
	// want to react to these changes when they are first made -
	// after this our own actions will have been recorded in the
	// undo buffer anyway and will be undone/redone automatically.
	// So here we early out if we're in such an Undo/Redo situation.

	ScriptNode *scriptNode = ancestor<ScriptNode>();
	scriptNode = scriptNode ? scriptNode : ( newParent ? newParent->ancestor<ScriptNode>() : NULL );
	if( scriptNode && ( scriptNode->currentActionStage() == Action::Undo || scriptNode->currentActionStage() == Action::Redo ) )
	{
		return;
	}

	// Now we can take the actions we need to based on the new parent
	// we're getting.

	if( !newParent )
	{
		// We're losing our parent - remove all our connections first.
		// this must be done here (rather than in a parentChangedSignal() slot)
		// because we need a current parent for the operation to be undoable.
		setInput( 0 );
		// Deal with outputs whose parent is an output of our parent.
		// For these we actually remove the destination plug itself,
		// so that the parent plugs may remain connected.
		if( Plug *oldParent = parent<Plug>() )
		{
			for( OutputContainer::iterator it = m_outputs.begin(); it!=m_outputs.end();  )
			{
				Plug *output = *it++;
				Plug *outputParent = output->parent<Plug>();
				if( outputParent && outputParent->getInput<Plug>() == oldParent )
				{
					// We're removing the child precisely so that the parent connection
					// remains valid, so we can block its updateInputFromChildInputs() call.
					assert( outputParent->m_skipNextUpdateInputFromChildInputs == false );
					ScopedAssignment<bool> blocker( outputParent->m_skipNextUpdateInputFromChildInputs, true );
					outputParent->removeChild( output );
				}
			}
		}
		// Remove any remaining output connections.
		removeOutputs();
	}
	else if( Plug *newParentPlug = IECore::runTimeCast<Plug>( newParent ) )
	{
		// we're getting a new parent - update its input connection from
		// all the children including the pending one.
		newParentPlug->updateInputFromChildInputs( this );
		// and add a new child plug to any of its outputs to maintain
		// the output connections.
		const OutputContainer &outputs = newParentPlug->outputs();
		for( OutputContainer::const_iterator it = outputs.begin(), eIt = outputs.end(); it != eIt; ++it )
		{
			Plug *output = *it;
			if( output->acceptsChild( this ) )
			{
				PlugPtr outputChildPlug = createCounterpart( getName(), direction() );
				{
					// We're adding the child so that the parent connection remains valid,
					// but the parent connection wouldn't be considered valid until the
					// child has both been added and had its input connected. We therefore
					// block the call to updateInputFromChildInputs() to keep the parent
					// connection intact.
					assert( output->m_skipNextUpdateInputFromChildInputs == false );
					ScopedAssignment<bool> blocker( output->m_skipNextUpdateInputFromChildInputs, true );
					output->addChild( outputChildPlug );
				}
				outputChildPlug->setInput( this, /* setChildInputs = */ true, /* updateParentInput = */ false );
			}
		}
	}

}
예제 #27
0
Gaffer::Plug *ParameterHandler::setupPlug( const AtParamEntry *parameter, Gaffer::GraphComponent *plugParent, Gaffer::Plug::Direction direction )
{
	std::string name = AiParamGetName( parameter );

	PlugPtr plug = 0;
	switch( AiParamGetType( parameter ) )
	{
		case AI_TYPE_FLOAT :

			plug = new FloatPlug(
				name,
				direction,
				AiParamGetDefault( parameter )->FLT
			);

			break;

		case AI_TYPE_INT :

			plug = new IntPlug(
				name,
				direction,
				AiParamGetDefault( parameter )->INT
			);

			break;

		case AI_TYPE_BOOLEAN :

			plug = new BoolPlug(
				name,
				direction,
				AiParamGetDefault( parameter )->BOOL
			);

			break;

		case AI_TYPE_RGB :

			plug = new Color3fPlug(
				name,
				direction,
				Color3f(
					AiParamGetDefault( parameter )->RGB.r,
					AiParamGetDefault( parameter )->RGB.g,
					AiParamGetDefault( parameter )->RGB.b
				)
			);

			break;

		case AI_TYPE_RGBA :

			plug = new Color4fPlug(
				name,
				direction,
				Color4f(
					AiParamGetDefault( parameter )->RGBA.r,
					AiParamGetDefault( parameter )->RGBA.g,
					AiParamGetDefault( parameter )->RGBA.b,
					AiParamGetDefault( parameter )->RGBA.a
				)
			);

			break;

		case AI_TYPE_POINT2 :

			plug = new V2fPlug(
				name,
				direction,
				V2f(
					AiParamGetDefault( parameter )->PNT2.x,
					AiParamGetDefault( parameter )->PNT2.y
				)
			);

			break;

		case AI_TYPE_POINT :

			plug = new V3fPlug(
				name,
				direction,
				V3f(
					AiParamGetDefault( parameter )->PNT.x,
					AiParamGetDefault( parameter )->PNT.y,
					AiParamGetDefault( parameter )->PNT.z
				)
			);

			break;

		case AI_TYPE_VECTOR :

			plug = new V3fPlug(
				name,
				direction,
				V3f(
					AiParamGetDefault( parameter )->VEC.x,
					AiParamGetDefault( parameter )->VEC.y,
					AiParamGetDefault( parameter )->VEC.z
				)
			);

			break;

		case AI_TYPE_ENUM :

			{
				AtEnum e = AiParamGetEnum( parameter );
				plug = new StringPlug(
					name,
					direction,
					AiEnumGetString( e, AiParamGetDefault( parameter )->INT )
				);

			}
			break;

		case AI_TYPE_STRING :

			{
				plug = new StringPlug(
					name,
					direction,
					AiParamGetDefault( parameter )->STR
				);

			}

	}

	if( plug )
	{
		plug->setFlags( Plug::Dynamic, true );
		plugParent->addChild( plug );
	}
	else
	{
		msg(
			Msg::Warning,
			"GafferArnold::ParameterHandler::setupPlug",
			format( "Unsupported parameter \"%s\" of type \"%s\"" ) %
				AiParamGetName( parameter ) %
				AiParamGetTypeName( AiParamGetType( parameter ) )
		);
	}

	return plug.get();
}
예제 #28
0
ImageView::ImageView( const std::string &name )
	:	View( name, new GafferImage::ImagePlug() ),
		m_imageGadget( new ImageGadget() ),
		m_framed( false )
{

	// build the preprocessor we use for applying colour
	// transforms, and the stats node we use for displaying stats.

	NodePtr preprocessor = new Node;
	ImagePlugPtr preprocessorInput = new ImagePlug( "in" );
	preprocessor->addChild( preprocessorInput );

	ClampPtr clampNode = new Clamp();
	preprocessor->setChild(  "__clamp", clampNode );
	clampNode->inPlug()->setInput( preprocessorInput );
	clampNode->enabledPlug()->setValue( false );
	clampNode->minClampToEnabledPlug()->setValue( true );
	clampNode->maxClampToEnabledPlug()->setValue( true );
	clampNode->minClampToPlug()->setValue( Color4f( 1.0f, 1.0f, 1.0f, 0.0f ) );
	clampNode->maxClampToPlug()->setValue( Color4f( 0.0f, 0.0f, 0.0f, 1.0f ) );

	BoolPlugPtr clippingPlug = new BoolPlug( "clipping" );
	clippingPlug->setFlags( Plug::AcceptsInputs, false );
	addChild( clippingPlug );

	GradePtr gradeNode = new Grade;
	preprocessor->setChild( "__grade", gradeNode );
	gradeNode->inPlug()->setInput( clampNode->outPlug() );

	FloatPlugPtr exposurePlug = new FloatPlug( "exposure" );
	exposurePlug->setFlags( Plug::AcceptsInputs, false );
	addChild( exposurePlug ); // dealt with in plugSet()

	PlugPtr gammaPlug = gradeNode->gammaPlug()->getChild( 0 )->createCounterpart( "gamma", Plug::In );
	gammaPlug->setFlags( Plug::AcceptsInputs, false );
	addChild( gammaPlug );

	addChild( new StringPlug( "displayTransform", Plug::In, "Default", Plug::Default & ~Plug::AcceptsInputs ) );

	ImagePlugPtr preprocessorOutput = new ImagePlug( "out", Plug::Out );
	preprocessor->addChild( preprocessorOutput );
	preprocessorOutput->setInput( gradeNode->outPlug() );

	// tell the base class about all the preprocessing we want to do

	setPreprocessor( preprocessor );

	// connect up to some signals

	plugSetSignal().connect( boost::bind( &ImageView::plugSet, this, ::_1 ) );
	viewportGadget()->keyPressSignal().connect( boost::bind( &ImageView::keyPress, this, ::_2 ) );
	viewportGadget()->preRenderSignal().connect( boost::bind( &ImageView::preRender, this ) );

	// get our display transform right

	insertDisplayTransform();

	// Now we can connect up our ImageGadget, which will do the
	// hard work of actually displaying the image.

	m_imageGadget->setImage( preprocessedInPlug<ImagePlug>() );
	m_imageGadget->setContext( getContext() );
	viewportGadget()->setPrimaryChild( m_imageGadget );

	m_colorInspector = shared_ptr<ColorInspector>( new ColorInspector( this ) );
}
예제 #29
0
void ArnoldShader::loadShader( const std::string &shaderName )
{
	IECoreArnold::UniverseBlock arnoldUniverse;
	
	const AtNodeEntry *shader = AiNodeEntryLookUp( shaderName.c_str() );
	if( !shader )
	{
		throw Exception( str( format( "Shader \"%s\" not found" ) % shaderName ) );
	}

	namePlug()->setValue( AiNodeEntryGetName( shader ) );
	typePlug()->setValue( "ai:surface" );
		
	ParameterHandler::setupPlugs( shader, parametersPlug() );
			
	PlugPtr outPlug = 0;
	const int outputType = AiNodeEntryGetOutputType( shader );
	switch( outputType )
	{
		case AI_TYPE_RGB :
			
			outPlug = new Color3fPlug(
				"out",
				Plug::Out
			);
		
			break;
			
		case AI_TYPE_RGBA :
			
			outPlug = new Color4fPlug(
				"out",
				Plug::Out
			);
		
			break;	
		
		case AI_TYPE_FLOAT :
			
			outPlug = new FloatPlug(
				"out",
				Plug::Out
			);
		
			break;
			
		case AI_TYPE_INT :
			
			outPlug = new IntPlug(
				"out",
				Plug::Out
			);
		
			break;	
	
	}
	
	if( outPlug )
	{
		outPlug->setFlags( Plug::Dynamic, true );
		addChild( outPlug );
	}
	else
	{
		if( outputType != AI_TYPE_NONE )
		{
			msg(
				Msg::Warning,
				"ArnoldShader::loadShader",
				format( "Unsupported output parameter of type \"%s\"" ) %
					AiParamGetTypeName( AiNodeEntryGetOutputType( shader ) )
			);
		}
	}
	
}
예제 #30
0
파일: Box.cpp 프로젝트: Eryckz/gaffer
BoxPtr Box::create( Node *parent, const Set *childNodes )
{
	BoxPtr result = new Box;
	parent->addChild( result );

	// it's pretty natural to call this function passing childNodes == ScriptNode::selection().
	// unfortunately nodes will be removed from the selection as we reparent
	// them, so we have to make a copy of childNodes so our iteration isn't befuddled by
	// the changing contents. we can use this opportunity to weed out anything in childNodes
	// which isn't a direct child of parent though.
	StandardSetPtr verifiedChildNodes = new StandardSet();
	for( NodeIterator nodeIt( parent ); nodeIt != nodeIt.end(); nodeIt++ )
	{
		if( childNodes->contains( nodeIt->get() ) )
		{
			verifiedChildNodes->add( *nodeIt );
		}
	}

	// when a node we're putting in the box has connections to
	// a node remaining outside, we need to reroute the connection
	// via an intermediate plug on the box. this mapping maps input
	// plugs (be they internal or external) to intermediate input plugs.
	typedef std::pair<const Plug *, Plug *> PlugPair;
	typedef std::map<const Plug *, Plug *> PlugMap;
	PlugMap plugMap;

	for( size_t i = 0, e = verifiedChildNodes->size(); i < e; i++ )
	{
		Node *childNode = static_cast<Node *>( verifiedChildNodes->member( i ) );
		// reroute any connections to external nodes
		for( RecursivePlugIterator plugIt( childNode ); plugIt != plugIt.end(); plugIt++ )
		{
			Plug *plug = plugIt->get();
			if( plug->direction() == Plug::In )
			{
				Plug *input = plug->getInput<Plug>();
				if( input && !verifiedChildNodes->contains( input->node() ) )
				{
					PlugMap::const_iterator mapIt = plugMap.find( input );
					if( mapIt == plugMap.end() )
					{
						PlugPtr intermediateInput = plug->createCounterpart( result->promotedCounterpartName( plug ), Plug::In );
						// we want intermediate inputs to appear on the same side of the node as the
						// equivalent internal plug, so we copy the relevant metadata over.
						copyMetadata( plug, intermediateInput.get() );
						intermediateInput->setFlags( Plug::Dynamic, true );
						result->addChild( intermediateInput );
						intermediateInput->setInput( input );
						mapIt = plugMap.insert( PlugPair( input, intermediateInput.get() ) ).first;
					}
					plug->setInput( mapIt->second );
					plugIt.prune();
				}
			}
			else
			{
				// take a copy of the outputs, because we might be modifying the
				// original as we iterate.
				Plug::OutputContainer outputs = plug->outputs();
				if( !outputs.empty() )
				{
					typedef Plug::OutputContainer::const_iterator OutputIterator;
					for( OutputIterator oIt = outputs.begin(), eIt = outputs.end(); oIt != eIt; oIt++ )
					{
						Plug *output = *oIt;
						const Node *outputNode = output->node();
						if( outputNode->parent<Node>() == parent && !verifiedChildNodes->contains( outputNode ) )
						{
							PlugMap::const_iterator mapIt = plugMap.find( plug );
							if( mapIt == plugMap.end() )
							{
								PlugPtr intermediateOutput = plug->createCounterpart( result->promotedCounterpartName( plug ), Plug::Out );
								copyMetadata( plug, intermediateOutput.get() );
								intermediateOutput->setFlags( Plug::Dynamic, true );
								result->addChild( intermediateOutput );
								intermediateOutput->setInput( plug );
								mapIt = plugMap.insert( PlugPair( plug, intermediateOutput.get() ) ).first;
							}
							output->setInput( mapIt->second );
						}
					}
					plugIt.prune();
				}
			}
		}
		// reparent the child under the Box. it's important that we do this after adding the intermediate
		// input plugs, so that when they are serialised and reloaded, the inputs to the box are set before
		// the inputs to the nodes inside the box - see GafferSceneTest.ShaderAssignmentTest.testAssignShaderFromOutsideBox
		// for a test case highlighting this necessity.
		result->addChild( childNode );
	}

	return result;
}