예제 #1
0
void BackdropNodeGadget::frame( const std::vector<Gaffer::Node *> &nodes )
{
	GraphGadget *graph = ancestor<GraphGadget>();
	if( !graph )
	{
		return;
	}
	
	Box3f b;
	for( std::vector<Node *>::const_iterator it = nodes.begin(), eIt = nodes.end(); it != eIt; ++it )
	{
		NodeGadget *nodeGadget = graph->nodeGadget( *it );
		if( nodeGadget )
		{
			b.extendBy( nodeGadget->transformedBound( NULL ) );
		}
	}
	
	if( b.isEmpty() )
	{
		return;
	}
	
	graph->setNodePosition( node(), V2f( b.center().x, b.center().y ) );
	
	V2f s( b.size().x / 2.0f, b.size().y / 2.0f );
	
	boundPlug()->setValue(
		Box2f( 
			V2f( -s ) - V2f( g_margin ),
			V2f( s ) + V2f( g_margin + 2.0f * g_margin )
		)
	);
}
예제 #2
0
void GraphGadget::updateDragSelection( bool dragEnd )
{
	Box2f selectionBound;
	selectionBound.extendBy( m_dragStartPosition );
	selectionBound.extendBy( m_lastDragPosition );

	for( NodeGadgetMap::const_iterator it = m_nodeGadgets.begin(), eIt = m_nodeGadgets.end(); it != eIt; ++it )
	{
		NodeGadget *nodeGadget = it->second.gadget;
		const Box3f nodeBound3 = nodeGadget->transformedBound();
		const Box2f nodeBound2( V2f( nodeBound3.min.x, nodeBound3.min.y ), V2f( nodeBound3.max.x, nodeBound3.max.y ) );
		if( boxContains( selectionBound, nodeBound2 ) )
		{
			nodeGadget->setHighlighted( true );
			if( dragEnd )
			{
				m_scriptNode->selection()->add( const_cast<Gaffer::Node *>( it->first ) );
			}
		}
		else
		{
			nodeGadget->setHighlighted( m_scriptNode->selection()->contains( it->first ) );
		}
	}
}
예제 #3
0
IECore::RunTimeTypedPtr GraphGadget::dragBegin( GadgetPtr gadget, const DragDropEvent &event )
{
	if( !m_scriptNode )
	{
		return 0;
	}
	
	V3f i;
	if( !event.line.intersect( Plane3f( V3f( 0, 0, 1 ), 0 ), i ) )
	{
		return 0;
	}
	
	m_dragMode = None;
	m_dragStartPosition = m_lastDragPosition = V2f( i.x, i.y );
	
	NodeGadget *nodeGadget = nodeGadgetAt( event.line );
	if( event.buttons == ButtonEvent::Left )
	{
		if( nodeGadget && m_scriptNode->selection()->contains( nodeGadget->node() ) )
		{
			m_dragMode = Moving;
			// we have to return an object to start the drag but the drag we're
			// starting is for our purposes only, so we return an object that won't
			// be accepted by any other drag targets.
			return IECore::NullObject::defaultNullObject();
		}
		else if( !nodeGadget )
		{
			m_dragMode = Selecting;
			return IECore::NullObject::defaultNullObject();
		}
	}
	else if( event.buttons == ButtonEvent::Middle )
	{
		if( nodeGadget )
		{
			m_dragMode = Sending;
			Pointer::setFromFile( "nodes.png" );
			if( m_scriptNode->selection()->contains( nodeGadget->node() ) )
			{
				return m_scriptNode->selection();
			}
			else
			{
				return nodeGadget->node();
			}
		}
	}
	
	return 0;
}
예제 #4
0
void GraphGadget::addConnectionGadgets( Gaffer::GraphComponent *plugParent )
{
	/// \todo I think this could be faster if we could iterate over just the nodules rather than all the plugs. Perhaps
	/// we could make it easy to recurse over all the Nodules of a NodeGadget if we had a RecursiveChildIterator for GraphComponents?
	Gaffer::Node *node = plugParent->isInstanceOf( Gaffer::Node::staticTypeId() ) ? static_cast<Gaffer::Node *>( plugParent ) : plugParent->ancestor<Gaffer::Node>();
	
	NodeGadget *nodeGadget = findNodeGadget( node );
	if( !nodeGadget )
	{
		return;
	}

	for( Gaffer::PlugIterator pIt( plugParent->children().begin(), plugParent->children().end() ); pIt!=pIt.end(); pIt++ )
	{
		if( (*pIt)->direction() == Gaffer::Plug::In )
		{
			// add connections for input plugs
			if( !findConnectionGadget( pIt->get() ) )
			{
				addConnectionGadget( pIt->get() );
			}
		}
		else
		{
			// reconnect any old output connections which may have been dangling
			Nodule *srcNodule = nodeGadget->nodule( *pIt );
			if( srcNodule )
			{
				for( Gaffer::Plug::OutputContainer::const_iterator oIt( (*pIt)->outputs().begin() ); oIt!= (*pIt)->outputs().end(); oIt++ )
				{
					ConnectionGadget *connection = findConnectionGadget( *oIt );
					if( connection && !connection->srcNodule() )
					{
						assert( connection->dstNodule()->plug()->getInput<Gaffer::Plug>() == *pIt ); 
						connection->setNodules( srcNodule, connection->dstNodule() );
					}
				}
			}
		}
		
		if( (*pIt)->isInstanceOf( Gaffer::CompoundPlug::staticTypeId() ) )
		{
			addConnectionGadgets( pIt->get() );
		}
	}
	
}
예제 #5
0
void GraphGadget::addConnectionGadget( Gaffer::Plug *dstPlug )
{
	Gaffer::Plug *srcPlug = dstPlug->getInput<Gaffer::Plug>();
	if( !srcPlug )
	{
		// there is no connection
		return;
	}
	
	Gaffer::Node *dstNode = dstPlug->node();
	NodeGadget *dstNodeGadget = findNodeGadget( dstNode );
	if( !dstNodeGadget )
	{
		return;
	}
	
	Nodule *dstNodule = dstNodeGadget->nodule( dstPlug );
	if( !dstNodule )
	{
		// the destination connection point is not represented in the graph
		return;
	}
	
	Gaffer::Node *srcNode = srcPlug->node();
	if( srcNode == dstNode )
	{
		// we don't want to visualise connections between plugs
		// on the same node.
		return;
	}
	
	// find the input nodule for the connection if there is one
	NodeGadget *srcNodeGadget = findNodeGadget( srcNode );
	Nodule *srcNodule = 0;
	if( srcNodeGadget )
	{
		srcNodule = srcNodeGadget->nodule( srcPlug );
	}
		
	ConnectionGadgetPtr connection = new ConnectionGadget( srcNodule, dstNodule );
	updateConnectionGadgetMinimisation( connection.get() );
	addChild( connection );

	m_connectionGadgets[dstPlug] = connection.get();
}
예제 #6
0
void GraphGadget::updateDragReconnectCandidate( const DragDropEvent &event )
{
	m_dragReconnectCandidate = 0;
	m_dragReconnectSrcNodule = 0;
	m_dragReconnectDstNodule = 0;
	
	if ( m_scriptNode->selection()->size() != 1 )
	{
		return;
	}
	
	// make sure the connection applies to this node.
	Gaffer::Node *node = IECore::runTimeCast<Gaffer::Node>( m_scriptNode->selection()->member( 0 ) );
	NodeGadget *selNodeGadget = nodeGadget( node );
	if ( !node || !selNodeGadget )
	{
		return;
	}
	
	m_dragReconnectCandidate = reconnectionGadgetAt( selNodeGadget, event.line );
	if ( !m_dragReconnectCandidate )
	{
		return;
	}
	
	// we don't want to reconnect the selected node to itself
	Gaffer::Plug *srcPlug = m_dragReconnectCandidate->srcNodule()->plug();
	Gaffer::Plug *dstPlug = m_dragReconnectCandidate->dstNodule()->plug();
	if ( srcPlug->node() == node || dstPlug->node() == node )
	{
		m_dragReconnectCandidate = 0;
		return;
	}
	
	Gaffer::DependencyNode *depNode = IECore::runTimeCast<Gaffer::DependencyNode>( node );
	for ( Gaffer::RecursiveOutputPlugIterator cIt( node ); cIt != cIt.end(); ++cIt )
	{
		// must be compatible
		Gaffer::Plug *p = cIt->get();
		if ( !dstPlug->acceptsInput( p ) )
		{
			continue;
		}
		
		// must have a nodule
		m_dragReconnectSrcNodule = selNodeGadget->nodule( p );
		if ( !m_dragReconnectSrcNodule )
		{
			continue;
		}
		
		// must not be connected to a nodule
		for ( Gaffer::Plug::OutputContainer::const_iterator oIt = p->outputs().begin(); oIt != p->outputs().end(); ++oIt )
		{
			NodeGadget *oNodeGadget = nodeGadget( (*oIt)->node() );
			if ( oNodeGadget && oNodeGadget->nodule( *oIt ) )
			{
				m_dragReconnectSrcNodule = 0;
				break;
			}
		}
		
		if ( !m_dragReconnectSrcNodule )
		{
			continue;
		}
		
		if ( !depNode )
		{
			// found the best option
			break;
		}
		
		// make sure its corresponding input is also free
		if ( Gaffer::Plug *in = depNode->correspondingInput( p ) )
		{
			if ( in->getInput<Gaffer::Plug>() )
			{
				m_dragReconnectSrcNodule = 0;
				continue;
			}
			
			m_dragReconnectDstNodule = selNodeGadget->nodule( in );
			if ( m_dragReconnectDstNodule )
			{
				break;
			}
		}
	}
	
	// check input plugs on non-dependencyNodes
	if ( !depNode && !m_dragReconnectDstNodule )
	{
		for ( Gaffer::RecursiveInputPlugIterator cIt( node ); cIt != cIt.end(); ++cIt )
		{
			Gaffer::Plug *p = cIt->get();
			if ( !p->getInput<Gaffer::Plug>() && p->acceptsInput( srcPlug ) )
			{
				m_dragReconnectDstNodule = selNodeGadget->nodule( p );
				if ( m_dragReconnectDstNodule )
				{
					break;
				}
			}
		}
	}
	
	if ( !m_dragReconnectSrcNodule && !m_dragReconnectDstNodule )
	{
		m_dragReconnectCandidate = 0;
	}
}
예제 #7
0
bool GraphGadget::buttonPress( GadgetPtr gadget, const ButtonEvent &event )
{
	if( event.buttons==ButtonEvent::Left )
	{
		// selection/deselection
		
		if( !m_scriptNode )
		{
			return false;
		}
		
		ViewportGadget *viewportGadget = ancestor<ViewportGadget>();
				
		std::vector<GadgetPtr> gadgetsUnderMouse;
		viewportGadget->gadgetsAt(
			viewportGadget->gadgetToRasterSpace( event.line.p0, this ),
			gadgetsUnderMouse
		);
				
		if( !gadgetsUnderMouse.size() || gadgetsUnderMouse[0] == this )
		{
			// background click. clear selection unless shift is
			// held, in which case we're expecting a shift drag
			// to add to the selection.
			if( !(event.modifiers & ButtonEvent::Shift) )
			{
				m_scriptNode->selection()->clear();
			}
			return true;
		}
				
		NodeGadget *nodeGadget = runTimeCast<NodeGadget>( gadgetsUnderMouse[0] );
		if( !nodeGadget )
		{
			nodeGadget = gadgetsUnderMouse[0]->ancestor<NodeGadget>();
		}
				
		if( nodeGadget )
		{				
			Gaffer::NodePtr node = nodeGadget->node();
			bool shiftHeld = event.modifiers && ButtonEvent::Shift;
			bool nodeSelected = m_scriptNode->selection()->contains( node );

			std::vector<Gaffer::Node *> affectedNodes;
			if( const BackdropNodeGadget *backdrop = runTimeCast<BackdropNodeGadget>( nodeGadget ) )
			{
				backdrop->framed( affectedNodes );
			}
			
			if( event.modifiers & ButtonEvent::Alt )
			{
				std::vector<NodeGadget *> upstream;
				upstreamNodeGadgets( node, upstream );
				for( std::vector<NodeGadget *>::const_iterator it = upstream.begin(), eIt = upstream.end(); it != eIt; ++it )
				{
					affectedNodes.push_back( (*it)->node() );
				}
			}
			
			affectedNodes.push_back( node );

			if( nodeSelected )
			{
				if( shiftHeld )
				{
					m_scriptNode->selection()->remove( affectedNodes.begin(), affectedNodes.end() );
				}
			}
			else
			{
				if( !shiftHeld )
				{
					m_scriptNode->selection()->clear();
				}
				m_scriptNode->selection()->add( affectedNodes.begin(), affectedNodes.end() );			
			}

			return true;
		}
	}
	else if( event.buttons == ButtonEvent::Middle )
	{
		// potentially the start of a middle button drag on a node
		return nodeGadgetAt( event.line );		
	}
	
	return false;
}