|
Blender
V2.59
|
00001 /* 00002 * $Id: node_select.c 37246 2011-06-06 11:04:54Z nazgul $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Blender Foundation, Nathan Letwory 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <stdio.h> 00035 00036 #include "DNA_node_types.h" 00037 #include "DNA_scene_types.h" 00038 00039 #include "BKE_context.h" 00040 00041 #include "BLI_rect.h" 00042 #include "BLI_utildefines.h" 00043 00044 #include "ED_screen.h" 00045 #include "ED_types.h" 00046 00047 #include "RNA_access.h" 00048 #include "RNA_define.h" 00049 00050 #include "WM_api.h" 00051 #include "WM_types.h" 00052 00053 #include "UI_view2d.h" 00054 00055 #include "node_intern.h" 00056 00057 /* ****** helpers ****** */ 00058 00059 static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my) 00060 { 00061 bNode *node; 00062 00063 for(next_node(ntree); (node=next_node(NULL));) { 00064 /* node body (header and scale are in other operators) */ 00065 if (BLI_in_rctf(&node->totr, mx, my)) 00066 return node; 00067 } 00068 return NULL; 00069 } 00070 00071 /* ****** Click Select ****** */ 00072 00073 static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, const int mval[2], short extend) 00074 { 00075 bNode *node; 00076 float mx, my; 00077 00078 /* get mouse coordinates in view2d space */ 00079 mx= (float)mval[0]; 00080 my= (float)mval[1]; 00081 00082 UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); 00083 00084 /* find the closest visible node */ 00085 node = node_under_mouse(snode->edittree, mx, my); 00086 00087 if (node) { 00088 if (extend == 0) { 00089 node_deselectall(snode); 00090 node->flag |= SELECT; 00091 } 00092 else 00093 node->flag ^= SELECT; 00094 00095 node_set_active(snode, node); 00096 } 00097 00098 return node; 00099 } 00100 00101 static int node_select_exec(bContext *C, wmOperator *op) 00102 { 00103 SpaceNode *snode= CTX_wm_space_node(C); 00104 ARegion *ar= CTX_wm_region(C); 00105 int mval[2]; 00106 short extend; 00107 bNode *node= NULL; 00108 00109 /* get settings from RNA properties for operator */ 00110 mval[0] = RNA_int_get(op->ptr, "mouse_x"); 00111 mval[1] = RNA_int_get(op->ptr, "mouse_y"); 00112 00113 extend = RNA_boolean_get(op->ptr, "extend"); 00114 00115 /* perform the select */ 00116 node= node_mouse_select(snode, ar, mval, extend); 00117 00118 /* send notifiers */ 00119 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00120 00121 /* allow tweak event to work too */ 00122 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; 00123 } 00124 00125 static int node_select_invoke(bContext *C, wmOperator *op, wmEvent *event) 00126 { 00127 RNA_int_set(op->ptr, "mouse_x", event->mval[0]); 00128 RNA_int_set(op->ptr, "mouse_y", event->mval[1]); 00129 00130 return node_select_exec(C,op); 00131 } 00132 00133 00134 void NODE_OT_select(wmOperatorType *ot) 00135 { 00136 /* identifiers */ 00137 ot->name= "Select"; 00138 ot->idname= "NODE_OT_select"; 00139 ot->description= "Select node under cursor"; 00140 00141 /* api callbacks */ 00142 ot->invoke= node_select_invoke; 00143 ot->poll= ED_operator_node_active; 00144 00145 /* flags */ 00146 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00147 00148 /* properties */ 00149 RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX); 00150 RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX); 00151 RNA_def_boolean(ot->srna, "extend", 0, "Extend", ""); 00152 } 00153 00154 /* ****** Border Select ****** */ 00155 00156 static int node_borderselect_exec(bContext *C, wmOperator *op) 00157 { 00158 SpaceNode *snode= CTX_wm_space_node(C); 00159 ARegion *ar= CTX_wm_region(C); 00160 bNode *node; 00161 rcti rect; 00162 rctf rectf; 00163 int gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); 00164 00165 rect.xmin= RNA_int_get(op->ptr, "xmin"); 00166 rect.ymin= RNA_int_get(op->ptr, "ymin"); 00167 UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); 00168 00169 rect.xmax= RNA_int_get(op->ptr, "xmax"); 00170 rect.ymax= RNA_int_get(op->ptr, "ymax"); 00171 UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); 00172 00173 for(node= snode->edittree->nodes.first; node; node= node->next) { 00174 if(BLI_isect_rctf(&rectf, &node->totr, NULL)) { 00175 if(gesture_mode==GESTURE_MODAL_SELECT) 00176 node->flag |= SELECT; 00177 else 00178 node->flag &= ~SELECT; 00179 } 00180 } 00181 00182 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00183 00184 return OPERATOR_FINISHED; 00185 } 00186 00187 static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) 00188 { 00189 int tweak = RNA_boolean_get(op->ptr, "tweak"); 00190 00191 if (tweak) { 00192 /* prevent initiating the border select if the mouse is over a node */ 00193 /* this allows border select on empty space, but drag-translate on nodes */ 00194 SpaceNode *snode= CTX_wm_space_node(C); 00195 ARegion *ar= CTX_wm_region(C); 00196 float mx, my; 00197 00198 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my); 00199 00200 if (node_under_mouse(snode->edittree, mx, my)) 00201 return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; 00202 } 00203 00204 return WM_border_select_invoke(C, op, event); 00205 } 00206 00207 void NODE_OT_select_border(wmOperatorType *ot) 00208 { 00209 /* identifiers */ 00210 ot->name= "Border Select"; 00211 ot->idname= "NODE_OT_select_border"; 00212 ot->description= "Use box selection to select nodes"; 00213 00214 /* api callbacks */ 00215 ot->invoke= node_border_select_invoke; 00216 ot->exec= node_borderselect_exec; 00217 ot->modal= WM_border_select_modal; 00218 ot->cancel= WM_border_select_cancel; 00219 00220 ot->poll= ED_operator_node_active; 00221 00222 /* flags */ 00223 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00224 00225 /* rna */ 00226 WM_operator_properties_gesture_border(ot, FALSE); 00227 RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture"); 00228 } 00229 00230 /* ****** Select/Deselect All ****** */ 00231 00232 static int node_select_all_exec(bContext *C, wmOperator *UNUSED(op)) 00233 { 00234 SpaceNode *snode = CTX_wm_space_node(C); 00235 bNode *first = snode->edittree->nodes.first; 00236 bNode *node; 00237 int count= 0; 00238 00239 for(node=first; node; node=node->next) 00240 if(node->flag & NODE_SELECT) 00241 count++; 00242 00243 if(count) { 00244 for(node=first; node; node=node->next) 00245 node->flag &= ~NODE_SELECT; 00246 } 00247 else { 00248 for(node=first; node; node=node->next) 00249 node->flag |= NODE_SELECT; 00250 } 00251 00252 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00253 return OPERATOR_FINISHED; 00254 } 00255 00256 void NODE_OT_select_all(wmOperatorType *ot) 00257 { 00258 /* identifiers */ 00259 ot->name = "Select or Deselect All"; 00260 ot->description = "(De)select all nodes"; 00261 ot->idname = "NODE_OT_select_all"; 00262 00263 /* api callbacks */ 00264 ot->exec = node_select_all_exec; 00265 ot->poll = ED_operator_node_active; 00266 00267 /* flags */ 00268 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00269 } 00270 00271 /* ****** Select Linked To ****** */ 00272 00273 static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) 00274 { 00275 SpaceNode *snode = CTX_wm_space_node(C); 00276 bNodeLink *link; 00277 bNode *node; 00278 00279 for (node=snode->edittree->nodes.first; node; node=node->next) 00280 node->flag &= ~NODE_TEST; 00281 00282 for (link=snode->edittree->links.first; link; link=link->next) { 00283 if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) 00284 link->tonode->flag |= NODE_TEST; 00285 } 00286 00287 for (node=snode->edittree->nodes.first; node; node=node->next) { 00288 if (node->flag & NODE_TEST) 00289 node->flag |= NODE_SELECT; 00290 } 00291 00292 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00293 return OPERATOR_FINISHED; 00294 } 00295 00296 void NODE_OT_select_linked_to(wmOperatorType *ot) 00297 { 00298 /* identifiers */ 00299 ot->name = "Select Linked To"; 00300 ot->description = "Select nodes linked to the selected ones"; 00301 ot->idname = "NODE_OT_select_linked_to"; 00302 00303 /* api callbacks */ 00304 ot->exec = node_select_linked_to_exec; 00305 ot->poll = ED_operator_node_active; 00306 00307 /* flags */ 00308 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00309 } 00310 00311 /* ****** Select Linked From ****** */ 00312 00313 static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) 00314 { 00315 SpaceNode *snode = CTX_wm_space_node(C); 00316 bNodeLink *link; 00317 bNode *node; 00318 00319 for(node=snode->edittree->nodes.first; node; node=node->next) 00320 node->flag &= ~NODE_TEST; 00321 00322 for(link=snode->edittree->links.first; link; link=link->next) { 00323 if(link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) 00324 link->fromnode->flag |= NODE_TEST; 00325 } 00326 00327 for(node=snode->edittree->nodes.first; node; node=node->next) { 00328 if(node->flag & NODE_TEST) 00329 node->flag |= NODE_SELECT; 00330 } 00331 00332 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00333 return OPERATOR_FINISHED; 00334 } 00335 00336 void NODE_OT_select_linked_from(wmOperatorType *ot) 00337 { 00338 /* identifiers */ 00339 ot->name = "Select Linked From"; 00340 ot->description = "Select nodes linked from the selected ones"; 00341 ot->idname = "NODE_OT_select_linked_from"; 00342 00343 /* api callbacks */ 00344 ot->exec = node_select_linked_from_exec; 00345 ot->poll = ED_operator_node_active; 00346 00347 /* flags */ 00348 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00349 } 00350 00351 /* ****** Select Same Type ****** */ 00352 00353 static int node_select_same_type_exec(bContext *C, wmOperator *UNUSED(op)) 00354 { 00355 SpaceNode *snode = CTX_wm_space_node(C); 00356 00357 node_select_same_type(snode); 00358 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00359 return OPERATOR_FINISHED; 00360 } 00361 00362 void NODE_OT_select_same_type(wmOperatorType *ot) 00363 { 00364 /* identifiers */ 00365 ot->name = "Select Same Type"; 00366 ot->description = "Select all the same type"; 00367 ot->idname = "NODE_OT_select_same_type"; 00368 00369 /* api callbacks */ 00370 ot->exec = node_select_same_type_exec; 00371 ot->poll = ED_operator_node_active; 00372 00373 /* flags */ 00374 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00375 } 00376 00377 /* ****** Select The Next/Prev Node Of The Same Type ****** */ 00378 00379 static int node_select_same_type_next_exec(bContext *C, wmOperator *UNUSED(op)) 00380 { 00381 SpaceNode *snode = CTX_wm_space_node(C); 00382 00383 node_select_same_type_np(snode, 0); 00384 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00385 return OPERATOR_FINISHED; 00386 } 00387 00388 void NODE_OT_select_same_type_next(wmOperatorType *ot) 00389 { 00390 /* identifiers */ 00391 ot->name = "Select Same Type Next"; 00392 ot->description = "Select the next node of the same type."; 00393 ot->idname = "NODE_OT_select_same_type_next"; 00394 00395 /* api callbacks */ 00396 ot->exec = node_select_same_type_next_exec; 00397 ot->poll = ED_operator_node_active; 00398 00399 /* flags */ 00400 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00401 } 00402 00403 static int node_select_same_type_prev_exec(bContext *C, wmOperator *UNUSED(op)) 00404 { 00405 SpaceNode *snode = CTX_wm_space_node(C); 00406 00407 node_select_same_type_np(snode, 1); 00408 WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); 00409 return OPERATOR_FINISHED; 00410 } 00411 00412 void NODE_OT_select_same_type_prev(wmOperatorType *ot) 00413 { 00414 /* identifiers */ 00415 ot->name = "Select Same Type Prev"; 00416 ot->description = "Select the prev node of the same type."; 00417 ot->idname = "NODE_OT_select_same_type_prev"; 00418 00419 /* api callbacks */ 00420 ot->exec = node_select_same_type_prev_exec; 00421 ot->poll = ED_operator_node_active; 00422 00423 /* flags */ 00424 ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; 00425 }