static void update_output_file(bNodeTree *ntree, bNode *node)
{
  bNodeSocket *sock, *sock_next;
  PointerRNA ptr;

  /* XXX fix for #36706: remove invalid sockets added with bpy API.
   * This is not ideal, but prevents crashes from missing storage.
   * FileOutput node needs a redesign to support this properly.
   */
  for (sock = node->inputs.first; sock; sock = sock_next) {
    sock_next = sock->next;
    if (sock->storage == NULL) {
      nodeRemoveSocket(ntree, node, sock);
    }
  }
  for (sock = node->outputs.first; sock; sock = sock_next) {
    sock_next = sock->next;
    nodeRemoveSocket(ntree, node, sock);
  }

  cmp_node_update_default(ntree, node);

  /* automatically update the socket type based on linked input */
  for (sock = node->inputs.first; sock; sock = sock->next) {
    if (sock->link) {
      RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
      RNA_enum_set(&ptr, "type", sock->link->fromsock->type);
    }
  }
}
Esempio n. 2
0
static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp_first)
{
	bNodeSocket *sock;
	bNodeSocketTemplate *stemp;
	
	/* no inputs anymore? */
	if(stemp_first==NULL) {
		while(socklist->first) {
			sock = (bNodeSocket*)socklist->first;
			if (!(sock->flag & SOCK_DYNAMIC))
				nodeRemoveSocket(ntree, node, socklist->first);
		}
	}
	else {
		/* step by step compare */
		stemp= stemp_first;
		while(stemp->type != -1) {
			stemp->sock= verify_socket_template(ntree, node, in_out, socklist, stemp);
			stemp++;
		}
		/* leftovers are removed */
		while(socklist->first) {
			sock = (bNodeSocket*)socklist->first;
			if (!(sock->flag & SOCK_DYNAMIC))
				nodeRemoveSocket(ntree, node, socklist->first);
		}
		
		/* and we put back the verified sockets */
		stemp= stemp_first;
		if (socklist->first) {
			/* some dynamic sockets left, store the list start
			 * so we can add static sockets infront of it.
			 */
			sock = socklist->first;
			while(stemp->type != -1) {
				/* put static sockets infront of dynamic */
				BLI_insertlinkbefore(socklist, sock, stemp->sock);
				stemp++;
			}
		}
		else {
			while(stemp->type != -1) {
				BLI_addtail(socklist, stemp->sock);
				stemp++;
			}
		}
	}
}
Esempio n. 3
0
/* used for both group nodes and interface nodes */
static void group_verify_socket_list(bNodeTree *ntree, bNode *gnode,
                                     ListBase *iosock_lb, ListBase *verify_lb, int in_out)
{
	bNodeSocket *iosock, *sock, *nextsock;
	
	/* step by step compare */
	
	iosock = iosock_lb->first;
	for (; iosock; iosock = iosock->next) {
		/* abusing new_sock pointer for verification here! only used inside this function */
		iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out);
	}
	/* leftovers are removed */
	for (sock = verify_lb->first; sock; sock = nextsock) {
		nextsock = sock->next;
		nodeRemoveSocket(ntree, gnode, sock);
	}
	/* and we put back the verified sockets */
	iosock = iosock_lb->first;
	for (; iosock; iosock = iosock->next) {
		if (iosock->new_sock) {
			BLI_addtail(verify_lb, iosock->new_sock);
			iosock->new_sock = NULL;
		}
	}
}
Esempio n. 4
0
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
{
	bNodeSocket *newsock, *oldsock, *oldsock_next;
	ListBase oldsocklist;
	int oldindex;
	bNodeLink *link;
	
	/* store current nodes in oldsocklist, then clear socket list */
	oldsocklist = node->outputs;
	BLI_listbase_clear(&node->outputs);
	
	/* XXX make callback */
	cmp_node_image_create_outputs(ntree, node);
	
	for (newsock = node->outputs.first; newsock; newsock = newsock->next) {
		/* XXX make callback */
		oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
		if (oldsock) {
			/* XXX make callback */
			cmp_node_image_sync_output(node, newsock, oldsock);
		}
	}
	
	/* move links to new socket */
	for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
		newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
		
		if (newsock) {
			for (link = ntree->links.first; link; link = link->next) {
				if (link->fromsock == oldsock)
					link->fromsock = newsock;
			}
		}
	}
	
	/* delete old sockets
	 * XXX oldsock is not actually in the node->outputs list any more,
	 * but the nodeRemoveSocket function works anyway. In future this
	 * should become part of the core code, so can take care of this behavior.
	 */
	for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
		oldsock_next = oldsock->next;
		MEM_freeN(oldsock->storage);
		nodeRemoveSocket(ntree, node, oldsock);
	}
}
int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
{
	NodeImageMultiFile *nimf = node->storage;
	bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
	int totinputs = BLI_countlist(&node->inputs);
	
	if (!sock)
		return 0;
	
	if (nimf->active_input == totinputs-1)
		--nimf->active_input;
	
	/* free format data */
	MEM_freeN(sock->storage);
	
	nodeRemoveSocket(ntree, node, sock);
	return 1;
}
Esempio n. 6
0
static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb)
{
	bNodeSocket *sock, *nextsock, *gsock;
	
	/* step by step compare */
	for (gsock= glb->first; gsock; gsock=gsock->next) {
		/* abusing new_sock pointer for verification here! only used inside this function */
		gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock);
	}
	/* leftovers are removed */
	for (sock=lb->first; sock; sock=nextsock) {
		nextsock=sock->next;
		if (sock->flag & SOCK_DYNAMIC)
			nodeRemoveSocket(ntree, node, sock);
	}
	/* and we put back the verified sockets */
	for (gsock= glb->first; gsock; gsock=gsock->next) {
		if (gsock->new_sock) {
			BLI_addtail(lb, gsock->new_sock);
			gsock->new_sock = NULL;
		}
	}
}
Esempio n. 7
0
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, int flag)
{
	bNodeSocket *input = node->inputs.first;
	bNodeSocket *output = node->outputs.first;
	bNodeLink *link;
	int type = SOCK_FLOAT;
	const char *type_idname = nodeStaticSocketType(type, PROP_NONE);
	
	/* XXX it would be a little bit more efficient to restrict actual updates
	 * to rerout nodes connected to an updated node, but there's no reliable flag
	 * to indicate updated nodes (node->update is not set on linking).
	 */
	
	node->done = 1;
	
	/* recursive update */
	for (link = ntree->links.first; link; link = link->next) {
		bNode *fromnode = link->fromnode;
		bNode *tonode = link->tonode;
		if (!tonode || !fromnode)
			continue;
		if (nodeLinkIsHidden(link))
			continue;
		
		if (flag & REFINE_FORWARD) {
			if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
				node_reroute_inherit_type_recursive(ntree, fromnode, REFINE_FORWARD);
		}
		if (flag & REFINE_BACKWARD) {
			if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done)
				node_reroute_inherit_type_recursive(ntree, tonode, REFINE_BACKWARD);
		}
	}
	
	/* determine socket type from unambiguous input/output connection if possible */
	if (input->limit == 1 && input->link) {
		type = input->link->fromsock->type;
		type_idname = nodeStaticSocketType(type, PROP_NONE);
	}
	else if (output->limit == 1 && output->link) {
		type = output->link->tosock->type;
		type_idname = nodeStaticSocketType(type, PROP_NONE);
	}
	
	if (input->type != type) {
		bNodeSocket *ninput = nodeAddSocket(ntree, node, SOCK_IN, type_idname, "input", "Input");
		for (link = ntree->links.first; link; link = link->next) {
			if (link->tosock == input) {
				link->tosock = ninput;
				ninput->link = link;
			}
		}
		nodeRemoveSocket(ntree, node, input);
	}
	
	if (output->type != type) {
		bNodeSocket *noutput = nodeAddSocket(ntree, node, SOCK_OUT, type_idname, "output", "Output");
		for (link = ntree->links.first; link; link = link->next) {
			if (link->fromsock == output) {
				link->fromsock = noutput;
			}
		}
		nodeRemoveSocket(ntree, node, output);
	}
	
	nodeUpdateInternalLinks(ntree, node);
}