Storing this list in the node has the advantage of requiring far fewer calls to the potentially expensive internal_connect callback. This was called on every node redraw ... Also it will allow Cycles to properly use the internal links for muted nodes, which ensures consistent behavior. The previous method was not applicable in Cycles because transient list return values are not supported well in the RNA and particularly the C++ API implementation.
172 lines
4.9 KiB
C++
172 lines
4.9 KiB
C++
/*
|
|
* Copyright 2011, Blender Foundation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Contributor:
|
|
* Jeroen Bakker
|
|
* Monique Dewanchand
|
|
*/
|
|
|
|
#include "COM_MuteNode.h"
|
|
#include "COM_SocketConnection.h"
|
|
#include "COM_SetValueOperation.h"
|
|
#include "COM_SetVectorOperation.h"
|
|
#include "COM_SetColorOperation.h"
|
|
|
|
extern "C" {
|
|
#include "BLI_listbase.h"
|
|
}
|
|
|
|
MuteNode::MuteNode(bNode *editorNode) : Node(editorNode)
|
|
{
|
|
/* pass */
|
|
}
|
|
|
|
void MuteNode::reconnect(ExecutionSystem *graph, OutputSocket *output)
|
|
{
|
|
vector<InputSocket *> &inputsockets = this->getInputSockets();
|
|
for (unsigned int index = 0; index < inputsockets.size(); index++) {
|
|
InputSocket *input = inputsockets[index];
|
|
if (input->getDataType() == output->getDataType()) {
|
|
if (input->isConnected()) {
|
|
output->relinkConnections(input->getConnection()->getFromSocket(), false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
createDefaultOutput(graph, output);
|
|
}
|
|
|
|
void MuteNode::createDefaultOutput(ExecutionSystem *graph, OutputSocket *output)
|
|
{
|
|
NodeOperation *operation = NULL;
|
|
switch (output->getDataType()) {
|
|
case COM_DT_VALUE:
|
|
{
|
|
SetValueOperation *valueoperation = new SetValueOperation();
|
|
valueoperation->setValue(0.0f);
|
|
operation = valueoperation;
|
|
break;
|
|
}
|
|
case COM_DT_VECTOR:
|
|
{
|
|
SetVectorOperation *vectoroperation = new SetVectorOperation();
|
|
vectoroperation->setX(0.0f);
|
|
vectoroperation->setY(0.0f);
|
|
vectoroperation->setW(0.0f);
|
|
operation = vectoroperation;
|
|
break;
|
|
}
|
|
case COM_DT_COLOR:
|
|
{
|
|
SetColorOperation *coloroperation = new SetColorOperation();
|
|
coloroperation->setChannel1(0.0f);
|
|
coloroperation->setChannel2(0.0f);
|
|
coloroperation->setChannel3(0.0f);
|
|
coloroperation->setChannel4(0.0f);
|
|
operation = coloroperation;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (operation) {
|
|
output->relinkConnections(operation->getOutputSocket(), false);
|
|
graph->addOperation(operation);
|
|
}
|
|
|
|
output->clearConnections();
|
|
}
|
|
|
|
template<class SocketType> void MuteNode::fillSocketMap(vector<SocketType *> &sockets, SocketMap &socketMap)
|
|
{
|
|
for (typename vector<SocketType *>::iterator it = sockets.begin(); it != sockets.end(); it++) {
|
|
Socket *socket = (Socket *) *it;
|
|
|
|
socketMap.insert(std::pair<bNodeSocket *, Socket *>(socket->getbNodeSocket(), socket));
|
|
}
|
|
}
|
|
|
|
void MuteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
|
|
{
|
|
bNode *editorNode = this->getbNode();
|
|
vector<OutputSocket *> &outputsockets = this->getOutputSockets();
|
|
|
|
/* mute node is also used for unknown nodes and couple of nodes in fast mode
|
|
* can't use generic routines in that case
|
|
*/
|
|
if (editorNode->flag & NODE_MUTED) {
|
|
vector<InputSocket *> &inputsockets = this->getInputSockets();
|
|
vector<OutputSocket *> relinkedsockets;
|
|
SocketMap socketMap;
|
|
bNodeLink *link;
|
|
|
|
this->fillSocketMap<OutputSocket>(outputsockets, socketMap);
|
|
this->fillSocketMap<InputSocket>(inputsockets, socketMap);
|
|
|
|
for (link = (bNodeLink *) editorNode->internal_links.first; link; link = link->next) {
|
|
if (link->fromnode == editorNode) {
|
|
InputSocket *fromSocket = (InputSocket *) socketMap.find(link->fromsock)->second;
|
|
OutputSocket *toSocket = (OutputSocket *) socketMap.find(link->tosock)->second;
|
|
|
|
if (toSocket->isConnected()) {
|
|
if (fromSocket->isConnected()) {
|
|
toSocket->relinkConnections(fromSocket->getConnection()->getFromSocket(), false);
|
|
}
|
|
else {
|
|
createDefaultOutput(graph, toSocket);
|
|
}
|
|
|
|
relinkedsockets.push_back(toSocket);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* in some cases node could be marked as muted, but it wouldn't have internal connections
|
|
* this happens in such cases as muted render layer node
|
|
*
|
|
* to deal with such cases create default operation for not-relinked output sockets
|
|
*/
|
|
|
|
for (unsigned int index = 0; index < outputsockets.size(); index++) {
|
|
OutputSocket *output = outputsockets[index];
|
|
|
|
if (output->isConnected()) {
|
|
bool relinked = false;
|
|
vector<OutputSocket *>::iterator it;
|
|
|
|
for (it = relinkedsockets.begin(); it != relinkedsockets.end(); it++) {
|
|
if (*it == output) {
|
|
relinked = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!relinked)
|
|
createDefaultOutput(graph, output);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (unsigned int index = 0; index < outputsockets.size(); index++) {
|
|
OutputSocket *output = outputsockets[index];
|
|
if (output->isConnected()) {
|
|
reconnect(graph, output);
|
|
}
|
|
}
|
|
}
|
|
}
|