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
path: root/source
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2011-12-18 16:51:50 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2011-12-18 16:51:50 +0400
commita885d8aee6eeaf9e202abf147ed769929f859cf3 (patch)
tree18a94bacc4e05a4d8237aa9964f4695ac5b7d245 /source
parent8ed5fdde1d0ffd11cfd0df6d1d54b768e7ac4127 (diff)
Fix for toggle buttons in node headers.
The buttons for "hiding" (collapsing) a node, hiding unlinked sockets, additional options, the preview and for opening a node group were all using a custom mouse test function, which was broken. They now use actual buttons instead of just displaying icons. Before executing the respective operators the button's node has to be selected and activated, so the buttons use an intermediate handle function, which selects the node and then calls the operator.
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/interface/interface_panel.c1
-rw-r--r--source/blender/editors/space_node/node_draw.c99
-rw-r--r--source/blender/editors/space_node/node_edit.c286
-rw-r--r--source/blender/editors/space_node/node_intern.h15
-rw-r--r--source/blender/editors/space_node/node_ops.c4
-rw-r--r--source/blender/editors/space_node/node_select.c204
-rw-r--r--source/blender/editors/space_node/node_state.c154
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 ************** */