diff options
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 99 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 286 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 15 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_select.c | 204 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_state.c | 154 |
7 files changed, 374 insertions, 389 deletions
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 1edfa2f4ea6..c21bc09ff27 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -330,7 +330,6 @@ static void uiPanelPop(uiBlock *UNUSED(block)) #endif /* triangle 'icon' for panel header */ -/* NOTE - this seems to be only used for hiding nodes now */ void UI_DrawTriIcon(float x, float y, char dir) { if(dir=='h') { diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 67b4c43343e..7c3e4ad5c54 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -562,6 +562,18 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) } +/* common handle function for operator buttons that need to select the node first */ +static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv) +{ + bNode *node = (bNode*)node_argv; + const char *opname = (const char *)op_argv; + + /* select & activate only the button's node */ + node_select_single(C, node); + + WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL); +} + static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) { bNodeSocket *sock; @@ -601,39 +613,54 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); - /* show/hide icons, note this sequence is copied in do_header_node() node_state.c */ + /* show/hide icons */ iconofs= rct->xmax - 7.0f; + /* preview */ if(node->typeinfo->flag & NODE_PREVIEW) { - float alpha = (node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))? 1.0f: 0.5f; - + uiBut *but; iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_MATERIAL, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, alpha, ""); + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_MATERIAL, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_preview_toggle"); + /* XXX this does not work when node is activated and the operator called right afterwards, + * since active ID is not updated yet (needs to process the notifier). + * This can only work as visual indicator! + */ +// if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))) +// uiButSetFlag(but, UI_BUT_DISABLED); + uiBlockSetEmboss(node->block, UI_EMBOSS); } + /* group edit */ if(node->type == NODE_GROUP) { - + uiBut *but; iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_NODETREE, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_NODETREE, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_group_edit"); + uiBlockSetEmboss(node->block, UI_EMBOSS); } + /* option buttons */ if(node->typeinfo->flag & NODE_OPTIONS) { + uiBut *but; iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_BUTS, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); - } - { /* always hide/reveal unused sockets */ - // XXX re-enable - /* int shade; - if(node_has_hidden_sockets(node)) - shade= -40; - else - shade= -90; */ - + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_BUTS, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_options_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); + } + /* hide unused sockets */ + { + uiBut *but; iconofs-=iconbutw; - - uiDefIconBut(node->block, LABEL, B_REDR, ICON_PLUS, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_PLUS, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_socket_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); } /* title */ @@ -643,7 +670,19 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); /* open/close entirely? */ - UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); + { + uiBut *but; + int but_size = UI_UNIT_X *0.6f; + /* XXX button uses a custom triangle draw below, so make it invisible without icon */ + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefBut(node->block, TOGBUT, B_REDR, "", + rct->xmin+10.0f-but_size/2, rct->ymax-NODE_DY/2.0f-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); + + /* custom draw function for this button */ + UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); + } /* this isn't doing anything for the label, so commenting out if(node->flag & SELECT) @@ -789,7 +828,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); /* open entirely icon */ - UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); + { + uiBut *but; + int but_size = UI_UNIT_X *0.6f; + /* XXX button uses a custom triangle draw below, so make it invisible without icon */ + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefBut(node->block, TOGBUT, B_REDR, "", + rct->xmin+10.0f-but_size/2, centy-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); + + /* custom draw function for this button */ + UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); + } /* disable lines */ if(node->flag & NODE_MUTED) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index e5a216d42b0..87a56274035 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -690,108 +690,6 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) } } -static int compare_nodes(bNode *a, bNode *b) -{ - bNode *parent; - /* These tell if either the node or any of the parent nodes is selected. - * A selected parent means an unselected node is also in foreground! - */ - int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT); - int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE); - - /* if one is an ancestor of the other */ - /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ - for (parent = a->parent; parent; parent=parent->parent) { - /* if b is an ancestor, it is always behind a */ - if (parent==b) - return 1; - /* any selected ancestor moves the node forward */ - if (parent->flag & NODE_ACTIVE) - a_active = 1; - if (parent->flag & NODE_SELECT) - a_select = 1; - } - for (parent = b->parent; parent; parent=parent->parent) { - /* if a is an ancestor, it is always behind b */ - if (parent==a) - return 0; - /* any selected ancestor moves the node forward */ - if (parent->flag & NODE_ACTIVE) - b_active = 1; - if (parent->flag & NODE_SELECT) - b_select = 1; - } - - /* if one of the nodes is in the background and the other not */ - if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) - return 0; - else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) - return 1; - - /* if one has a higher selection state (active > selected > nothing) */ - if (!b_active && a_active) - return 1; - else if (!b_select && (a_active || a_select)) - return 1; - - return 0; -} -/* Sorts nodes by selection: unselected nodes first, then selected, - * then the active node at the very end. Relative order is kept intact! - */ -void node_sort(bNodeTree *ntree) -{ - /* merge sort is the algorithm of choice here */ - bNode *first_a, *first_b, *node_a, *node_b, *tmp; - int totnodes= BLI_countlist(&ntree->nodes); - int k, a, b; - - k = 1; - while (k < totnodes) { - first_a = first_b = ntree->nodes.first; - - do { - /* setup first_b pointer */ - for (b=0; b < k && first_b; ++b) { - first_b = first_b->next; - } - /* all batches merged? */ - if (first_b==NULL) - break; - - /* merge batches */ - node_a = first_a; - node_b = first_b; - a = b = 0; - while (a < k && b < k && node_b) { - if (compare_nodes(node_a, node_b)==0) { - node_a = node_a->next; - ++a; - } - else { - tmp = node_b; - node_b = node_b->next; - ++b; - BLI_remlink(&ntree->nodes, tmp); - BLI_insertlinkbefore(&ntree->nodes, node_a, tmp); - } - } - - /* setup first pointers for next batch */ - first_b = node_b; - for (; b < k; ++b) { - /* all nodes sorted? */ - if (first_b==NULL) - break; - first_b = first_b->next; - } - first_a = first_b; - } while (first_b); - - k = k << 1; - } -} - static int inside_rctf(rctf *bounds, rctf *rect) { return (bounds->xmin <= rect->xmin && bounds->xmax >= rect->xmax @@ -940,7 +838,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(C); if (snode->nodetree==snode->edittree) { - bNode *gnode= nodeGetActive(snode->nodetree); + bNode *gnode = nodeGetActive(snode->edittree); snode_make_group_editable(snode, gnode); } else @@ -955,8 +853,11 @@ static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e { SpaceNode *snode = CTX_wm_space_node(C); bNode *gnode; - - gnode= nodeGetActive(snode->edittree); + + gnode = nodeGetActive(snode->edittree); + if (!gnode) + return OPERATOR_CANCELLED; + /* XXX callback? */ if(gnode && gnode->id && GS(gnode->id->name)==ID_NT && gnode->id->lib) { uiPupMenuOkee(C, op->type->idname, "Make group local?"); @@ -1696,90 +1597,8 @@ void NODE_OT_resize(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING; } -/* ********************** select ******************** */ - - -/* no undo here! */ -void node_deselectall(SpaceNode *snode) -{ - bNode *node; - - for(node= snode->edittree->nodes.first; node; node= node->next) - node->flag &= ~SELECT; -} -/* return 1 if we need redraw otherwise zero. */ -int node_select_same_type(SpaceNode *snode) -{ - bNode *nac, *p; - int redraw; - - /* search for the active node. */ - for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { - if (nac->flag & SELECT) - break; - } - - /* no active node, return. */ - if (!nac) - return(0); - - redraw= 0; - for (p= snode->edittree->nodes.first; p; p= p->next) { - if (p->type != nac->type && p->flag & SELECT) { - /* if it's selected but different type, unselect */ - redraw= 1; - p->flag &= ~SELECT; - } - else if (p->type == nac->type && (!(p->flag & SELECT))) { - /* if it's the same type and is not selected, select! */ - redraw= 1; - p->flag |= SELECT; - } - } - return(redraw); -} - -/* return 1 if we need redraw, otherwise zero. - * dir can be 0 == next or 0 != prev. - */ -int node_select_same_type_np(SpaceNode *snode, int dir) -{ - bNode *nac, *p; - - /* search the active one. */ - for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { - if (nac->flag & SELECT) - break; - } - - /* no active node, return. */ - if (!nac) - return(0); - - if (dir == 0) - p= nac->next; - else - p= nac->prev; - - while (p) { - /* Now search the next with the same type. */ - if (p->type == nac->type) - break; - - if (dir == 0) - p= p->next; - else - p= p->prev; - } - - if (p) { - node_deselectall(snode); - p->flag |= SELECT; - return(1); - } - return(0); -} +/* ********************** hidden sockets ******************** */ int node_has_hidden_sockets(bNode *node) { @@ -1794,6 +1613,31 @@ int node_has_hidden_sockets(bNode *node) return 0; } +/* note: call node_tree_verify_groups(snode->nodetree) after this + */ +void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) +{ + bNodeSocket *sock; + + if(set==0) { + for(sock= node->inputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_HIDDEN; + for(sock= node->outputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_HIDDEN; + } + else { + /* hide unused sockets */ + for(sock= node->inputs.first; sock; sock= sock->next) { + if(sock->link==NULL) + sock->flag |= SOCK_HIDDEN; + } + for(sock= node->outputs.first; sock; sock= sock->next) { + if(nodeCountSocketLinks(snode->edittree, sock)==0) + sock->flag |= SOCK_HIDDEN; + } + } +} + static void node_link_viewer(SpaceNode *snode, bNode *tonode) { bNode *node; @@ -2232,7 +2076,7 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate { bNode *node= NULL, *gnode; - node_deselectall(snode); + node_deselect_all(snode); node = nodeAddNode(snode->edittree, ntemp); @@ -3130,15 +2974,21 @@ void NODE_OT_group_make(wmOperatorType *ot) static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) { - int tot_eq= 0, tot_neq= 0; bNode *node; + int tot_eq= 0, tot_neq= 0; + /* Toggles the flag on all selected nodes. + * If the flag is set on all nodes it is unset. + * If the flag is not set on all nodes, it is set. + */ for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { - + if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) continue; - + if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0) + continue; + if(node->flag & toggle_flag) tot_eq++; else @@ -3147,10 +2997,12 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) } for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { - + if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) continue; - + if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0) + continue; + if( (tot_eq && tot_neq) || tot_eq==0) node->flag |= toggle_flag; else @@ -3159,7 +3011,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) } } -static int node_hide_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); @@ -3182,14 +3034,14 @@ void NODE_OT_hide_toggle(wmOperatorType *ot) ot->idname= "NODE_OT_hide_toggle"; /* callbacks */ - ot->exec= node_hide_exec; + ot->exec= node_hide_toggle_exec; ot->poll= ED_operator_node_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static int node_preview_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); @@ -3214,7 +3066,37 @@ void NODE_OT_preview_toggle(wmOperatorType *ot) ot->idname= "NODE_OT_preview_toggle"; /* callbacks */ - ot->exec= node_preview_exec; + ot->exec= node_preview_toggle_exec; + ot->poll= ED_operator_node_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode= CTX_wm_space_node(C); + + /* sanity checking (poll callback checks this already) */ + if((snode == NULL) || (snode->edittree == NULL)) + return OPERATOR_CANCELLED; + + node_flag_toggle_exec(snode, NODE_OPTIONS); + + snode_notify(C, snode); + + return OPERATOR_FINISHED; +} + +void NODE_OT_options_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Node Options"; + ot->description= "Toggle option buttons display for selected nodes"; + ot->idname= "NODE_OT_options_toggle"; + + /* callbacks */ + ot->exec= node_options_toggle_exec; ot->poll= ED_operator_node_active; /* flags */ @@ -3225,7 +3107,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); bNode *node; - int hidden= 0; + int hidden; /* sanity checking (poll callback checks this already) */ if((snode == NULL) || (snode->edittree == NULL)) @@ -3233,6 +3115,8 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(C); + /* Toggle for all selected nodes */ + hidden = 0; for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { if(node_has_hidden_sockets(node)) { @@ -3241,7 +3125,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) } } } - + for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { node_set_hidden_sockets(snode, node, !hidden); @@ -3570,7 +3454,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) } } - node_deselectall(snode); + node_deselect_all(snode); if (snode->nodetree->type==NTREE_COMPOSIT) ntemp.type = CMP_NODE_IMAGE; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 88b81d0855c..9068493360e 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -82,17 +82,23 @@ void node_operatortypes(void); void node_keymap(wmKeyConfig *keyconf); /* node_select.c */ +void node_deselect_all(struct SpaceNode *snode); +int node_select_same_type(struct SpaceNode *snode); +int node_select_same_type_np(struct SpaceNode *snode, int dir); +void node_select_single(struct bContext *C, struct bNode *node); + void NODE_OT_select(struct wmOperatorType *ot); void NODE_OT_select_all(wmOperatorType *ot); void NODE_OT_select_linked_to(wmOperatorType *ot); void NODE_OT_select_linked_from(wmOperatorType *ot); -void NODE_OT_visibility_toggle(struct wmOperatorType *ot); -void NODE_OT_view_all(struct wmOperatorType *ot); void NODE_OT_select_border(struct wmOperatorType *ot); void NODE_OT_select_same_type(struct wmOperatorType *ot); void NODE_OT_select_same_type_next(wmOperatorType *ot); void NODE_OT_select_same_type_prev(wmOperatorType *ot); +/* node_state.c */ +void NODE_OT_view_all(struct wmOperatorType *ot); + /* drawnode.c */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link); void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 ); @@ -108,10 +114,6 @@ void snode_dag_update(bContext *C, SpaceNode *snode); bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene, struct bNodeTemplate *ntemp, float locx, float locy); void snode_set_context(SpaceNode *snode, Scene *scene); void snode_make_group_editable(SpaceNode *snode, bNode *gnode); -void node_sort(struct bNodeTree *ntree); -void node_deselectall(SpaceNode *snode); -int node_select_same_type(SpaceNode *snode); -int node_select_same_type_np(SpaceNode *snode, int dir); void snode_composite_job(const struct bContext *C, ScrArea *sa); bNode *node_tree_get_editgroup(bNodeTree *ntree); void node_tree_verify_groups(bNodeTree *nodetree); @@ -141,6 +143,7 @@ void NODE_OT_mute_toggle(struct wmOperatorType *ot); void NODE_OT_hide_toggle(struct wmOperatorType *ot); void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); void NODE_OT_preview_toggle(struct wmOperatorType *ot); +void NODE_OT_options_toggle(struct wmOperatorType *ot); void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 8309181ddda..b5c435b50e8 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -59,10 +59,11 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_select_same_type_prev); WM_operatortype_append(NODE_OT_view_all); - WM_operatortype_append(NODE_OT_visibility_toggle); + WM_operatortype_append(NODE_OT_mute_toggle); WM_operatortype_append(NODE_OT_hide_toggle); WM_operatortype_append(NODE_OT_preview_toggle); + WM_operatortype_append(NODE_OT_options_toggle); WM_operatortype_append(NODE_OT_hide_socket_toggle); WM_operatortype_append(NODE_OT_show_cyclic_dependencies); @@ -148,7 +149,6 @@ void node_keymap(struct wmKeyConfig *keyconf) /* each of these falls through if not handled... */ WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index c863efada9f..15efd65450c 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -31,6 +31,8 @@ #include <stdio.h> +#include "BLI_listbase.h" + #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -68,6 +70,206 @@ static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my) return NULL; } +static int compare_nodes(bNode *a, bNode *b) +{ + bNode *parent; + /* These tell if either the node or any of the parent nodes is selected. + * A selected parent means an unselected node is also in foreground! + */ + int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT); + int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE); + + /* if one is an ancestor of the other */ + /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ + for (parent = a->parent; parent; parent=parent->parent) { + /* if b is an ancestor, it is always behind a */ + if (parent==b) + return 1; + /* any selected ancestor moves the node forward */ + if (parent->flag & NODE_ACTIVE) + a_active = 1; + if (parent->flag & NODE_SELECT) + a_select = 1; + } + for (parent = b->parent; parent; parent=parent->parent) { + /* if a is an ancestor, it is always behind b */ + if (parent==a) + return 0; + /* any selected ancestor moves the node forward */ + if (parent->flag & NODE_ACTIVE) + b_active = 1; + if (parent->flag & NODE_SELECT) + b_select = 1; + } + + /* if one of the nodes is in the background and the other not */ + if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) + return 0; + else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) + return 1; + + /* if one has a higher selection state (active > selected > nothing) */ + if (!b_active && a_active) + return 1; + else if (!b_select && (a_active || a_select)) + return 1; + + return 0; +} + +/* Sorts nodes by selection: unselected nodes first, then selected, + * then the active node at the very end. Relative order is kept intact! + */ +static void node_sort(bNodeTree *ntree) +{ + /* merge sort is the algorithm of choice here */ + bNode *first_a, *first_b, *node_a, *node_b, *tmp; + int totnodes= BLI_countlist(&ntree->nodes); + int k, a, b; + + k = 1; + while (k < totnodes) { + first_a = first_b = ntree->nodes.first; + + do { + /* setup first_b pointer */ + for (b=0; b < k && first_b; ++b) { + first_b = first_b->next; + } + /* all batches merged? */ + if (first_b==NULL) + break; + + /* merge batches */ + node_a = first_a; + node_b = first_b; + a = b = 0; + while (a < k && b < k && node_b) { + if (compare_nodes(node_a, node_b)==0) { + node_a = node_a->next; + ++a; + } + else { + tmp = node_b; + node_b = node_b->next; + ++b; + BLI_remlink(&ntree->nodes, tmp); + BLI_insertlinkbefore(&ntree->nodes, node_a, tmp); + } + } + + /* setup first pointers for next batch */ + first_b = node_b; + for (; b < k; ++b) { + /* all nodes sorted? */ + if (first_b==NULL) + break; + first_b = first_b->next; + } + first_a = first_b; + } while (first_b); + + k = k << 1; + } +} + +/* no undo here! */ +void node_deselect_all(SpaceNode *snode) +{ + bNode *node; + + for(node= snode->edittree->nodes.first; node; node= node->next) + node->flag &= ~SELECT; +} + +/* return 1 if we need redraw otherwise zero. */ +int node_select_same_type(SpaceNode *snode) +{ + bNode *nac, *p; + int redraw; + + /* search for the active node. */ + for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { + if (nac->flag & SELECT) + break; + } + + /* no active node, return. */ + if (!nac) + return(0); + + redraw= 0; + for (p= snode->edittree->nodes.first; p; p= p->next) { + if (p->type != nac->type && p->flag & SELECT) { + /* if it's selected but different type, unselect */ + redraw= 1; + p->flag &= ~SELECT; + } + else if (p->type == nac->type && (!(p->flag & SELECT))) { + /* if it's the same type and is not selected, select! */ + redraw= 1; + p->flag |= SELECT; + } + } + return(redraw); +} + +/* return 1 if we need redraw, otherwise zero. + * dir can be 0 == next or 0 != prev. + */ +int node_select_same_type_np(SpaceNode *snode, int dir) +{ + bNode *nac, *p; + + /* search the active one. */ + for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { + if (nac->flag & SELECT) + break; + } + + /* no active node, return. */ + if (!nac) + return(0); + + if (dir == 0) + p= nac->next; + else + p= nac->prev; + + while (p) { + /* Now search the next with the same type. */ + if (p->type == nac->type) + break; + + if (dir == 0) + p= p->next; + else + p= p->prev; + } + + if (p) { + node_deselect_all(snode); + p->flag |= SELECT; + return(1); + } + return(0); +} + +void node_select_single(bContext *C, bNode *node) +{ + Main *bmain= CTX_data_main(C); + SpaceNode *snode= CTX_wm_space_node(C); + + node_deselect_all(snode); + node->flag |= SELECT; + + ED_node_set_active(bmain, snode->edittree, node); + + node_sort(snode->edittree); + + WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); +} + /* ****** Click Select ****** */ static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend) @@ -86,7 +288,7 @@ static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, cons if (node) { if (extend == 0) { - node_deselectall(snode); + node_deselect_all(snode); node->flag |= SELECT; } else diff --git a/source/blender/editors/space_node/node_state.c b/source/blender/editors/space_node/node_state.c index bfebd087c3f..58623e17b10 100644 --- a/source/blender/editors/space_node/node_state.c +++ b/source/blender/editors/space_node/node_state.c @@ -52,160 +52,6 @@ #include "node_intern.h" -/* **************** Node Header Buttons ************** */ - -/* note: call node_tree_verify_groups(snode->nodetree) after this - */ -void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) -{ - bNodeSocket *sock; - - if(set==0) { - for(sock= node->inputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_HIDDEN; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_HIDDEN; - } - else { - /* hide unused sockets */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->link==NULL) - sock->flag |= SOCK_HIDDEN; - } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(nodeCountSocketLinks(snode->edittree, sock)==0) - sock->flag |= SOCK_HIDDEN; - } - } -} - -static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node) -{ - node_set_hidden_sockets(snode, node, !node_has_hidden_sockets(node)); - ntreeUpdateTree(snode->edittree); -} - -static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my) -{ - rctf totr= node->totr; - - totr.ymin= totr.ymax-20.0f; - - totr.xmax= totr.xmin+15.0f; - if(BLI_in_rctf(&totr, mx, my)) { - node->flag |= NODE_HIDDEN; - return 1; - } - - totr.xmax= node->totr.xmax; - totr.xmin= totr.xmax-18.0f; - if(node->typeinfo->flag & NODE_PREVIEW) { - if(BLI_in_rctf(&totr, mx, my)) { - node->flag ^= NODE_PREVIEW; - return 1; - } - totr.xmin-=15.0f; - } - if(node->type == NODE_GROUP) { - if(BLI_in_rctf(&totr, mx, my)) { - snode_make_group_editable(snode, node); - return 1; - } - totr.xmin-=15.0f; - } - if(node->typeinfo->flag & NODE_OPTIONS) { - if(BLI_in_rctf(&totr, mx, my)) { - node->flag ^= NODE_OPTIONS; - return 1; - } - totr.xmin-=15.0f; - } - /* hide unused sockets */ - if(BLI_in_rctf(&totr, mx, my)) { - node_hide_unhide_sockets(snode, node); - } - - return 0; -} - -static int do_header_hidden_node(bNode *node, float mx, float my) -{ - rctf totr= node->totr; - - totr.xmax= totr.xmin+15.0f; - if(BLI_in_rctf(&totr, mx, my)) { - node->flag &= ~NODE_HIDDEN; - return 1; - } - return 0; -} - -static int node_toggle_visibility(SpaceNode *snode, ARegion *ar, const int mval[2]) -{ - bNode *node; - float mx, my; - - mx= (float)mval[0]; - my= (float)mval[1]; - - UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); - - for(node=snode->edittree->nodes.last; node; node=node->prev) { - if(node->flag & NODE_HIDDEN) { - if(do_header_hidden_node(node, mx, my)) { - ED_region_tag_redraw(ar); - return 1; - } - } - else { - if(do_header_node(snode, node, mx, my)) { - ED_region_tag_redraw(ar); - return 1; - } - } - } - return 0; -} - -static int node_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode= CTX_wm_space_node(C); - ARegion *ar= CTX_wm_region(C); - int mval[2]; - - mval[0] = RNA_int_get(op->ptr, "mouse_x"); - mval[1] = RNA_int_get(op->ptr, "mouse_y"); - if(node_toggle_visibility(snode, ar, mval)) - return OPERATOR_FINISHED; - else - return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; -} - -static int node_toggle_visibility_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - RNA_int_set(op->ptr, "mouse_x", event->mval[0]); - RNA_int_set(op->ptr, "mouse_y", event->mval[1]); - - return node_toggle_visibility_exec(C,op); -} - -void NODE_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Toggle Visibility"; - ot->idname= "NODE_OT_visibility_toggle"; - ot->description= "Handle clicks on node header buttons"; - - /* api callbacks */ - ot->invoke= node_toggle_visibility_invoke; - ot->poll= ED_operator_node_active; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX); -} /* **************** View All Operator ************** */ |