static int node_animation_properties(bNodeTree *ntree, bNode *node)
{
	bNodeSocket *sock;
	const ListBase *lb;
	Link *link;
	PointerRNA ptr;
	PropertyRNA *prop;

	/* check to see if any of the node's properties have fcurves */
	RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
	lb = RNA_struct_type_properties(ptr.type);

	for (link = lb->first; link; link = link->next) {
		prop = (PropertyRNA *)link;

		if (RNA_property_animated(&ptr, prop)) {
			nodeUpdate(ntree, node);
			return 1;
		}
	}

	/* now check node sockets */
	for (sock = node->inputs.first; sock; sock = sock->next) {
		RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
		prop = RNA_struct_find_property(&ptr, "default_value");

		if (RNA_property_animated(&ptr, prop)) {
			nodeUpdate(ntree, node);
			return 1;
		}
	}

	return 0;
}
static int node_animation_properties(bNodeTree *ntree, bNode *node)
{
	bNodeSocket *sock;
	const ListBase *lb;
	Link *link;
	PointerRNA ptr;
	PropertyRNA *prop;

	/* check to see if any of the node's properties have fcurves */
	RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
	lb = RNA_struct_type_properties(ptr.type);

	for (link = lb->first; link; link = link->next) {
		int driven, len = 1, index;
		prop = (PropertyRNA *)link;

		if (RNA_property_array_check(prop))
			len = RNA_property_array_length(&ptr, prop);

		for (index = 0; index < len; index++) {
			if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
				nodeUpdate(ntree, node);
				return 1;
			}
		}
	}

	/* now check node sockets */
	for (sock = node->inputs.first; sock; sock = sock->next) {
		int driven, len = 1, index;

		RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
		prop = RNA_struct_find_property(&ptr, "default_value");
		if (prop) {
			if (RNA_property_array_check(prop))
				len = RNA_property_array_length(&ptr, prop);

			for (index = 0; index < len; index++) {
				if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
					nodeUpdate(ntree, node);
					return 1;
				}
			}
		}
	}

	return 0;
}
Example #3
0
void ED_node_changed_update(ID *id, bNode *node)
{
	bNodeTree *nodetree, *edittree;
	int treetype;

	node_tree_from_ID(id, &nodetree, &edittree, &treetype);

	if(treetype==NTREE_SHADER) {
		DAG_id_tag_update(id, 0);

		if(GS(id->name) == ID_MA)
			WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, id);
		else if(GS(id->name) == ID_LA)
			WM_main_add_notifier(NC_LAMP|ND_LIGHTING_DRAW, id);
		else if(GS(id->name) == ID_WO)
			WM_main_add_notifier(NC_WORLD|ND_WORLD_DRAW, id);
	}
	else if(treetype==NTREE_COMPOSIT) {
		if(node)
			nodeUpdate(edittree, node);
		/* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
			
		node= node_tree_get_editgroup(nodetree);
		if(node)
			nodeUpdateID(nodetree, node->id);

		WM_main_add_notifier(NC_SCENE|ND_NODES, id);
	}			
	else if(treetype==NTREE_TEXTURE) {
		DAG_id_tag_update(id, 0);
		WM_main_add_notifier(NC_TEXTURE|ND_NODES, id);
	}
}
/* need to do all scenes, to prevent errors when you re-render 1 scene */
void ntreeCompositTagRender(Scene *curscene)
{
	Scene *sce;

	for (sce = G.main->scene.first; sce; sce = sce->id.next) {
		if (sce->nodetree) {
			bNode *node;

			for (node = sce->nodetree->nodes.first; node; node = node->next) {
				if (node->id == (ID *)curscene || node->type == CMP_NODE_COMPOSITE)
					nodeUpdate(sce->nodetree, node);
				else if (node->type == CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
					nodeUpdate(sce->nodetree, node);
			}
		}
	}
}
/* called from image window preview */
void ntreeCompositTagGenerators(bNodeTree *ntree)
{
	bNode *node;

	if (ntree == NULL) return;

	for (node = ntree->nodes.first; node; node = node->next) {
		if (ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
			nodeUpdate(ntree, node);
	}
}
/* tags nodes that have animation capabilities */
int ntreeCompositTagAnimated(bNodeTree *ntree)
{
	bNode *node;
	int tagged = 0;

	if (ntree == NULL) return 0;

	for (node = ntree->nodes.first; node; node = node->next) {

		tagged = node_animation_properties(ntree, node);

		/* otherwise always tag these node types */
		if (node->type == CMP_NODE_IMAGE) {
			Image *ima = (Image *)node->id;
			if (ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
				nodeUpdate(ntree, node);
				tagged = 1;
			}
		}
		else if (node->type == CMP_NODE_TIME) {
			nodeUpdate(ntree, node);
			tagged = 1;
		}
		/* here was tag render layer, but this is called after a render, so re-composites fail */
		else if (node->type == NODE_GROUP) {
			if (ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
				nodeUpdate(ntree, node);
			}
		}
		else if (ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
			nodeUpdate(ntree, node);
			tagged = 1;
		}
		else if (node->type == CMP_NODE_MASK) {
			nodeUpdate(ntree, node);
			tagged = 1;
		}
	}

	return tagged;
}
Example #7
0
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
{
	if (!sock_to->link)
		return;

	node_remove_linked(ntree, sock_to->link->fromnode);

	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(ntree);

	ED_node_generic_update(bmain, ntree, node_to);
}
Example #8
0
/* disconnect socket from the node it is connected to */
static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
{
	if (!sock_to->link)
		return;

	nodeRemLink(ntree, sock_to->link);

	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(ntree);

	ED_node_generic_update(bmain, ntree, node_to);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
{
	if (!sock_to->link)
		return;

	node_remove_linked(ntree, sock_to->link->fromnode);
	sock_to->flag |= SOCK_COLLAPSED;

	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(bmain, ntree);

	ED_node_tag_update_nodetree(bmain, ntree);
}
/* disconnect socket from the node it is connected to */
static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
{
	if (!sock_to->link)
		return;

	nodeRemLink(ntree, sock_to->link);
	sock_to->flag |= SOCK_COLLAPSED;

	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(bmain, ntree);

	ED_node_tag_update_nodetree(bmain, ntree);
}
int ntreeTexTagAnimated(bNodeTree *ntree)
{
	bNode *node;
	
	if (ntree == NULL) return 0;
	
	for (node = ntree->nodes.first; node; node = node->next) {
		if (node->type == TEX_NODE_CURVE_TIME) {
			nodeUpdate(ntree, node);
			return 1;
		}
		else if (node->type == NODE_GROUP) {
			if (ntreeTexTagAnimated((bNodeTree *)node->id) ) {
				return 1;
			}
		}
	}
	
	return 0;
}
/* based on rules, force sockets hidden always */
void ntreeCompositForceHidden(bNodeTree *ntree)
{
	bNode *node;

	if (ntree == NULL) return;

	for (node = ntree->nodes.first; node; node = node->next) {
		if (node->type == CMP_NODE_R_LAYERS)
			node_cmp_rlayers_force_hidden_passes(node);
		
		/* XXX this stuff is called all the time, don't want that.
		 * Updates should only happen when actually necessary.
		 */
#if 0
		else if (node->type == CMP_NODE_IMAGE) {
			nodeUpdate(ntree, node);
		}
#endif
	}

}
/* based on rules, force sockets hidden always */
void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
{
	bNode *node;

	if (ntree == NULL) return;

	for (node = ntree->nodes.first; node; node = node->next) {
		if (node->type == CMP_NODE_R_LAYERS) {
			Scene *sce = node->id ? (Scene *)node->id : curscene;
			SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
			if (srl)
				force_hidden_passes(node, srl->passflag);
		}
		/* XXX this stuff is called all the time, don't want that.
		 * Updates should only happen when actually necessary.
		 */
		#if 0
		else if (node->type == CMP_NODE_IMAGE) {
			nodeUpdate(ntree, node);
		}
		#endif
	}

}
/* add new node connected to this socket, or replace an existing one */
static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to,
                                    int type, NodeLinkItem *item)
{
	bNode *node_from;
	bNodeSocket *sock_from_tmp;
	bNode *node_prev = NULL;

	/* unlink existing node */
	if (sock_to->link) {
		node_prev = sock_to->link->fromnode;
		nodeRemLink(ntree, sock_to->link);
	}

	/* find existing node that we can use */
	for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
		if (node_from->type == type)
			break;

	if (node_from)
		if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex)
			node_from = NULL;

	if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item)) {
		/* keep the previous node if it's the same type */
		node_from = node_prev;
	}
	else if (!node_from) {
		node_from = nodeAddStaticNode(C, ntree, type);
		if (node_prev != NULL) {
			/* If we're replacing existing node, use it's location. */
			node_from->locx = node_prev->locx;
			node_from->locy = node_prev->locy;
			node_from->offsetx = node_prev->offsetx;
			node_from->offsety = node_prev->offsety;
		}
		else {
			/* Avoid exact intersection of nodes.
			 * TODO(sergey): Still not ideal, but better than nothing.
			 */
			int index = BLI_findindex(&node_to->inputs, sock_to);
			BLI_assert(index != -1);
			node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
			node_from->locy = node_to->locy - (node_from->typeinfo->height * index);
		}
		
		node_link_item_apply(node_from, item);
	}

	nodeSetActive(ntree, node_from);

	/* add link */
	sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
	nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to);
	sock_to->flag &= ~SOCK_COLLAPSED;

	/* copy input sockets from previous node */
	if (node_prev && node_from != node_prev) {
		bNodeSocket *sock_prev, *sock_from;

		for (sock_prev = node_prev->inputs.first; sock_prev; sock_prev = sock_prev->next) {
			for (sock_from = node_from->inputs.first; sock_from; sock_from = sock_from->next) {
				if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
					continue;

				if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
					bNodeLink *link = sock_prev->link;

					if (link && link->fromnode) {
						nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
						nodeRemLink(ntree, link);
					}

					node_socket_copy_default_value(sock_from, sock_prev);
				}
			}
		}

		/* also preserve mapping for texture nodes */
		if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
		    node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
		{
			memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
		}

		/* remove node */
		node_remove_linked(ntree, node_prev);
	}

	nodeUpdate(ntree, node_from);
	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(CTX_data_main(C), ntree);

	ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
}
Example #15
0
/* add new node connected to this socket, or replace an existing one */
static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
{
	bNode *node_from;
	bNodeSocket *sock_from;
	bNode *node_prev = NULL;

	/* unlink existing node */
	if (sock_to->link) {
		node_prev = sock_to->link->fromnode;
		nodeRemLink(ntree, sock_to->link);
	}

	/* find existing node that we can use */
	for (node_from=ntree->nodes.first; node_from; node_from=node_from->next)
		if (node_from->type == ntemp->type)
			break;

	if (node_from)
		if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
			node_from = NULL;

	if (node_prev && node_prev->type == ntemp->type &&
		(ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) {
		/* keep the previous node if it's the same type */
		node_from = node_prev;
	}
	else if (!node_from) {
		node_from= nodeAddNode(ntree, ntemp);
		node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
		node_from->locy = node_to->locy;

		if (node_from->id)
			id_us_plus(node_from->id);
	}

	nodeSetActive(ntree, node_from);

	/* add link */
	sock_from = BLI_findlink(&node_from->outputs, sock_num);
	nodeAddLink(ntree, node_from, sock_from, node_to, sock_to);

	/* copy input sockets from previous node */
	if (node_prev && node_from != node_prev) {
		bNodeSocket *sock_prev, *sock_from;

		for (sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) {
			for (sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) {
				if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
					continue;
				
				if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
					bNodeLink *link = sock_prev->link;

					if (link && link->fromnode) {
						nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
						nodeRemLink(ntree, link);
					}

					node_socket_free_default_value(sock_from->type, sock_from->default_value);
					sock_from->default_value = node_socket_make_default_value(sock_from->type);
					node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
				}
			}
		}

		/* also preserve mapping for texture nodes */
		if (node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
		    node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
		{
			memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
		}

		/* remove node */
		node_remove_linked(ntree, node_prev);
	}

	nodeUpdate(ntree, node_from);
	nodeUpdate(ntree, node_to);
	ntreeUpdateTree(ntree);

	ED_node_generic_update(bmain, ntree, node_to);
}