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:
authorThomas Dinges <blender@dingto.org>2012-01-03 08:23:41 +0400
committerThomas Dinges <blender@dingto.org>2012-01-03 08:23:41 +0400
commitd3af919ac618f82e650b9ae7a2a7b7049f27adf3 (patch)
treec4dfb58d5f176f97ce51329940af513ed51c40d2 /source/blender/editors/space_node
parente8dab248c8070d9651f20e34fdf358a18d52f75d (diff)
parent434c1e6df82a082fe03034a3ad3825f7b50ea533 (diff)
Merging Trunk changes into Tile branch:
SVN Range: 42300-43091. Resolved issues: * Re-added compat code for new Compositor in readfile.c * Matrix multiplication order fixes, see commit 42670. Tested compile on windows, branch looks good after merge! :)
Diffstat (limited to 'source/blender/editors/space_node')
-rw-r--r--source/blender/editors/space_node/node_buttons.c3
-rw-r--r--source/blender/editors/space_node/node_draw.c103
-rw-r--r--source/blender/editors/space_node/node_edit.c291
-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
-rw-r--r--source/blender/editors/space_node/node_templates.c2
-rw-r--r--source/blender/editors/space_node/space_node.c4
9 files changed, 369 insertions, 411 deletions
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 15e5719be37..1b5f2417384 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -115,6 +115,9 @@ static void active_node_panel(const bContext *C, Panel *pa)
uiItemS(layout);
uiItemR(layout, &ptr, "name", 0, NULL, ICON_NODE);
uiItemS(layout);
+
+ uiItemO(layout, NULL, 0, "NODE_OT_hide_socket_toggle");
+ uiItemS(layout);
/* draw this node's settings */
if (node->typeinfo && node->typeinfo->uifuncbut)
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 02a8b5cc9fb..7b692f55965 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -351,10 +351,10 @@ static void node_update_hidden(bNode *node)
/* calculate minimal radius */
for(nsock= node->inputs.first; nsock; nsock= nsock->next)
- if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE))
totin++;
for(nsock= node->outputs.first; nsock; nsock= nsock->next)
- if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE))
totout++;
tot= MAX2(totin, totout);
@@ -371,7 +371,7 @@ static void node_update_hidden(bNode *node)
rad=drad= (float)M_PI/(1.0f + (float)totout);
for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
- if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE)) {
nsock->locx= node->totr.xmax - hiddenrad + (float)sin(rad)*hiddenrad;
nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
rad+= drad;
@@ -382,7 +382,7 @@ static void node_update_hidden(bNode *node)
rad=drad= - (float)M_PI/(1.0f + (float)totin);
for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
- if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+ if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE)) {
nsock->locx= node->totr.xmin + hiddenrad + (float)sin(rad)*hiddenrad;
nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
rad+= drad;
@@ -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,43 +613,34 @@ 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) {
- int icon_id;
-
- if(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))
- icon_id= ICON_MATERIAL;
- else
- icon_id= ICON_MATERIAL_DATA;
+ uiBut *but;
iconofs-=iconbutw;
- uiDefIconBut(node->block, LABEL, B_REDR, icon_id, 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_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, "");
- }
- if(node->typeinfo->flag & NODE_OPTIONS) {
- 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; */
-
- 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_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);
}
/* title */
@@ -647,7 +650,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)
@@ -793,7 +808,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)
@@ -827,12 +854,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for(sock= node->inputs.first; sock; sock= sock->next) {
- if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (sock->flag & SOCK_IN_USE))
node_socket_circle_draw(snode->nodetree, sock, socket_size);
}
for(sock= node->outputs.first; sock; sock= sock->next) {
- if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+ if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (sock->flag & SOCK_IN_USE))
node_socket_circle_draw(snode->nodetree, sock, socket_size);
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 56246dd659f..7345c1ec6aa 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -487,6 +487,7 @@ void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *tre
}
else {
*ntree= NULL;
+ *edittree= NULL;
if(treetype) *treetype= 0;
}
}
@@ -693,108 +694,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
@@ -943,7 +842,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
@@ -958,8 +857,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?");
@@ -1699,90 +1601,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)
{
@@ -1797,6 +1617,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;
@@ -2235,7 +2080,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);
@@ -3133,15 +2978,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
@@ -3150,10 +3001,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
@@ -3162,7 +3015,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);
@@ -3185,14 +3038,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);
@@ -3217,7 +3070,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 */
@@ -3228,7 +3111,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))
@@ -3236,6 +3119,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)) {
@@ -3244,7 +3129,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);
@@ -3280,10 +3165,6 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode= CTX_wm_space_node(C);
bNode *node;
- /* no disabling inside of groups */
- if(node_tree_get_editgroup(snode->nodetree))
- return OPERATOR_CANCELLED;
-
ED_preview_kill_jobs(C);
for(node= snode->edittree->nodes.first; node; node= node->next) {
@@ -3577,7 +3458,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 ************** */
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 6027a272270..a733d45c20b 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -1,6 +1,4 @@
/*
- * $Id$
- *
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 1a808e8ee5f..9d4c5705bd1 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -248,12 +248,10 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_IMAGE:
if (wmn->action == NA_EDITED) {
if(type==NTREE_COMPOSIT) {
- Scene *scene= wmn->window->screen->scene;
-
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
- if(nodeUpdateID(scene->nodetree, wmn->reference))
+ if(nodeUpdateID(snode->nodetree, wmn->reference))
ED_area_tag_refresh(sa);
}
}