Exemple #1
0
bool DotNodeGadget::drop( const DragDropEvent &event )
{
	if( dotNode()->inPlug<Plug>() )
	{
		// We've already got our plugs set up - StandardNodeGadget
		// behaviour will take care of everything.
		return false;
	}

	Plug *plug = runTimeCast<Plug>( event.data.get() );
	if( !plug )
	{
		return false;
	}

	Gaffer::UndoScope undoEnabler( node()->ancestor<ScriptNode>() );

	dotNode()->setup( plug );
	if( plug->direction() == Plug::In )
	{
		plug->setInput( dotNode()->outPlug<Plug>() );
	}
	else
	{
		dotNode()->inPlug<Plug>()->setInput( plug );
	}

	return true;
}
Exemple #2
0
void Plug::removeOutputs()
{
    for( OutputContainer::iterator it = m_outputs.begin(); it!=m_outputs.end();  )
    {
        Plug *p = *it++;
        p->setInput( 0 );
    }
}
Exemple #3
0
void BoxIO::insert( Box *box )
{
	// Must take a copy of children because adding a child
	// would invalidate our PlugIterator.
	GraphComponent::ChildContainer children = box->children();
	for( PlugIterator it( children ); !it.done(); ++it )
	{
		Plug *plug = it->get();
		if( plug->direction() == Plug::In )
		{
			std::vector<Plug *> outputsNeedingBoxIn;
			const Plug::OutputContainer &outputs = plug->outputs();
			for( Plug::OutputContainer::const_iterator oIt = outputs.begin(), oeIt = outputs.end(); oIt != oeIt; ++oIt )
			{
				if( hasNodule( *oIt ) && !runTimeCast<BoxIO>( (*oIt)->node() ) )
				{
					outputsNeedingBoxIn.push_back( *oIt );
				}
			}

			if( outputsNeedingBoxIn.empty() )
			{
				continue;
			}

			BoxInPtr boxIn = new BoxIn;
			boxIn->namePlug()->setValue( plug->getName() );
			boxIn->setup( plug );
			box->addChild( boxIn );

			boxIn->inPlugInternal()->setInput( plug );
			for( std::vector<Plug *>::const_iterator oIt = outputsNeedingBoxIn.begin(), oeIt = outputsNeedingBoxIn.end(); oIt != oeIt; ++oIt )
			{
				(*oIt)->setInput( boxIn->plug() );
			}
		}
		else
		{
			// Output plug

			Plug *input = plug->getInput();
			if( !input || !hasNodule( input ) || runTimeCast<BoxIO>( input->node() ) )
			{
				continue;
			}

			BoxOutPtr boxOut = new BoxOut;
			boxOut->namePlug()->setValue( plug->getName() );
			boxOut->setup( plug );
			box->addChild( boxOut );

			boxOut->plug()->setInput( input );
			plug->setInput( boxOut->outPlugInternal() );
		}
	}

}
Exemple #4
0
void ScriptNode::deleteNodes( Node *parent, const Set *filter, bool reconnect )
{
	parent = parent ? parent : this;
	// because children are stored as a vector, it's
	// much more efficient to delete those at the end before
	// those at the beginning.
	int i = (int)(parent->children().size()) - 1;
	while( i >= 0 )
	{
		Node *node = parent->getChild<Node>( i );
		if( node && ( !filter || filter->contains( node ) ) )
		{
			// reconnect the inputs and outputs as though the node was disabled
			DependencyNode *dependencyNode = IECore::runTimeCast<DependencyNode>( node );
			if( reconnect && dependencyNode )
			{
				for( OutputPlugIterator it( node ); it != it.end(); ++it )
				{
					Plug *inPlug = dependencyNode->correspondingInput( it->get() );
					if ( !inPlug )
					{
						continue;
					}

					Plug *srcPlug = inPlug->getInput<Plug>();
					if ( !srcPlug )
					{
						continue;
					}

					// record this plug's current outputs, and reconnect them. This is a copy of (*it)->outputs() rather
					// than a reference, as reconnection can modify (*it)->outputs()...
					Plug::OutputContainer outputs = (*it)->outputs();
					for ( Plug::OutputContainer::const_iterator oIt = outputs.begin(); oIt != outputs.end(); )
					{
						Plug *dstPlug = *oIt;
						if ( dstPlug && dstPlug->acceptsInput( srcPlug ) && this->isAncestorOf( dstPlug ) )
						{
							oIt++;
							dstPlug->setInput( srcPlug );
						}
						else
						{
							oIt++;
						}
					}
				}
			}

			parent->removeChild( node );
		}
		i--;
	}
}
void CompoundNumericPlug<T>::ungang()
{
	for( size_t i = 1, e = children().size(); i < e; ++i )
	{
		Plug *child = getChild( i );
		if( const Plug *input = child->getInput<Plug>() )
		{
			if( input->parent<Plug>() == this )
			{
				child->setInput( 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 );
}
Exemple #7
0
void ScriptNode::deleteNodes( Node *parent, const Set *filter, bool reconnect )
{
	parent = parent ? parent : this;
	// because children are stored as a vector, it's
	// much more efficient to delete those at the end before
	// those at the beginning.
	int i = (int)(parent->children().size()) - 1;
	while( i >= 0 )
	{
		Node *node = parent->getChild<Node>( i );
		if( node && ( !filter || filter->contains( node ) ) )
		{
			// reconnect the inputs and outputs as though the node was disabled
			DependencyNode *dependencyNode = IECore::runTimeCast<DependencyNode>( node );
			if( reconnect && dependencyNode )
			{
				for( RecursiveOutputPlugIterator it( node ); !it.done(); ++it )
				{
					Plug *inPlug = nullptr;
					try
					{
						inPlug = dependencyNode->correspondingInput( it->get() );
					}
					catch( const std::exception &e )
					{
						msg(
							IECore::Msg::Warning,
							boost::str( boost::format( "correspondingInput error while deleting - cannot reconnect \"%s\"" ) % it->get()->fullName() ),
							e.what()
						);
					}

					if ( !inPlug )
					{
						continue;
					}

					Plug *srcPlug = inPlug->getInput();
					if ( !srcPlug )
					{
						continue;
					}

					// record this plug's current outputs, and reconnect them. This is a copy of (*it)->outputs() rather
					// than a reference, as reconnection can modify (*it)->outputs()...
					Plug::OutputContainer outputs = (*it)->outputs();
					for ( Plug::OutputContainer::const_iterator oIt = outputs.begin(); oIt != outputs.end(); ++oIt )
					{
						Plug *dstPlug = *oIt;
						if ( dstPlug && dstPlug->acceptsInput( srcPlug ) && this->isAncestorOf( dstPlug ) )
						{
							dstPlug->setInput( srcPlug );
						}
					}
				}
			}

			parent->removeChild( node );
		}
		i--;
	}
}
Exemple #8
0
void Reference::load( const std::string &fileName )
{
	ScriptNode *script = scriptNode();
	if( !script )
	{
		throw IECore::Exception( "Reference::load called without ScriptNode" );
	}

	// if we're doing a reload, then we want to maintain any values and
	// connections that our external plugs might have. but we also need to
	// get those existing plugs out of the way during the load, so that the
	// incoming plugs don't get renamed.

	std::map<std::string, Plug *> previousPlugs;
	for( PlugIterator it( this ); it != it.end(); ++it )
	{
		Plug *plug = it->get();
		if( isReferencePlug( plug ) )
		{
			previousPlugs[plug->getName()] = plug;
			plug->setName( "__tmp__" + plug->getName().string() );
		}
	}

	for( PlugIterator it( userPlug() ); it != it.end(); ++it )
	{
		Plug *plug = it->get();
		previousPlugs[plug->relativeName( this )] = plug;
		plug->setName( "__tmp__" + plug->getName().string() );
	}

	// if we're doing a reload, then we also need to delete all our child
	// nodes to make way for the incoming nodes.

	int i = (int)(children().size()) - 1;
	while( i >= 0 )
	{
		if( Node *node = getChild<Node>( i ) )
		{
			removeChild( node );
		}
		i--;
	}

	// load the reference. we use continueOnError=true to get everything possible
	// loaded, but if any errors do occur we throw an exception at the end of this
	// function. this means that the caller is still notified of errors via the
	// exception mechanism, but we leave ourselves in the best state possible for
	// the case where ScriptNode::load( continueOnError = true ) will ignore the
	// exception that we throw.

	const bool errors = script->executeFile( fileName, this, /* continueOnError = */ true );
	fileNamePlug()->setValue( fileName );

	// transfer connections and values from the old plugs onto the corresponding new ones.

	for( std::map<std::string, Plug *>::const_iterator it = previousPlugs.begin(), eIt = previousPlugs.end(); it != eIt; ++it )
	{
		Plug *oldPlug = it->second;
		Plug *newPlug = descendant<Plug>( it->first );
		if( newPlug )
		{
			try
			{
				if( newPlug->direction() == Plug::In && oldPlug->direction() == Plug::In )
				{
					if( Plug *oldInput = oldPlug->getInput<Plug>() )
					{
						newPlug->setInput( oldInput );
					}
					else
					{
						ValuePlug *oldValuePlug = runTimeCast<ValuePlug>( oldPlug );
						ValuePlug *newValuePlug = runTimeCast<ValuePlug>( newPlug );
						if( oldValuePlug && newValuePlug )
						{
							newValuePlug->setFrom( oldValuePlug );
						}
					}
				}
				else if( newPlug->direction() == Plug::Out && oldPlug->direction() == Plug::Out )
				{
					for( Plug::OutputContainer::const_iterator oIt = oldPlug->outputs().begin(), oeIt = oldPlug->outputs().end(); oIt != oeIt;  )
					{
						Plug *outputPlug = *oIt;
						++oIt; // increment now because the setInput() call invalidates our iterator.
						outputPlug->setInput( newPlug );
					}
				}
			}
			catch( const std::exception &e )
			{
				msg(
					Msg::Warning,
					boost::str( boost::format( "Loading \"%s\" onto \"%s\"" ) % fileName % getName().c_str() ),
					e.what()
				);
			}

		}

		// remove the old plug now we're done with it.
		oldPlug->parent<GraphComponent>()->removeChild( oldPlug );
	}

	// make the loaded plugs non-dynamic, because we don't want them
	// to be serialised in the script the reference is in - the whole
	// point is that they are referenced.

	for( RecursivePlugIterator it( this ); it != it.end(); ++it )
	{
		if( isReferencePlug( it->get() ) )
		{
			(*it)->setFlags( Plug::Dynamic, false );
		}
	}

	if( errors )
	{
		throw Exception( boost::str( boost::format( "Error loading reference \"%s\"" ) % fileName ) );
	}
}
Exemple #9
0
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;
}
Exemple #10
0
void Box::unpromotePlug( Plug *promotedDescendantPlug )
{
	if( !plugIsPromoted( promotedDescendantPlug ) )
	{
		if( promotedDescendantPlug )
		{
			throw IECore::Exception(
				boost::str(
					boost::format( "Cannot unpromote plug \"%s\" as it has not been promoted." ) % promotedDescendantPlug->fullName()
				)
			);
		}
		else
		{
			throw IECore::Exception( "Cannot unpromote null plug" );
		}
	}

	Plug *externalPlug = NULL;
	if( promotedDescendantPlug->direction() == Plug::In )
	{
		externalPlug = promotedDescendantPlug->getInput<Plug>();
		promotedDescendantPlug->setInput( NULL );
	}
	else
	{
		for( Plug::OutputContainer::const_iterator it = promotedDescendantPlug->outputs().begin(), eIt = promotedDescendantPlug->outputs().end(); it != eIt; ++it )
		{
			if( (*it)->node() == this )
			{
				externalPlug = *it;
				break;
			}
		}
		assert( externalPlug ); // should be true because we checked plugIsPromoted()
		externalPlug->setInput( NULL );
	}

	// remove the top level external plug , but only if
	// all the children are unused too in the case of a compound plug.
	bool remove = true;
	Plug *plugToRemove = externalPlug;
	while( plugToRemove->parent<Plug>() && plugToRemove->parent<Plug>() != userPlug() )
	{
		plugToRemove = plugToRemove->parent<Plug>();
		for( PlugIterator it( plugToRemove ); it != it.end(); ++it )
		{
			if(
				( (*it)->direction() == Plug::In && (*it)->outputs().size() ) ||
				( (*it)->direction() == Plug::Out && (*it)->getInput<Plug>() )
			)
			{
				remove = false;
				break;
			}
		}
	}
	if( remove )
	{
		plugToRemove->parent<GraphComponent>()->removeChild( plugToRemove );
	}
}