doxygen: blender/editors tagged.
[blender.git] / source / blender / editors / space_node / node_select.c
index 87bd6075ec573ffb8e347dcaa6a6021f8e9efc9c..4aa56ef370d4fbcd3b44e4f6fa2dc4523bdd3170 100644 (file)
@@ -1,5 +1,5 @@
-/**
- * $Id:
+/*
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2008 Blender Foundation.
  * All rights reserved.
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/space_node/node_select.c
+ *  \ingroup spnode
+ */
+
+
 #include <stdio.h>
 
 #include "DNA_node_types.h"
-#include "DNA_material_types.h"
-#include "DNA_texture_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
 
 #include "BKE_context.h"
-#include "BKE_node.h"
-#include "BKE_global.h"
-#include "BKE_utildefines.h"
 
 #include "BLI_rect.h"
+#include "BLI_utildefines.h"
 
-#include "ED_space_api.h"
 #include "ED_screen.h"
 #include "ED_types.h"
 
 #include "UI_view2d.h"
  
 #include "node_intern.h"
+
+/* ****** helpers ****** */
+
+static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my)
+{
+       bNode *node;
+       
+       for(next_node(ntree); (node=next_node(NULL));) {
+               /* node body (header and scale are in other operators) */
+               if (BLI_in_rctf(&node->totr, mx, my))
+                       return node;
+       }
+       return NULL;
+}
+
+/* ****** Click Select ****** */
  
 static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short extend)
 {
@@ -68,11 +82,7 @@ static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, shor
        UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
        
        /* find the closest visible node */
-       for(next_node(snode->edittree); (node=next_node(NULL));) {
-               /* node body (header and scale are in other operators) */
-               if (BLI_in_rctf(&node->totr, mx, my))
-                       break;
-       }
+       node = node_under_mouse(snode->edittree, mx, my);
        
        if (node) {
                if (extend == 0) {
@@ -104,19 +114,9 @@ static int node_select_exec(bContext *C, wmOperator *op)
        
        /* perform the select */
        node= node_mouse_select(snode, ar, mval, extend);
-
-       /* need refresh/a notifier vs compo notifier */
-       WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */
-
-       /* WATCH THIS, there are a few other ways to change the active material */
-       if(node) {
-               if (node->id && GS(node->id->name)== ID_MA) {
-                       WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING_DRAW, node->id);
-               }
-       }
        
-    /* send notifiers */
-       WM_event_add_notifier(C, NC_NODE|ND_NODE_SELECT, NULL);
+       /* send notifiers */
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
        
        /* allow tweak event to work too */
        return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
@@ -142,6 +142,7 @@ void NODE_OT_select(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select";
        ot->idname= "NODE_OT_select";
+       ot->description= "Select node under cursor";
        
        /* api callbacks */
        ot->invoke= node_select_invoke;
@@ -175,9 +176,6 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
        rect.ymax= RNA_int_get(op->ptr, "ymax");
        UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
        
-       if (snode->edittree == NULL) // XXX should this be in poll()? - campbell
-               return OPERATOR_FINISHED;
-
        for(node= snode->edittree->nodes.first; node; node= node->next) {
                if(BLI_isect_rctf(&rectf, &node->totr, NULL)) {
                        if(gesture_mode==GESTURE_MODAL_SELECT)
@@ -187,19 +185,48 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
                }
        }
        
-       WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
 
        return OPERATOR_FINISHED;
 }
 
+static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       int tweak = RNA_boolean_get(op->ptr, "tweak");
+       
+       if (tweak) {
+               /* prevent initiating the border select if the mouse is over a node */
+               /* this allows border select on empty space, but drag-translate on nodes */
+               SpaceNode *snode= CTX_wm_space_node(C);
+               ARegion *ar= CTX_wm_region(C);
+               short mval[2];
+               float mx, my;
+               
+               mval[0]= event->x - ar->winrct.xmin;
+               mval[1]= event->y - ar->winrct.ymin;
+               
+               /* get mouse coordinates in view2d space */
+               mx= (float)mval[0];
+               my= (float)mval[1];
+               
+               UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
+               
+               if (node_under_mouse(snode->edittree, mx, my))
+                       return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
+       }
+       
+       return WM_border_select_invoke(C, op, event);
+}
+
 void NODE_OT_select_border(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Border Select";
        ot->idname= "NODE_OT_select_border";
+       ot->description= "Use box selection to select nodes";
        
        /* api callbacks */
-       ot->invoke= WM_border_select_invoke;
+       ot->invoke= node_border_select_invoke;
        ot->exec= node_borderselect_exec;
        ot->modal= WM_border_select_modal;
        
@@ -210,11 +237,12 @@ void NODE_OT_select_border(wmOperatorType *ot)
        
        /* rna */
        WM_operator_properties_gesture_border(ot, FALSE);
+       RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture");
 }
 
 /* ****** Select/Deselect All ****** */
 
-static int node_select_all_exec(bContext *C, wmOperator *op)
+static int node_select_all_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNode *first = snode->edittree->nodes.first;
@@ -234,15 +262,15 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
                        node->flag |= NODE_SELECT;
        }
        
