diff options
Diffstat (limited to 'source/blender/editors/space_node/node_edit.c')
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 202 |
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)) |