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:
-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 ************** */