Blender  V3.3
node_select.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
8 #include <array>
9 #include <cstdlib>
10 
11 #include "DNA_node_types.h"
13 
14 #include "BLI_lasso_2d.h"
15 #include "BLI_listbase.h"
16 #include "BLI_rect.h"
17 #include "BLI_string.h"
18 #include "BLI_string_search.h"
19 #include "BLI_string_utf8.h"
20 #include "BLI_utildefines.h"
21 
22 #include "BKE_context.h"
23 #include "BKE_main.h"
24 #include "BKE_node.h"
25 #include "BKE_workspace.h"
26 
27 #include "ED_node.h" /* own include */
28 #include "ED_screen.h"
29 #include "ED_select_utils.h"
30 #include "ED_spreadsheet.h"
31 #include "ED_view3d.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_define.h"
35 
36 #include "WM_api.h"
37 #include "WM_types.h"
38 
39 #include "UI_interface.h"
40 #include "UI_resources.h"
41 #include "UI_view2d.h"
42 
43 #include "DEG_depsgraph.h"
44 
45 #include "MEM_guardedalloc.h"
46 
47 #include "node_intern.hh" /* own include */
48 
49 namespace blender::ed::space_node {
50 
51 static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event);
52 
63  const Scene *scene,
64  const Object *ob)
65 {
66  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
67  if (win->scene != scene) {
68  continue;
69  }
70  const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
71  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
72  if (area->spacetype == SPACE_VIEW3D) {
73  const View3D *v3d = (const View3D *)area->spacedata.first;
74 
76  return true;
77  }
78  }
79  }
80  }
81  return false;
82 }
83 
84 /* -------------------------------------------------------------------- */
89 {
90  const float margin = 1.5f * U.widget_unit;
91  rctf frame_inside = {
92  node.totr.xmin,
93  node.totr.xmax,
94  node.totr.ymin,
95  node.totr.ymax,
96  };
97 
98  BLI_rctf_pad(&frame_inside, -margin, -margin);
99 
100  return frame_inside;
101 }
102 
104 {
105  return is_event_over_node_or_socket(C, event);
106 }
107 
108 static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse)
109 {
110  /* Frame nodes are selectable by their borders (including their whole rect - as for other nodes -
111  * would prevent e.g. box selection of nodes inside that frame). */
112  const rctf frame_inside = node_frame_rect_inside(*node);
113  if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y) &&
114  !BLI_rctf_isect_pt(&frame_inside, mouse.x, mouse.y)) {
115  return true;
116  }
117 
118  return false;
119 }
120 
121 static bNode *node_under_mouse_select(bNodeTree &ntree, int mx, int my)
122 {
124  switch (node->type) {
125  case NODE_FRAME: {
126  const float2 mouse{(float)mx, (float)my};
127  if (node_frame_select_isect_mouse(node, mouse)) {
128  return node;
129  }
130  break;
131  }
132  default: {
133  if (BLI_rctf_isect_pt(&node->totr, mx, my)) {
134  return node;
135  }
136  break;
137  }
138  }
139  }
140  return nullptr;
141 }
142 
144 {
145  using namespace blender::math;
146 
148  switch (node->type) {
149  case NODE_REROUTE: {
150  bNodeSocket *socket = (bNodeSocket *)node->inputs.first;
151  const float2 location{socket->locx, socket->locy};
152  if (distance(mouse, location) < 24.0f) {
153  return node;
154  }
155  break;
156  }
157  case NODE_FRAME: {
158  if (node_frame_select_isect_mouse(node, mouse)) {
159  return node;
160  }
161  break;
162  }
163  default: {
164  if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y)) {
165  return node;
166  }
167  break;
168  }
169  }
170  }
171  return nullptr;
172 }
173 
174 static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mouse)
175 {
176  if (node_under_mouse_tweak(*snode.edittree, mouse)) {
177  return true;
178  }
179 
180  bNode *node;
181  bNodeSocket *sock;
183  snode, &node, &sock, mouse, (eNodeSocketInOut)(SOCK_IN | SOCK_OUT))) {
184  return true;
185  }
186 
187  return false;
188 }
189 
190 static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event)
191 {
192  SpaceNode *snode = CTX_wm_space_node(C);
193  ARegion *region = CTX_wm_region(C);
194  float2 mouse;
195 
196  int mval[2];
197  WM_event_drag_start_mval(event, region, mval);
198 
199  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &mouse.x, &mouse.y);
200  return is_position_over_node_or_socket(*snode, mouse);
201 }
202 
204 {
205  sock.flag |= SELECT;
206 
207  /* select node too */
208  if (node) {
209  node->flag |= SELECT;
210  }
211 }
212 
213 void node_socket_deselect(bNode *node, bNodeSocket &sock, const bool deselect_node)
214 {
215  sock.flag &= ~SELECT;
216 
217  if (node && deselect_node) {
218  bool sel = false;
219 
220  /* if no selected sockets remain, also deselect the node */
221  LISTBASE_FOREACH (bNodeSocket *, input, &node->inputs) {
222  if (input->flag & SELECT) {
223  sel = true;
224  break;
225  }
226  }
227  LISTBASE_FOREACH (bNodeSocket *, output, &node->outputs) {
228  if (output->flag & SELECT) {
229  sel = true;
230  break;
231  }
232  }
233 
234  if (!sel) {
235  node->flag &= ~SELECT;
236  }
237  }
238 }
239 
240 static void node_socket_toggle(bNode *node, bNodeSocket &sock, bool deselect_node)
241 {
242  if (sock.flag & SELECT) {
243  node_socket_deselect(node, sock, deselect_node);
244  }
245  else {
246  node_socket_select(node, sock);
247  }
248 }
249 
251 {
252  LISTBASE_FOREACH (bNode *, node, &snode.edittree->nodes) {
253  nodeSetSelected(node, false);
254  }
255 }
256 
257 void node_deselect_all_input_sockets(SpaceNode &snode, const bool deselect_nodes)
258 {
259  /* XXX not calling node_socket_deselect here each time, because this does iteration
260  * over all node sockets internally to check if the node stays selected.
261  * We can do that more efficiently here.
262  */
263 
264  LISTBASE_FOREACH (bNode *, node, &snode.edittree->nodes) {
265  bool sel = false;
266 
267  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
268  socket->flag &= ~SELECT;
269  }
270 
271  /* if no selected sockets remain, also deselect the node */
272  if (deselect_nodes) {
273  LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
274  if (socket->flag & SELECT) {
275  sel = true;
276  break;
277  }
278  }
279 
280  if (!sel) {
281  node->flag &= ~SELECT;
282  }
283  }
284  }
285 }
286 
287 void node_deselect_all_output_sockets(SpaceNode &snode, const bool deselect_nodes)
288 {
289  /* XXX not calling node_socket_deselect here each time, because this does iteration
290  * over all node sockets internally to check if the node stays selected.
291  * We can do that more efficiently here.
292  */
293 
294  LISTBASE_FOREACH (bNode *, node, &snode.edittree->nodes) {
295  bool sel = false;
296 
297  LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
298  socket->flag &= ~SELECT;
299  }
300 
301  /* if no selected sockets remain, also deselect the node */
302  if (deselect_nodes) {
303  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
304  if (socket->flag & SELECT) {
305  sel = true;
306  break;
307  }
308  }
309 
310  if (!sel) {
311  node->flag &= ~SELECT;
312  }
313  }
314  }
315 }
316 
319 /* -------------------------------------------------------------------- */
323 /* Return true if we need redraw, otherwise false. */
324 
326 {
327  bool changed = false;
328  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
329  if ((node->flag & SELECT) == 0) {
330  if (node->type == node_act.type) {
331  nodeSetSelected(node, true);
332  changed = true;
333  }
334  }
335  }
336  return changed;
337 }
338 
340 {
341  bool changed = false;
342  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
343  if ((node->flag & SELECT) == 0) {
344  if (compare_v3v3(node->color, node_act.color, 0.005f)) {
345  nodeSetSelected(node, true);
346  changed = true;
347  }
348  }
349  }
350  return changed;
351 }
352 
353 static bool node_select_grouped_name(bNodeTree &node_tree, bNode &node_act, const bool from_right)
354 {
355  bool changed = false;
356  const uint delims[] = {'.', '-', '_', '\0'};
357  size_t pref_len_act, pref_len_curr;
358  const char *sep, *suf_act, *suf_curr;
359 
360  pref_len_act = BLI_str_partition_ex_utf8(
361  node_act.name, nullptr, delims, &sep, &suf_act, from_right);
362 
363  /* NOTE: in case we are searching for suffix, and found none, use whole name as suffix. */
364  if (from_right && !(sep && suf_act)) {
365  pref_len_act = 0;
366  suf_act = node_act.name;
367  }
368 
369  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
370  if (node->flag & SELECT) {
371  continue;
372  }
373  pref_len_curr = BLI_str_partition_ex_utf8(
374  node->name, nullptr, delims, &sep, &suf_curr, from_right);
375 
376  /* Same as with active node name! */
377  if (from_right && !(sep && suf_curr)) {
378  pref_len_curr = 0;
379  suf_curr = node->name;
380  }
381 
382  if ((from_right && STREQ(suf_act, suf_curr)) ||
383  (!from_right && (pref_len_act == pref_len_curr) &&
384  STREQLEN(node_act.name, node->name, pref_len_act))) {
385  nodeSetSelected(node, true);
386  changed = true;
387  }
388  }
389 
390  return changed;
391 }
392 
393 enum {
398 };
399 
401 {
402  SpaceNode &snode = *CTX_wm_space_node(C);
403  bNodeTree &node_tree = *snode.edittree;
404  bNode *node_act = nodeGetActive(snode.edittree);
405 
406  if (node_act == nullptr) {
407  return OPERATOR_CANCELLED;
408  }
409 
410  bool changed = false;
411  const bool extend = RNA_boolean_get(op->ptr, "extend");
412  const int type = RNA_enum_get(op->ptr, "type");
413 
414  if (!extend) {
415  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
416  nodeSetSelected(node, false);
417  }
418  }
419  nodeSetSelected(node_act, true);
420 
421  switch (type) {
423  changed = node_select_grouped_type(node_tree, *node_act);
424  break;
426  changed = node_select_grouped_color(node_tree, *node_act);
427  break;
429  changed = node_select_grouped_name(node_tree, *node_act, false);
430  break;
432  changed = node_select_grouped_name(node_tree, *node_act, true);
433  break;
434  default:
435  break;
436  }
437 
438  if (changed) {
441  return OPERATOR_FINISHED;
442  }
443 
444  return OPERATOR_CANCELLED;
445 }
446 
448 {
449  PropertyRNA *prop;
451  {NODE_SELECT_GROUPED_TYPE, "TYPE", 0, "Type", ""},
452  {NODE_SELECT_GROUPED_COLOR, "COLOR", 0, "Color", ""},
453  {NODE_SELECT_GROUPED_PREFIX, "PREFIX", 0, "Prefix", ""},
454  {NODE_SELECT_GROUPED_SUFIX, "SUFFIX", 0, "Suffix", ""},
455  {0, nullptr, 0, nullptr, nullptr},
456  };
457 
458  /* identifiers */
459  ot->name = "Select Grouped";
460  ot->description = "Select nodes with similar properties";
461  ot->idname = "NODE_OT_select_grouped";
462 
463  /* api callbacks */
467 
468  /* flags */
470 
471  /* properties */
472  prop = RNA_def_boolean(ot->srna,
473  "extend",
474  false,
475  "Extend",
476  "Extend selection instead of deselecting everything first");
478  ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
479 }
480 
483 /* -------------------------------------------------------------------- */
488 {
489  Main *bmain = CTX_data_main(&C);
490  SpaceNode &snode = *CTX_wm_space_node(&C);
491  bNodeTree &node_tree = *snode.edittree;
492  const Object *ob = CTX_data_active_object(&C);
493  const Scene *scene = CTX_data_scene(&C);
494  const wmWindowManager *wm = CTX_wm_manager(&C);
495  bool active_texture_changed = false;
496 
497  LISTBASE_FOREACH (bNode *, node_iter, &node_tree.nodes) {
498  if (node_iter != &node) {
499  nodeSetSelected(node_iter, false);
500  }
501  }
502  nodeSetSelected(&node, true);
503 
504  ED_node_set_active(bmain, &snode, &node_tree, &node, &active_texture_changed);
506 
508  if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) {
510  }
511 
513 }
514 
516  wmOperator *op,
517  const int mval[2],
518  struct SelectPick_Params *params)
519 {
520  Main &bmain = *CTX_data_main(C);
521  SpaceNode &snode = *CTX_wm_space_node(C);
522  ARegion &region = *CTX_wm_region(C);
523  const Object *ob = CTX_data_active_object(C);
524  const Scene *scene = CTX_data_scene(C);
525  const wmWindowManager *wm = CTX_wm_manager(C);
526  bNode *node, *tnode;
527  bNodeSocket *sock = nullptr;
528  bNodeSocket *tsock;
529  float cursor[2];
530 
531  /* always do socket_select when extending selection. */
532  const bool socket_select = (params->sel_op == SEL_OP_XOR) ||
533  RNA_boolean_get(op->ptr, "socket_select");
534  bool changed = false;
535  bool found = false;
536  bool node_was_selected = false;
537 
538  /* get mouse coordinates in view2d space */
539  UI_view2d_region_to_view(&region.v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
540 
541  /* first do socket selection, these generally overlap with nodes. */
542  if (socket_select) {
543  /* NOTE: unlike nodes #SelectPick_Params isn't fully supported. */
544  const bool extend = (params->sel_op == SEL_OP_XOR);
545  if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
546  found = true;
547  node_was_selected = node->flag & SELECT;
548 
549  /* NOTE: SOCK_IN does not take into account the extend case...
550  * This feature is not really used anyway currently? */
551  node_socket_toggle(node, *sock, true);
552  changed = true;
553  }
554  else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
555  found = true;
556  node_was_selected = node->flag & SELECT;
557 
558  if (sock->flag & SELECT) {
559  if (extend) {
560  node_socket_deselect(node, *sock, true);
561  changed = true;
562  }
563  }
564  else {
565  /* Only allow one selected output per node, for sensible linking.
566  * Allow selecting outputs from different nodes though, if extend is true. */
567  if (node) {
568  for (tsock = (bNodeSocket *)node->outputs.first; tsock; tsock = tsock->next) {
569  if (tsock == sock) {
570  continue;
571  }
572  node_socket_deselect(node, *tsock, true);
573  changed = true;
574  }
575  }
576  if (!extend) {
577  for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) {
578  if (tnode == node) {
579  continue;
580  }
581  for (tsock = (bNodeSocket *)tnode->outputs.first; tsock; tsock = tsock->next) {
582  node_socket_deselect(tnode, *tsock, true);
583  changed = true;
584  }
585  }
586  }
587  node_socket_select(node, *sock);
588  changed = true;
589  }
590  }
591  }
592 
593  if (!sock) {
594 
595  /* find the closest visible node */
596  node = node_under_mouse_select(*snode.edittree, (int)cursor[0], (int)cursor[1]);
597  found = (node != nullptr);
598  node_was_selected = node && (node->flag & SELECT);
599 
600  if (params->sel_op == SEL_OP_SET) {
601  if ((found && params->select_passthrough) && (node->flag & SELECT)) {
602  found = false;
603  }
604  else if (found || params->deselect_all) {
605  /* Deselect everything. */
606  for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) {
607  nodeSetSelected(tnode, false);
608  }
609  changed = true;
610  }
611  }
612 
613  if (found) {
614  switch (params->sel_op) {
615  case SEL_OP_ADD: {
616  nodeSetSelected(node, true);
617  break;
618  }
619  case SEL_OP_SUB: {
620  nodeSetSelected(node, false);
621  break;
622  }
623  case SEL_OP_XOR: {
624  /* Check active so clicking on an inactive node activates it. */
625  bool is_selected = (node->flag & NODE_SELECT) && (node->flag & NODE_ACTIVE);
626  nodeSetSelected(node, !is_selected);
627  break;
628  }
629  case SEL_OP_SET: {
630  nodeSetSelected(node, true);
631  break;
632  }
633  case SEL_OP_AND: {
634  BLI_assert_unreachable(); /* Doesn't make sense for picking. */
635  break;
636  }
637  }
638 
639  changed = true;
640  }
641  }
642 
643  /* update node order */
644  if (changed || found) {
645  bool active_texture_changed = false;
646  bool viewer_node_changed = false;
647  if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) {
648  viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER;
649  ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed);
650  }
651  else if (node != nullptr && node->type == GEO_NODE_VIEWER) {
653  }
655  node_sort(*snode.edittree);
656  if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) ||
657  viewer_node_changed) {
659  }
660 
662  }
663 
664  return changed || found;
665 }
666 
668 {
669  /* get settings from RNA properties for operator */
670  int mval[2];
671  RNA_int_get_array(op->ptr, "location", mval);
672 
673  struct SelectPick_Params params = {};
675 
676  /* perform the select */
677  const bool changed = node_mouse_select(C, op, mval, &params);
678 
679  if (changed) {
681  }
682  /* Nothing selected, just passthrough. */
684 }
685 
686 static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
687 {
688  RNA_int_set_array(op->ptr, "location", event->mval);
689 
690  const int retval = node_select_exec(C, op);
691 
692  return WM_operator_flag_only_pass_through_on_press(retval, event);
693 }
694 
696 {
697  PropertyRNA *prop;
698 
699  /* identifiers */
700  ot->name = "Select";
701  ot->idname = "NODE_OT_select";
702  ot->description = "Select the node under the cursor";
703 
704  /* api callbacks */
709 
710  /* flags */
712 
713  /* properties */
715 
716  prop = RNA_def_int_vector(ot->srna,
717  "location",
718  2,
719  nullptr,
720  INT_MIN,
721  INT_MAX,
722  "Location",
723  "Mouse location",
724  INT_MIN,
725  INT_MAX);
727 
728  RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", "");
729 }
730 
733 /* -------------------------------------------------------------------- */
738 {
739  SpaceNode &snode = *CTX_wm_space_node(C);
740  bNodeTree &node_tree = *snode.edittree;
741  const ARegion &region = *CTX_wm_region(C);
742  rctf rectf;
743 
745  UI_view2d_region_to_view_rctf(&region.v2d, &rectf, &rectf);
746 
747  const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode");
748  const bool select = (sel_op != SEL_OP_SUB);
751  }
752 
753  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
754  bool is_inside = false;
755 
756  switch (node->type) {
757  case NODE_FRAME: {
758  /* Frame nodes are selectable by their borders (including their whole rect - as for other
759  * nodes - would prevent selection of other nodes inside that frame. */
760  const rctf frame_inside = node_frame_rect_inside(*node);
761  if (BLI_rctf_isect(&rectf, &node->totr, nullptr) &&
762  !BLI_rctf_inside_rctf(&frame_inside, &rectf)) {
764  is_inside = true;
765  }
766  break;
767  }
768  default: {
769  is_inside = BLI_rctf_isect(&rectf, &node->totr, nullptr);
770  break;
771  }
772  }
773 
774  if (is_inside) {
776  }
777  }
778 
780 
782 
783  return OPERATOR_FINISHED;
784 }
785 
786 static int node_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
787 {
788  const bool tweak = RNA_boolean_get(op->ptr, "tweak");
789 
790  if (tweak && is_event_over_node_or_socket(C, event)) {
792  }
793 
794  return WM_gesture_box_invoke(C, op, event);
795 }
796 
798 {
799  /* identifiers */
800  ot->name = "Box Select";
801  ot->idname = "NODE_OT_select_box";
802  ot->description = "Use box selection to select nodes";
803 
804  /* api callbacks */
809 
811 
812  /* flags */
814 
815  /* properties */
817  "tweak",
818  false,
819  "Tweak",
820  "Only activate when mouse is not over a node (useful for tweak gesture)");
821 
824 }
825 
828 /* -------------------------------------------------------------------- */
833 {
834  SpaceNode *snode = CTX_wm_space_node(C);
835  ARegion *region = CTX_wm_region(C);
836  bNode *node;
837 
838  int x, y, radius;
839  float offset[2];
840 
841  float zoom = (float)(BLI_rcti_size_x(&region->winrct)) /
842  (float)(BLI_rctf_size_x(&region->v2d.cur));
843 
845  (eSelectOp)RNA_enum_get(op->ptr, "mode"),
847  const bool select = (sel_op != SEL_OP_SUB);
850  }
851 
852  /* get operator properties */
853  x = RNA_int_get(op->ptr, "x");
854  y = RNA_int_get(op->ptr, "y");
855  radius = RNA_int_get(op->ptr, "radius");
856 
857  UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
858 
859  for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) {
860  switch (node->type) {
861  case NODE_FRAME: {
862  /* Frame nodes are selectable by their borders (including their whole rect - as for other
863  * nodes - would prevent selection of _only_ other nodes inside that frame. */
864  rctf frame_inside = node_frame_rect_inside(*node);
865  const float radius_adjusted = (float)radius / zoom;
866  BLI_rctf_pad(&frame_inside, -2.0f * radius_adjusted, -2.0f * radius_adjusted);
867  if (BLI_rctf_isect_circle(&node->totr, offset, radius_adjusted) &&
868  !BLI_rctf_isect_circle(&frame_inside, offset, radius_adjusted)) {
870  }
871  break;
872  }
873  default: {
874  if (BLI_rctf_isect_circle(&node->totr, offset, radius / zoom)) {
876  }
877  break;
878  }
879  }
880  }
881 
883 
884  return OPERATOR_FINISHED;
885 }
886 
888 {
889  /* identifiers */
890  ot->name = "Circle Select";
891  ot->idname = "NODE_OT_select_circle";
892  ot->description = "Use circle selection to select nodes";
893 
894  /* api callbacks */
900 
901  /* flags */
903 
904  /* properties */
907 }
908 
911 /* -------------------------------------------------------------------- */
915 static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
916 {
917  const bool tweak = RNA_boolean_get(op->ptr, "tweak");
918 
919  if (tweak && is_event_over_node_or_socket(C, event)) {
921  }
922 
923  return WM_gesture_lasso_invoke(C, op, event);
924 }
925 
927  const int mcoords[][2],
928  const int mcoords_len,
930 {
931  SpaceNode *snode = CTX_wm_space_node(C);
932  bNode *node;
933 
934  ARegion *region = CTX_wm_region(C);
935 
936  rcti rect;
937  bool changed = false;
938 
939  const bool select = (sel_op != SEL_OP_SUB);
942  changed = true;
943  }
944 
945  /* get rectangle from operator */
946  BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
947 
948  /* do actual selection */
949  for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) {
950 
951  if (select && (node->flag & NODE_SELECT)) {
952  continue;
953  }
954 
955  switch (node->type) {
956  case NODE_FRAME: {
957  /* Frame nodes are selectable by their borders (including their whole rect - as for other
958  * nodes - would prevent selection of other nodes inside that frame. */
959  rctf rectf;
960  BLI_rctf_rcti_copy(&rectf, &rect);
961  UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
962  const rctf frame_inside = node_frame_rect_inside(*node);
963  if (BLI_rctf_isect(&rectf, &node->totr, nullptr) &&
964  !BLI_rctf_inside_rctf(&frame_inside, &rectf)) {
966  changed = true;
967  }
968  break;
969  }
970  default: {
971  int screen_co[2];
972  const float cent[2] = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)};
973 
974  /* marker in screen coords */
976  &region->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) &&
977  BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
978  BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) {
980  changed = true;
981  }
982  break;
983  }
984  }
985  }
986 
987  if (changed) {
989  }
990 
991  return changed;
992 }
993 
995 {
996  int mcoords_len;
997  const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
998 
999  if (mcoords) {
1000  const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode");
1001 
1002  do_lasso_select_node(C, mcoords, mcoords_len, sel_op);
1003 
1004  MEM_freeN((void *)mcoords);
1005 
1006  return OPERATOR_FINISHED;
1007  }
1008  return OPERATOR_PASS_THROUGH;
1009 }
1010 
1012 {
1013  /* identifiers */
1014  ot->name = "Lasso Select";
1015  ot->description = "Select nodes using lasso selection";
1016  ot->idname = "NODE_OT_select_lasso";
1017 
1018  /* api callbacks */
1024 
1025  /* flags */
1027 
1028  /* properties */
1030  "tweak",
1031  false,
1032  "Tweak",
1033  "Only activate when mouse is not over a node (useful for tweak gesture)");
1034 
1037 }
1038 
1041 /* -------------------------------------------------------------------- */
1046 {
1047  SpaceNode &snode = *CTX_wm_space_node(C);
1048  ListBase *node_lb = &snode.edittree->nodes;
1049  int action = RNA_enum_get(op->ptr, "action");
1050 
1051  node_select_all(node_lb, action);
1052 
1053  node_sort(*snode.edittree);
1054 
1056  return OPERATOR_FINISHED;
1057 }
1058 
1060 {
1061  /* identifiers */
1062  ot->name = "(De)select All";
1063  ot->description = "(De)select all nodes";
1064  ot->idname = "NODE_OT_select_all";
1065 
1066  /* api callbacks */
1069 
1070  /* flags */
1072 
1074 }
1075 
1078 /* -------------------------------------------------------------------- */
1083 {
1084  SpaceNode &snode = *CTX_wm_space_node(C);
1085  bNodeTree &node_tree = *snode.edittree;
1086 
1087  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
1088  node->flag &= ~NODE_TEST;
1089  }
1090 
1091  LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
1092  if (nodeLinkIsHidden(link)) {
1093  continue;
1094  }
1095  if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) {
1096  link->tonode->flag |= NODE_TEST;
1097  }
1098  }
1099 
1100  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
1101  if (node->flag & NODE_TEST) {
1102  nodeSetSelected(node, true);
1103  }
1104  }
1105 
1107 
1109  return OPERATOR_FINISHED;
1110 }
1111 
1113 {
1114  /* identifiers */
1115  ot->name = "Select Linked To";
1116  ot->description = "Select nodes linked to the selected ones";
1117  ot->idname = "NODE_OT_select_linked_to";
1118 
1119  /* api callbacks */
1122 
1123  /* flags */
1125 }
1126 
1129 /* -------------------------------------------------------------------- */
1134 {
1135  SpaceNode &snode = *CTX_wm_space_node(C);
1136  bNodeTree &node_tree = *snode.edittree;
1137 
1138  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
1139  node->flag &= ~NODE_TEST;
1140  }
1141 
1142  LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
1143  if (nodeLinkIsHidden(link)) {
1144  continue;
1145  }
1146  if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) {
1147  link->fromnode->flag |= NODE_TEST;
1148  }
1149  }
1150 
1151  LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
1152  if (node->flag & NODE_TEST) {
1153  nodeSetSelected(node, true);
1154  }
1155  }
1156 
1158 
1160  return OPERATOR_FINISHED;
1161 }
1162 
1164 {
1165  /* identifiers */
1166  ot->name = "Select Linked From";
1167  ot->description = "Select nodes linked from the selected ones";
1168  ot->idname = "NODE_OT_select_linked_from";
1169 
1170  /* api callbacks */
1173 
1174  /* flags */
1176 }
1177 
1180 /* -------------------------------------------------------------------- */
1185 {
1186  SpaceNode *snode = CTX_wm_space_node(C);
1187  ARegion *region = CTX_wm_region(C);
1188  bNode **node_array;
1189  bNode *active = nodeGetActive(snode->edittree);
1190  int totnodes;
1191  const bool revert = RNA_boolean_get(op->ptr, "prev");
1192  const bool same_type = true;
1193 
1194  ntreeGetDependencyList(snode->edittree, &node_array, &totnodes);
1195 
1196  if (totnodes > 1) {
1197  int a;
1198 
1199  for (a = 0; a < totnodes; a++) {
1200  if (node_array[a] == active) {
1201  break;
1202  }
1203  }
1204 
1205  if (same_type) {
1206  bNode *node = nullptr;
1207 
1208  while (node == nullptr) {
1209  if (revert) {
1210  a--;
1211  }
1212  else {
1213  a++;
1214  }
1215 
1216  if (a < 0 || a >= totnodes) {
1217  break;
1218  }
1219 
1220  node = node_array[a];
1221 
1222  if (node->type == active->type) {
1223  break;
1224  }
1225  node = nullptr;
1226  }
1227  if (node) {
1228  active = node;
1229  }
1230  }
1231  else {
1232  if (revert) {
1233  if (a == 0) {
1234  active = node_array[totnodes - 1];
1235  }
1236  else {
1237  active = node_array[a - 1];
1238  }
1239  }
1240  else {
1241  if (a == totnodes - 1) {
1242  active = node_array[0];
1243  }
1244  else {
1245  active = node_array[a + 1];
1246  }
1247  }
1248  }
1249 
1251 
1252  /* is note outside view? */
1253  if (active->totr.xmax < region->v2d.cur.xmin || active->totr.xmin > region->v2d.cur.xmax ||
1254  active->totr.ymax < region->v2d.cur.ymin || active->totr.ymin > region->v2d.cur.ymax) {
1255  const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
1256  space_node_view_flag(*C, *snode, *region, NODE_SELECT, smooth_viewtx);
1257  }
1258  }
1259 
1260  if (node_array) {
1261  MEM_freeN(node_array);
1262  }
1263 
1264  return OPERATOR_FINISHED;
1265 }
1266 
1268 {
1269  /* identifiers */
1270  ot->name = "Activate Same Type Next/Prev";
1271  ot->description = "Activate and view same node type, step by step";
1272  ot->idname = "NODE_OT_select_same_type_step";
1273 
1274  /* api callbacks */
1277 
1278  /* flags */
1280 
1281  RNA_def_boolean(ot->srna, "prev", false, "Previous", "");
1282 }
1283 
1286 /* -------------------------------------------------------------------- */
1290 static void node_find_create_label(const bNode *node, char *str, int maxlen)
1291 {
1292  if (node->label[0]) {
1293  BLI_snprintf(str, maxlen, "%s (%s)", node->name, node->label);
1294  }
1295  else {
1296  BLI_strncpy(str, node->name, maxlen);
1297  }
1298 }
1299 
1300 /* Generic search invoke. */
1301 static void node_find_update_fn(const struct bContext *C,
1302  void *UNUSED(arg),
1303  const char *str,
1304  uiSearchItems *items,
1305  const bool UNUSED(is_first))
1306 {
1307  SpaceNode *snode = CTX_wm_space_node(C);
1308 
1309  StringSearch *search = BLI_string_search_new();
1310 
1311  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1312  char name[256];
1313  node_find_create_label(node, name, ARRAY_SIZE(name));
1314  BLI_string_search_add(search, name, node, 0);
1315  }
1316 
1317  bNode **filtered_nodes;
1318  int filtered_amount = BLI_string_search_query(search, str, (void ***)&filtered_nodes);
1319 
1320  for (int i = 0; i < filtered_amount; i++) {
1321  bNode *node = filtered_nodes[i];
1322  char name[256];
1323  node_find_create_label(node, name, ARRAY_SIZE(name));
1324  if (!UI_search_item_add(items, name, node, ICON_NONE, 0, 0)) {
1325  break;
1326  }
1327  }
1328 
1329  MEM_freeN(filtered_nodes);
1330  BLI_string_search_free(search);
1331 }
1332 
1333 static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2)
1334 {
1335  SpaceNode *snode = CTX_wm_space_node(C);
1336  bNode *active = (bNode *)arg2;
1337 
1338  if (active) {
1339  ARegion *region = CTX_wm_region(C);
1341 
1342  /* is note outside view? */
1343  if (active->totr.xmax < region->v2d.cur.xmin || active->totr.xmin > region->v2d.cur.xmax ||
1344  active->totr.ymax < region->v2d.cur.ymin || active->totr.ymin > region->v2d.cur.ymax) {
1345  space_node_view_flag(*C, *snode, *region, NODE_SELECT, U.smooth_viewtx);
1346  }
1347  }
1348 }
1349 
1350 static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op)
1351 {
1352  static char search[256] = "";
1353  uiBlock *block;
1354  uiBut *but;
1355  wmOperator *op = (wmOperator *)arg_op;
1356 
1357  block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
1360 
1361  but = uiDefSearchBut(block,
1362  search,
1363  0,
1364  ICON_VIEWZOOM,
1365  sizeof(search),
1366  10,
1367  10,
1369  UI_UNIT_Y,
1370  0,
1371  0,
1372  "");
1374  but, nullptr, node_find_update_fn, op->type, false, nullptr, node_find_exec_fn, nullptr);
1376 
1377  /* fake button, it holds space for search items */
1378  uiDefBut(block,
1380  0,
1381  "",
1382  10,
1383  10 - UI_searchbox_size_y(),
1386  nullptr,
1387  0,
1388  0,
1389  0,
1390  0,
1391  nullptr);
1392 
1393  /* Move it downwards, mouse over button. */
1394  std::array<int, 2> bounds_offset = {0, -UI_UNIT_Y};
1395  UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, bounds_offset.data());
1396 
1397  return block;
1398 }
1399 
1400 static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1401 {
1402  UI_popup_block_invoke(C, node_find_menu, op, nullptr);
1403  return OPERATOR_CANCELLED;
1404 }
1405 
1407 {
1408  /* identifiers */
1409  ot->name = "Find Node";
1410  ot->description = "Search for a node by name and focus and select it";
1411  ot->idname = "NODE_OT_find_node";
1412 
1413  /* api callbacks */
1416 
1417  /* flags */
1419 
1420  RNA_def_boolean(ot->srna, "prev", false, "Previous", "");
1421 }
1422 
1425 } // namespace blender::ed::space_node
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:878
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define NODE_REROUTE
Definition: BKE_node.h:986
bool nodeLinkIsHidden(const struct bNodeLink *link)
#define GEO_NODE_VIEWER
Definition: BKE_node.h:1413
struct bNode * nodeGetActive(struct bNodeTree *ntree)
Definition: node.cc:3601
void nodeSetSelected(struct bNode *node, bool select)
Definition: node.cc:3615
#define NODE_FRAME
Definition: BKE_node.h:985
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len)
Definition: node.cc:4095
struct bScreen * BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
bool BLI_lasso_is_point_inside(const int mcoords[][2], unsigned int mcoords_len, int sx, int sy, int error_value)
Definition: lasso_2d.c:38
void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], unsigned int mcoords_len)
Definition: lasso_2d.c:15
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:348
MINLINE bool compare_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:181
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition: BLI_rect.h:177
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
bool BLI_rctf_isect_circle(const struct rctf *rect, const float xy[2], float radius)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
void BLI_rctf_pad(struct rctf *rect, float pad_x, float pad_y)
Definition: rct.c:615
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b)
Definition: rct.c:192
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_string_search_add(StringSearch *search, const char *str, void *user_data, int weight)
void BLI_string_search_free(StringSearch *search)
StringSearch * BLI_string_search_new(void)
int BLI_string_search_query(StringSearch *search, const char *query, void ***r_data)
size_t size_t size_t BLI_str_partition_ex_utf8(const char *str, const char *end, const unsigned int delim[], const char **sep, const char **suf, bool from_right) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
#define STREQLEN(a, b, n)
#define UNUSED(x)
#define STREQ(a, b)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
#define NODE_TEST
#define NODE_DO_OUTPUT
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
#define NODE_SELECT
#define NODE_ACTIVE
@ SPACE_VIEW3D
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
void ED_node_set_active(struct Main *bmain, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bool *r_active_texture_changed)
Definition: node_edit.cc:659
void ED_node_set_active_viewer_key(struct SpaceNode *snode)
Definition: space_node.cc:187
bool ED_operator_node_active(struct bContext *C)
Definition: screen_ops.c:307
eSelectOp ED_select_op_modal(eSelectOp sel_op, bool is_first)
Definition: select_utils.c:59
void ED_select_pick_params_from_operator(struct PointerRNA *ptr, struct SelectPick_Params *params) ATTR_NONNULL(1
#define SEL_OP_USE_PRE_DESELECT(sel_op)
const char * ED_select_circle_get_name(struct wmOperatorType *ot, PointerRNA *ptr)
@ SEL_DESELECT
void const char * ED_select_pick_get_name(struct wmOperatorType *ot, PointerRNA *ptr)
eSelectOp
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
@ SEL_OP_AND
@ SEL_OP_XOR
void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain, struct SpaceNode *snode, struct bNode *node)
bool ED_view3d_has_workbench_in_texture_color(const struct Scene *scene, const struct Object *ob, const struct View3D *v3d)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_Y
int UI_searchbox_size_x(void)
@ UI_BUT_ACTIVATE_ON_INIT
Definition: UI_interface.h:219
@ UI_EMBOSS
Definition: UI_interface.h:108
void UI_block_theme_style_set(uiBlock *block, char theme_style)
Definition: interface.cc:3634
int UI_searchbox_size_y(void)
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:4806
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition: interface.cc:598
@ UI_BLOCK_THEME_STYLE_POPUP
Definition: UI_interface.h:770
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, bool free_arg, uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
Definition: interface.cc:6242
bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int but_flag, uint8_t name_prefix_offset)
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip)
Definition: interface.cc:6217
void UI_block_flag_enable(uiBlock *block, int flag)
Definition: interface.cc:5848
@ UI_BTYPE_LABEL
Definition: UI_interface.h:354
void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free)
void UI_but_flag_enable(uiBut *but, int flag)
Definition: interface.cc:5858
@ UI_BLOCK_SEARCH_MENU
Definition: UI_interface.h:147
@ UI_BLOCK_LOOP
Definition: UI_interface.h:135
@ UI_BLOCK_MOVEMOUSE_QUIT
Definition: UI_interface.h:143
void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
bool UI_view2d_view_to_region_clip(const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL()
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_NODE
Definition: WM_types.h:344
#define NA_SELECTED
Definition: WM_types.h:528
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
OperationNode * node
Scene scene
bNodeTree * ntree
#define str(s)
static bool is_inside(int x, int y, int cols, int rows)
Definition: filesel.c:706
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_global KernelShaderEvalInput * input
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
bool active
all scheduled work for the GPU.
static bool has_workbench_in_texture_color(const wmWindowManager *wm, const Scene *scene, const Object *ob)
Definition: node_select.cc:62
static bool node_select_grouped_type(bNodeTree &node_tree, bNode &node_act)
Definition: node_select.cc:325
void node_sort(bNodeTree &ntree)
Definition: node_draw.cc:215
bool node_or_socket_isect_event(bContext *C, const wmEvent *event)
Definition: node_select.cc:103
void NODE_OT_select_circle(wmOperatorType *ot)
Definition: node_select.cc:887
static uiBlock * node_find_menu(bContext *C, ARegion *region, void *arg_op)
static int node_box_select_exec(bContext *C, wmOperator *op)
Definition: node_select.cc:737
static int node_lasso_select_exec(bContext *C, wmOperator *op)
Definition: node_select.cc:994
static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
bool space_node_view_flag(bContext &C, SpaceNode &snode, ARegion &region, int node_flag, int smooth_viewtx)
Definition: node_view.cc:48
static bool do_lasso_select_node(bContext *C, const int mcoords[][2], const int mcoords_len, eSelectOp sel_op)
Definition: node_select.cc:926
void NODE_OT_find_node(wmOperatorType *ot)
void NODE_OT_select_lasso(wmOperatorType *ot)
void node_socket_select(bNode *node, bNodeSocket &sock)
Definition: node_select.cc:203
void NODE_OT_select(wmOperatorType *ot)
Definition: node_select.cc:695
static bool node_select_grouped_name(bNodeTree &node_tree, bNode &node_act, const bool from_right)
Definition: node_select.cc:353
static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static void node_socket_toggle(bNode *node, bNodeSocket &sock, bool deselect_node)
Definition: node_select.cc:240
static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event)
Definition: node_select.cc:190
void node_socket_deselect(bNode *node, bNodeSocket &sock, bool deselect_node)
Definition: node_select.cc:213
static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: node_select.cc:915
static bool node_mouse_select(bContext *C, wmOperator *op, const int mval[2], struct SelectPick_Params *params)
Definition: node_select.cc:515
void node_select_all(ListBase *lb, int action)
Definition: node_edit.cc:1488
void node_deselect_all(SpaceNode &snode)
Definition: node_select.cc:250
static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mouse)
Definition: node_select.cc:174
void NODE_OT_select_grouped(wmOperatorType *ot)
Definition: node_select.cc:447
void node_deselect_all_output_sockets(SpaceNode &snode, bool deselect_nodes)
Definition: node_select.cc:287
static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse)
Definition: node_select.cc:108
static int node_circleselect_exec(bContext *C, wmOperator *op)
Definition: node_select.cc:832
static int node_select_all_exec(bContext *C, wmOperator *op)
static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2)
static void node_find_update_fn(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items, const bool UNUSED(is_first))
void NODE_OT_select_linked_from(wmOperatorType *ot)
bool node_find_indicated_socket(SpaceNode &snode, bNode **nodep, bNodeSocket **sockp, const float2 &cursor, const eNodeSocketInOut in_out)
Definition: node_edit.cc:1226
static int node_select_grouped_exec(bContext *C, wmOperator *op)
Definition: node_select.cc:400
static int node_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: node_select.cc:786
void NODE_OT_select_same_type_step(wmOperatorType *ot)
void node_select_single(bContext &C, bNode &node)
Definition: node_select.cc:487
static bool node_select_grouped_color(bNodeTree &node_tree, bNode &node_act)
Definition: node_select.cc:339
void NODE_OT_select_linked_to(wmOperatorType *ot)
static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
static bNode * node_under_mouse_select(bNodeTree &ntree, int mx, int my)
Definition: node_select.cc:121
static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: node_select.cc:686
rctf node_frame_rect_inside(const bNode &node)
Definition: node_select.cc:88
static bNode * node_under_mouse_tweak(bNodeTree &ntree, const float2 &mouse)
Definition: node_select.cc:143
void node_deselect_all_input_sockets(SpaceNode &snode, bool deselect_nodes)
Definition: node_select.cc:257
void NODE_OT_select_box(wmOperatorType *ot)
Definition: node_select.cc:797
void NODE_OT_select_all(wmOperatorType *ot)
static int node_select_exec(bContext *C, wmOperator *op)
Definition: node_select.cc:667
static void node_find_create_label(const bNode *node, char *str, int maxlen)
static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
T distance(const T &a, const T &b)
static const EnumPropertyItem prop_select_grouped_types[]
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
Definition: rna_access.c:4945
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
Definition: rna_access.c:4933
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifier, int len, const int *default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3623
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct bNodeTree * edittree
struct bNodeSocket * next
ListBase nodes
float color[3]
char name[64]
short type
struct bNode * next
ListBase outputs
ListBase areabase
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int mval[2]
Definition: WM_types.h:684
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
const char *(* get_name)(struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:960
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
bool WM_gesture_is_modal_first(const wmGesture *gesture)
Definition: wm_gesture.c:108
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const int(* WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *r_mcoords_len))[2]
void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
void WM_operator_properties_gesture_circle(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect)
void WM_operator_properties_mouse_select(wmOperatorType *ot)
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)
int WM_operator_smooth_viewtx_get(const wmOperator *op)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))