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 ) ) ); }
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 ) ); } } }
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; }
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() ); } } }
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(); }
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; } }
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; }