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