-       WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
        return OPERATOR_FINISHED;
 }
 
 void NODE_OT_select_all(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name = "Select/Deselect All";
-       ot->description = "(De)select all nodes.";
+       ot->name = "Select or Deselect All";
+       ot->description = "(De)select all nodes";
        ot->idname = "NODE_OT_select_all";
        
        /* api callbacks */
@@ -255,7 +283,7 @@ void NODE_OT_select_all(wmOperatorType *ot)
 
 /* ****** Select Linked To ****** */
 
-static int node_select_linked_to_exec(bContext *C, wmOperator *op)
+static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNodeLink *link;
@@ -265,7 +293,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *op)
                node->flag &= ~NODE_TEST;
 
        for (link=snode->edittree->links.first; link; link=link->next) {
-               if (link->fromnode->flag & NODE_SELECT)
+               if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
                        link->tonode->flag |= NODE_TEST;
        }
        
@@ -274,7 +302,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *op)
                        node->flag |= NODE_SELECT;
        }
        
-       WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
        return OPERATOR_FINISHED;
 }
 
@@ -282,7 +310,7 @@ void NODE_OT_select_linked_to(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name = "Select Linked To";
-       ot->description = "Select nodes linked to the selected ones.";
+       ot->description = "Select nodes linked to the selected ones";
        ot->idname = "NODE_OT_select_linked_to";
        
        /* api callbacks */
@@ -295,7 +323,7 @@ void NODE_OT_select_linked_to(wmOperatorType *ot)
 
 /* ****** Select Linked From ****** */
 
-static int node_select_linked_from_exec(bContext *C, wmOperator *op)
+static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNodeLink *link;
@@ -305,7 +333,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *op)
                node->flag &= ~NODE_TEST;
 
        for(link=snode->edittree->links.first; link; link=link->next) {
-               if(link->tonode->flag & NODE_SELECT)
+               if(link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
                        link->fromnode->flag |= NODE_TEST;
        }
        
@@ -314,7 +342,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *op)
                        node->flag |= NODE_SELECT;
        }
        
-       WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
        return OPERATOR_FINISHED;
 }
 
@@ -322,7 +350,7 @@ void NODE_OT_select_linked_from(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name = "Select Linked From";
-       ot->description = "Select nodes linked from the selected ones.";
+       ot->description = "Select nodes linked from the selected ones";
        ot->idname = "NODE_OT_select_linked_from";
        
        /* api callbacks */
@@ -333,3 +361,78 @@ void NODE_OT_select_linked_from(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* ****** Select Same Type ****** */
+
+static int node_select_same_type_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+
+       node_select_same_type(snode);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_select_same_type(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Same Type";
+       ot->description = "Select all the same type";
+       ot->idname = "NODE_OT_select_same_type";
+       
+       /* api callbacks */
+       ot->exec = node_select_same_type_exec;
+       ot->poll = ED_operator_node_active;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ****** Select The Next/Prev Node Of The Same Type ****** */
+
+static int node_select_same_type_next_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+
+       node_select_same_type_np(snode, 0);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_select_same_type_next(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Same Type Next";
+       ot->description = "Select the next node of the same type.";
+       ot->idname = "NODE_OT_select_same_type_next";
+       
+       /* api callbacks */
+       ot->exec = node_select_same_type_next_exec;
+       ot->poll = ED_operator_node_active;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int node_select_same_type_prev_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+
+       node_select_same_type_np(snode, 1);
+       WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_select_same_type_prev(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Same Type Prev";
+       ot->description = "Select the prev node of the same type.";
+       ot->idname = "NODE_OT_select_same_type_prev";
+       
+       /* api callbacks */
+       ot->exec = node_select_same_type_prev_exec;
+       ot->poll = ED_operator_node_active;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}