예제 #1
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--;
	}
}
예제 #2
0
void buildInParallel(vector<string> filesToBuild,StringToDepNodeMap dnMap,map<string,bool> FileStatus){
  graph g;
  broadcast_node<continue_msg> input(g);
  map<string,continue_node<continue_msg>* > continueNodes; 
  for(int ii = 0; ii < filesToBuild.size(); ii++){
    string name = filesToBuild[ii];
    DependencyNode* node = dnMap[name];
    bool fileHasChangedOnDisk = FileStatus[name];
    continue_node<continue_msg> * f = new continue_node<continue_msg>( g,  [&FileStatus,node,name,fileHasChangedOnDisk]( const continue_msg& ){ 
	bool parentsChanged = checkIfParentsHaveChanged(node->dependencies,FileStatus);
	bool needToBuild = fileHasChangedOnDisk || parentsChanged;
	if(needToBuild){
	  node->doBuild();
	}

	tbb::mutex::scoped_lock lock;
	lock.acquire(mut);
	FileStatus[name] = needToBuild;
	lock.release();
	
      });
    continueNodes[node->target]= f;
  }

  map<string,continue_node<continue_msg>* >::iterator iter;
  for(iter = continueNodes.begin(); iter != continueNodes.end(); iter++){
    DependencyNode* depNode = dnMap[iter->first];
    continue_node<continue_msg>*node  = iter->second;
    //if it is a leaf node, connect it to the input node, else connect it to its parents
    if(depNode->dependencies.size() == 0){
      make_edge(input,*node);
    }
    for(int i = 0; i < depNode->dependencies.size(); i++){
      continue_node<continue_msg>* parent = continueNodes[ depNode->dependencies[i]->target ];
      make_edge(*parent,*node);
    } 
    

  }
  input.try_put( continue_msg() );

  g.wait_for_all();
	
}
예제 #3
0
void StandardNodeGadget::updateNodeEnabled( const Gaffer::Plug *dirtiedPlug )
{
	DependencyNode *dependencyNode = IECore::runTimeCast<DependencyNode>( node() );
	if( !dependencyNode )
	{
		return;
	}

	const Gaffer::BoolPlug *enabledPlug = dependencyNode->enabledPlug();
	if( !enabledPlug )
	{
		return;
	}

	if( dirtiedPlug && dirtiedPlug != enabledPlug )
	{
		return;
	}

	bool enabled = true;
	try
	{
		enabled = enabledPlug->getValue();
	}
	catch( const std::exception &e )
	{
		// The error will be reported via Node::errorSignal() anyway.
		return;
	}


	if( enabled == m_nodeEnabled )
	{
		return;
	}

	m_nodeEnabled = enabled;
	requestRender();
}
예제 #4
0
파일: Plug.cpp 프로젝트: TRiGGER80/gaffer
void Plug::propagateDirtiness()
{
    if( children().size() ) /// \todo This would be isInstanceOf( CompoundPlugTypeId ) if it didn't cause crashes somehow
    {
        // we only propagate dirtiness along leaf level plugs, because
        // they are the only plugs which can be the target of the affects(),
        // and compute() methods.
        return;
    }

    DependencyNode *n = ancestor<DependencyNode>();
    if( n )
    {
        if( direction()==In )
        {
            DependencyNode::AffectedPlugsContainer affected;
            n->affects( this, affected );
            for( DependencyNode::AffectedPlugsContainer::const_iterator it=affected.begin(); it!=affected.end(); it++ )
            {
                if( ( *it )->isInstanceOf( (IECore::TypeId)Gaffer::CompoundPlugTypeId ) )
                {
                    // DependencyNode::affects() implementations are only allowed to place leaf plugs in the outputs,
                    // so we helpfully report any mistakes.
                    throw IECore::Exception( "Non-leaf plug " + (*it)->fullName() + " cannot be returned by affects()" );
                }
                const_cast<Plug *>( *it )->emitDirtiness( n );
                const_cast<Plug *>( *it )->propagateDirtiness();
            }
        }
    }

    for( OutputContainer::const_iterator it=outputs().begin(); it!=outputs().end(); it++ )
    {
        (*it)->emitDirtiness();
        (*it)->propagateDirtiness();
    }
}
예제 #5
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--;
	}
}
예제 #6
0
void DependencyNode::propagateDirtiness( Plug *plugToDirty )
{
	// we're not able to signal anything if there's no node, so just early out
	Node *node = plugToDirty->ancestor<Node>();
	if( !node )
	{
		return;
	}
	
	// we don't emit dirtiness immediately for each plug as we traverse the
	// dependency graph for two reasons :
	//
	// - we don't want to emit dirtiness for the same plug more than once
	// - we don't want to emit dirtiness while the graph may still be being
	//   rewired by slots connected to plugSetSignal() or plugInputChangedSignal()
	//
	// instead we collect all the dirty plugs in a container as we traverse
	// the graph and only when the traversal is complete do we emit the plugDirtiedSignal().
	//
	// the container used is stored per-thread as although it's illegal to be
	// monkeying with a script from multiple threads, it's perfectly legal to
	// be monkeying with a different script in each thread.
	
	DirtyPlugsContainer &dirtyPlugs = g_dirtyPlugsContainers.local();
	
	// if the container is currently empty then we are at the start of a traversal,
	// and will emit plugDirtiedSignal() and empty the container before returning
	// from this function. if the container isn't empty then we are mid-traversal
	// and will just add to it.
	const bool emit = dirtyPlugs.empty();

	Plug *p = plugToDirty;
	while( p )
	{
		dirtyPlugs.insert( p );
		p = p->parent<Plug>();
	}	
	
	// we only propagate dirtiness along leaf level plugs, because
	// they are the only plugs which can be the target of the affects(),
	// and compute() methods.
	if( !plugToDirty->isInstanceOf( (IECore::TypeId)CompoundPlugTypeId ) )
	{
		DependencyNode *dependencyNode = IECore::runTimeCast<DependencyNode>( node );
		if( dependencyNode )
		{
			AffectedPlugsContainer affected;
			dependencyNode->affects( plugToDirty, affected );
			for( AffectedPlugsContainer::const_iterator it=affected.begin(); it!=affected.end(); it++ )
			{
				if( ( *it )->isInstanceOf( (IECore::TypeId)Gaffer::CompoundPlugTypeId ) )
				{
					// DependencyNode::affects() implementations are only allowed to place leaf plugs in the outputs,
					// so we helpfully report any mistakes.
					dirtyPlugs.clear();
					throw IECore::Exception( "Non-leaf plug " + (*it)->fullName() + " cannot be returned by affects()" );
				}
				// cast is ok - AffectedPlugsContainer only holds const pointers so that
				// affects() can be const to discourage implementations from having side effects.
				propagateDirtiness( const_cast<Plug *>( *it ) );
			}
		}
	
		for( Plug::OutputContainer::const_iterator it=plugToDirty->outputs().begin(), eIt=plugToDirty->outputs().end(); it!=eIt; ++it )
		{
			propagateDirtiness( *it );
		}		
	}
	
	if( emit )
	{
		for( size_t i = 0, e = dirtyPlugs.size(); i < e; ++i )
		{
			Plug *plug = dirtyPlugs.get<1>()[i];
			Node *node = plug->node();
			if( node )
			{
				node->plugDirtiedSignal()( plug );
			}
		}
		dirtyPlugs.clear();
	}
}