Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_node/node_edit.c')
-rw-r--r--source/blender/editors/space_node/node_edit.c202
1 files changed, 180 insertions, 22 deletions
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 99f2ea99efc..abc7b273ec9 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -504,14 +504,7 @@ void node_set_active(SpaceNode *snode, bNode *node)
ED_node_changed_update(snode->id, node);
}
- // XXX
-#if 0
- if(node->id)
- ; // XXX BIF_preview_changed(-1); /* temp hack to force texture preview to update */
-
- // allqueue(REDRAWBUTSSHADING, 1);
- // allqueue(REDRAWIPO, 0);
-#endif
+ WM_main_add_notifier(NC_MATERIAL|ND_NODES, node->id);
}
else if(snode->treetype==NTREE_COMPOSIT) {
Scene *scene= (Scene*)snode->id;
@@ -1332,7 +1325,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
}
else {
node->width= nsw->oldwidth + mx - nsw->mxstart;
- CLAMP(node->width, node->typeinfo->minwidth, node->typeinfo->maxwidth);
+ CLAMP(node->width, UI_DPI_FAC*node->typeinfo->minwidth, UI_DPI_FAC*node->typeinfo->maxwidth);
}
}
@@ -1366,10 +1359,17 @@ static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->mx, &snode->my);
- /* rect we're interested in is just the bottom right corner */
totr= node->totr;
- totr.xmin= totr.xmax-10.0f;
- totr.ymax= totr.ymin+10.0f;
+
+ if(node->flag & NODE_HIDDEN) {
+ /* right part of node */
+ totr.xmin= node->totr.xmax-20.0f;
+ }
+ else {
+ /* bottom right corner */
+ totr.xmin= totr.xmax-10.0f;
+ totr.ymax= totr.ymin+10.0f;
+ }
if(BLI_in_rctf(&totr, snode->mx, snode->my)) {
NodeSizeWidget *nsw= MEM_callocN(sizeof(NodeSizeWidget), "size widget op data");
@@ -2000,23 +2000,21 @@ bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float
/* ****************** Duplicate *********************** */
-static int node_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_duplicate_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree= snode->edittree;
- bNode *node, *newnode, *last;
+ bNode *node, *newnode, *lastnode;
+ bNodeLink *link, *newlink, *lastlink;
+ int keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
ED_preview_kill_jobs(C);
- last = ntree->nodes.last;
+ lastnode = ntree->nodes.last;
for(node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
newnode = nodeCopyNode(ntree, node);
- /* deselect old node, select the copy instead */
- node->flag &= ~(NODE_SELECT|NODE_ACTIVE);
- newnode->flag |= NODE_SELECT;
-
if(newnode->id) {
/* simple id user adjustment, node internal functions dont touch this
* but operators and readfile.c do. */
@@ -2027,7 +2025,54 @@ static int node_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make sure we don't copy new nodes again! */
- if (node==last)
+ if (node==lastnode)
+ break;
+ }
+
+ /* copy links between selected nodes
+ * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy!
+ */
+ lastlink = ntree->links.last;
+ for (link=ntree->links.first; link; link=link->next) {
+ /* This creates new links between copied nodes.
+ * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)!
+ */
+ if (link->tonode && (link->tonode->flag & NODE_SELECT)
+ && (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) {
+ newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink");
+ newlink->flag = link->flag;
+ newlink->tonode = link->tonode->new_node;
+ newlink->tosock = link->tosock->new_sock;
+ if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
+ newlink->fromnode = link->fromnode->new_node;
+ newlink->fromsock = link->fromsock->new_sock;
+ }
+ else {
+ /* input node not copied, this keeps the original input linked */
+ newlink->fromnode = link->fromnode;
+ newlink->fromsock = link->fromsock;
+ }
+
+ BLI_addtail(&ntree->links, newlink);
+ }
+
+ /* make sure we don't copy new links again! */
+ if (link==lastlink)
+ break;
+ }
+
+ /* deselect old nodes, select the copies instead */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->flag & SELECT) {
+ /* has been set during copy above */
+ newnode = node->new_node;
+
+ node->flag &= ~(NODE_SELECT|NODE_ACTIVE);
+ newnode->flag |= NODE_SELECT;
+ }
+
+ /* make sure we don't copy new nodes again! */
+ if (node==lastnode)
break;
}
@@ -2053,6 +2098,8 @@ void NODE_OT_duplicate(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "keep_inputs", 0, "Keep Inputs", "Keep the input links to duplicated nodes");
}
/* *************************** add link op ******************** */
@@ -2071,9 +2118,9 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
if(tlink) {
/* try to move the existing link to the next available socket */
if (tlink->tonode) {
- /* is there a free input socket with same type? */
+ /* is there a free input socket with the target type? */
for(sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
- if(sock->type==tlink->fromsock->type)
+ if(sock->type==tlink->tosock->type)
if(nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
break;
}
@@ -2863,6 +2910,117 @@ void NODE_OT_delete(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+/* ****************** Delete with reconnect ******************* */
+
+/* note: in cmp_util.c is similar code, for node_compo_pass_on() */
+/* used for disabling node (similar code in node_draw.c for disable line) */
+static void node_delete_reconnect(bNodeTree* tree, bNode* node) {
+ bNodeLink *link, *next;
+ bNodeSocket *valsocket= NULL, *colsocket= NULL, *vecsocket= NULL;
+ bNodeSocket *deliveringvalsocket= NULL, *deliveringcolsocket= NULL, *deliveringvecsocket= NULL;
+ bNode *deliveringvalnode= NULL, *deliveringcolnode= NULL, *deliveringvecnode= NULL;
+ bNodeSocket *sock;
+
+ /* test the inputs */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ int type = sock->type;
+ if(type==SOCK_VALUE && valsocket==NULL) valsocket = sock;
+ if(type==SOCK_VECTOR && vecsocket==NULL) vecsocket = sock;
+ if(type==SOCK_RGBA && colsocket==NULL) colsocket = sock;
+ }
+ // we now have the input sockets for the 'data types'
+ // now find the output sockets (and nodes) in the tree that delivers data to these input sockets
+ for(link= tree->links.first; link; link=link->next) {
+ if (valsocket != NULL) {
+ if (link->tosock == valsocket) {
+ deliveringvalnode = link->fromnode;
+ deliveringvalsocket = link->fromsock;
+ }
+ }
+ if (vecsocket != NULL) {
+ if (link->tosock == vecsocket) {
+ deliveringvecnode = link->fromnode;
+ deliveringvecsocket = link->fromsock;
+ }
+ }
+ if (colsocket != NULL) {
+ if (link->tosock == colsocket) {
+ deliveringcolnode = link->fromnode;
+ deliveringcolsocket = link->fromsock;
+ }
+ }
+ }
+ // we now have the sockets+nodes that fill the inputsockets be aware for group nodes these can be NULL
+ // now make the links for all outputlinks of the node to be reconnected
+ for(link= tree->links.first; link; link=next) {
+ next= link->next;
+ if (link->fromnode == node) {
+ sock = link->fromsock;
+ switch(sock->type) {
+ case SOCK_VALUE:
+ if (deliveringvalsocket) {
+ link->fromnode = deliveringvalnode;
+ link->fromsock = deliveringvalsocket;
+ }
+ break;
+ case SOCK_VECTOR:
+ if (deliveringvecsocket) {
+ link->fromnode = deliveringvecnode;
+ link->fromsock = deliveringvecsocket;
+ }
+ break;
+ case SOCK_RGBA:
+ if (deliveringcolsocket) {
+ link->fromnode = deliveringcolnode;
+ link->fromsock = deliveringcolsocket;
+ }
+ break;
+ }
+ }
+ }
+ if(node->id)
+ node->id->us--;
+ nodeFreeNode(tree, node);
+
+}
+
+static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode= CTX_wm_space_node(C);
+ bNode *node, *next;
+
+ ED_preview_kill_jobs(C);
+
+ for(node= snode->edittree->nodes.first; node; node= next) {
+ next= node->next;
+ if(node->flag & SELECT) {
+ node_delete_reconnect(snode->edittree, node);
+ }
+ }
+
+ node_tree_verify_groups(snode->nodetree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_delete_reconnect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete with reconnect";
+ ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
+ ot->idname= "NODE_OT_delete_reconnect";
+
+ /* api callbacks */
+ ot->exec= node_delete_reconnect_exec;
+ ot->poll= ED_operator_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/* ****************** Show Cyclic Dependencies Operator ******************* */
static int node_show_cycles_exec(bContext *C, wmOperator *UNUSED(op))