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:
Diffstat (limited to 'source/blender/editors/space_node/node_select.cc')
-rw-r--r--source/blender/editors/space_node/node_select.cc248
1 files changed, 143 insertions, 105 deletions
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index 9d73156edab..d93b205b1b7 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -22,6 +22,7 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_node_runtime.hh"
#include "BKE_workspace.h"
#include "ED_node.h" /* own include */
@@ -48,7 +49,7 @@
namespace blender::ed::space_node {
-static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event);
+static bool is_event_over_node_or_socket(const bContext &C, const wmEvent &event);
/**
* Function to detect if there is a visible view3d that uses workbench in texture mode.
@@ -100,17 +101,17 @@ rctf node_frame_rect_inside(const bNode &node)
return frame_inside;
}
-bool node_or_socket_isect_event(bContext *C, const wmEvent *event)
+bool node_or_socket_isect_event(const bContext &C, const wmEvent &event)
{
return is_event_over_node_or_socket(C, event);
}
-static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse)
+static bool node_frame_select_isect_mouse(const bNode &node, const float2 &mouse)
{
/* Frame nodes are selectable by their borders (including their whole rect - as for other nodes -
* would prevent e.g. box selection of nodes inside that frame). */
- const rctf frame_inside = node_frame_rect_inside(*node);
- if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y) &&
+ const rctf frame_inside = node_frame_rect_inside(node);
+ if (BLI_rctf_isect_pt(&node.totr, mouse.x, mouse.y) &&
!BLI_rctf_isect_pt(&frame_inside, mouse.x, mouse.y)) {
return true;
}
@@ -118,19 +119,18 @@ static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse)
return false;
}
-static bNode *node_under_mouse_select(bNodeTree &ntree, int mx, int my)
+static bNode *node_under_mouse_select(bNodeTree &ntree, const float2 mouse)
{
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) {
switch (node->type) {
case NODE_FRAME: {
- const float2 mouse{(float)mx, (float)my};
- if (node_frame_select_isect_mouse(node, mouse)) {
+ if (node_frame_select_isect_mouse(*node, mouse)) {
return node;
}
break;
}
default: {
- if (BLI_rctf_isect_pt(&node->totr, mx, my)) {
+ if (BLI_rctf_isect_pt(&node->totr, int(mouse.x), int(mouse.y))) {
return node;
}
break;
@@ -140,35 +140,32 @@ static bNode *node_under_mouse_select(bNodeTree &ntree, int mx, int my)
return nullptr;
}
-static bNode *node_under_mouse_tweak(bNodeTree &ntree, const float2 &mouse)
+static bool node_under_mouse_tweak(const bNodeTree &ntree, const float2 &mouse)
{
- using namespace blender::math;
-
- LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) {
+ LISTBASE_FOREACH_BACKWARD (const bNode *, node, &ntree.nodes) {
switch (node->type) {
case NODE_REROUTE: {
- bNodeSocket *socket = (bNodeSocket *)node->inputs.first;
- const float2 location{socket->locx, socket->locy};
- if (distance(mouse, location) < 24.0f) {
- return node;
+ const float2 location = node_to_view(*node, {node->locx, node->locy});
+ if (math::distance(mouse, location) < 24.0f) {
+ return true;
}
break;
}
case NODE_FRAME: {
- if (node_frame_select_isect_mouse(node, mouse)) {
- return node;
+ if (node_frame_select_isect_mouse(*node, mouse)) {
+ return true;
}
break;
}
default: {
if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y)) {
- return node;
+ return true;
}
break;
}
}
}
- return nullptr;
+ return false;
}
static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mouse)
@@ -187,17 +184,17 @@ static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mous
return false;
}
-static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event)
+static bool is_event_over_node_or_socket(const bContext &C, const wmEvent &event)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *region = CTX_wm_region(C);
- float2 mouse;
+ SpaceNode &snode = *CTX_wm_space_node(&C);
+ ARegion &region = *CTX_wm_region(&C);
- int mval[2];
- WM_event_drag_start_mval(event, region, mval);
+ int2 mval;
+ WM_event_drag_start_mval(&event, &region, mval);
- UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &mouse.x, &mouse.y);
- return is_position_over_node_or_socket(*snode, mouse);
+ float2 mouse;
+ UI_view2d_region_to_view(&region.v2d, mval.x, mval.y, &mouse.x, &mouse.y);
+ return is_position_over_node_or_socket(snode, mouse);
}
void node_socket_select(bNode *node, bNodeSocket &sock)
@@ -314,6 +311,17 @@ void node_deselect_all_output_sockets(SpaceNode &snode, const bool deselect_node
}
}
+Set<bNode *> get_selected_nodes(bNodeTree &node_tree)
+{
+ Set<bNode *> selected_nodes;
+ for (bNode *node : node_tree.all_nodes()) {
+ if (node->flag & NODE_SELECT) {
+ selected_nodes.add(node);
+ }
+ }
+ return selected_nodes;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -412,9 +420,7 @@ static int node_select_grouped_exec(bContext *C, wmOperator *op)
const int type = RNA_enum_get(op->ptr, "type");
if (!extend) {
- LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
- nodeSetSelected(node, false);
- }
+ node_deselect_all(snode);
}
nodeSetSelected(node_act, true);
@@ -514,8 +520,8 @@ void node_select_single(bContext &C, bNode &node)
static bool node_mouse_select(bContext *C,
wmOperator *op,
- const int mval[2],
- struct SelectPick_Params *params)
+ const int2 mval,
+ SelectPick_Params *params)
{
Main &bmain = *CTX_data_main(C);
SpaceNode &snode = *CTX_wm_space_node(C);
@@ -526,7 +532,6 @@ static bool node_mouse_select(bContext *C,
bNode *node, *tnode;
bNodeSocket *sock = nullptr;
bNodeSocket *tsock;
- float cursor[2];
/* always do socket_select when extending selection. */
const bool socket_select = (params->sel_op == SEL_OP_XOR) ||
@@ -536,7 +541,8 @@ static bool node_mouse_select(bContext *C,
bool node_was_selected = false;
/* get mouse coordinates in view2d space */
- UI_view2d_region_to_view(&region.v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
+ float2 cursor;
+ UI_view2d_region_to_view(&region.v2d, mval.x, mval.y, &cursor.x, &cursor.y);
/* first do socket selection, these generally overlap with nodes. */
if (socket_select) {
@@ -593,7 +599,7 @@ static bool node_mouse_select(bContext *C,
if (!sock) {
/* find the closest visible node */
- node = node_under_mouse_select(*snode.edittree, (int)cursor[0], (int)cursor[1]);
+ node = node_under_mouse_select(*snode.edittree, cursor);
found = (node != nullptr);
node_was_selected = node && (node->flag & SELECT);
@@ -603,9 +609,7 @@ static bool node_mouse_select(bContext *C,
}
else if (found || params->deselect_all) {
/* Deselect everything. */
- for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
- }
+ node_deselect_all(snode);
changed = true;
}
}
@@ -640,37 +644,38 @@ static bool node_mouse_select(bContext *C,
}
}
- /* update node order */
- if (changed || found) {
- bool active_texture_changed = false;
- bool viewer_node_changed = false;
- if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) {
- viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER;
- ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed);
- }
- else if (node != nullptr && node->type == GEO_NODE_VIEWER) {
- ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node);
- }
- ED_node_set_active_viewer_key(&snode);
- node_sort(*snode.edittree);
- if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) ||
- viewer_node_changed) {
- DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE);
- }
+ if (!(changed || found)) {
+ return false;
+ }
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr);
+ bool active_texture_changed = false;
+ bool viewer_node_changed = false;
+ if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) {
+ viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER;
+ ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed);
+ }
+ else if (node != nullptr && node->type == GEO_NODE_VIEWER) {
+ ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node);
}
+ ED_node_set_active_viewer_key(&snode);
+ node_sort(*snode.edittree);
+ if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) ||
+ viewer_node_changed) {
+ DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr);
- return changed || found;
+ return true;
}
static int node_select_exec(bContext *C, wmOperator *op)
{
/* get settings from RNA properties for operator */
- int mval[2];
+ int2 mval;
RNA_int_get_array(op->ptr, "location", mval);
- struct SelectPick_Params params = {};
+ SelectPick_Params params = {};
ED_select_pick_params_from_operator(op->ptr, &params);
/* perform the select */
@@ -747,7 +752,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op)
const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- node_select_all(&node_tree.nodes, SEL_DESELECT);
+ node_deselect_all(snode);
}
LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
@@ -787,7 +792,7 @@ static int node_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *ev
{
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- if (tweak && is_event_over_node_or_socket(C, event)) {
+ if (tweak && is_event_over_node_or_socket(*C, *event)) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
@@ -836,7 +841,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
bNode *node;
int x, y, radius;
- float offset[2];
+ float2 offset;
float zoom = (float)(BLI_rcti_size_x(&region->winrct)) /
(float)(BLI_rctf_size_x(&region->v2d.cur));
@@ -846,7 +851,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
WM_gesture_is_modal_first((const wmGesture *)op->customdata));
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- node_select_all(&snode->edittree->nodes, SEL_DESELECT);
+ node_deselect_all(*snode);
}
/* get operator properties */
@@ -854,7 +859,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
y = RNA_int_get(op->ptr, "y");
radius = RNA_int_get(op->ptr, "radius");
- UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
+ UI_view2d_region_to_view(&region->v2d, x, y, &offset.x, &offset.y);
for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) {
switch (node->type) {
@@ -916,7 +921,7 @@ static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent *
{
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- if (tweak && is_event_over_node_or_socket(C, event)) {
+ if (tweak && is_event_over_node_or_socket(*C, *event)) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
@@ -938,7 +943,7 @@ static bool do_lasso_select_node(bContext *C,
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- node_select_all(&snode->edittree->nodes, SEL_DESELECT);
+ node_deselect_all(*snode);
changed = true;
}
@@ -968,14 +973,14 @@ static bool do_lasso_select_node(bContext *C,
break;
}
default: {
- int screen_co[2];
- const float cent[2] = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)};
+ int2 screen_co;
+ const float2 center = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)};
/* marker in screen coords */
if (UI_view2d_view_to_region_clip(
- &region->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) &&
- BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
- BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) {
+ &region->v2d, center.x, center.y, &screen_co.x, &screen_co.y) &&
+ BLI_rcti_isect_pt(&rect, screen_co.x, screen_co.y) &&
+ BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co.x, screen_co.y, INT_MAX)) {
nodeSetSelected(node, select);
changed = true;
}
@@ -1042,13 +1047,48 @@ void NODE_OT_select_lasso(wmOperatorType *ot)
/** \name (De)select All Operator
* \{ */
+static bool any_node_selected(const bNodeTree &node_tree)
+{
+ for (const bNode *node : node_tree.all_nodes()) {
+ if (node->flag & NODE_SELECT) {
+ return true;
+ }
+ }
+ return false;
+}
+
static int node_select_all_exec(bContext *C, wmOperator *op)
{
SpaceNode &snode = *CTX_wm_space_node(C);
- ListBase *node_lb = &snode.edittree->nodes;
+ bNodeTree &node_tree = *snode.edittree;
+
+ node_tree.ensure_topology_cache();
+
int action = RNA_enum_get(op->ptr, "action");
+ if (action == SEL_TOGGLE) {
+ if (any_node_selected(node_tree)) {
+ action = SEL_DESELECT;
+ }
+ else {
+ action = SEL_SELECT;
+ }
+ }
- node_select_all(node_lb, action);
+ switch (action) {
+ case SEL_SELECT:
+ for (bNode *node : node_tree.all_nodes()) {
+ nodeSetSelected(node, true);
+ }
+ break;
+ case SEL_DESELECT:
+ node_deselect_all(snode);
+ break;
+ case SEL_INVERT:
+ for (bNode *node : node_tree.all_nodes()) {
+ nodeSetSelected(node, !(node->flag & SELECT));
+ }
+ break;
+ }
node_sort(*snode.edittree);
@@ -1084,22 +1124,21 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode &snode = *CTX_wm_space_node(C);
bNodeTree &node_tree = *snode.edittree;
- LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
- node->flag &= ~NODE_TEST;
- }
+ node_tree.ensure_topology_cache();
- LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
- if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) {
- link->tonode->flag |= NODE_TEST;
- }
- }
+ Set<bNode *> initial_selection = get_selected_nodes(node_tree);
- LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
- if (node->flag & NODE_TEST) {
- nodeSetSelected(node, true);
+ for (bNode *node : initial_selection) {
+ for (bNodeSocket *output_socket : node->output_sockets()) {
+ if (!output_socket->is_available()) {
+ continue;
+ }
+ for (bNodeSocket *input_socket : output_socket->directly_linked_sockets()) {
+ if (!input_socket->is_available()) {
+ continue;
+ }
+ nodeSetSelected(&input_socket->owner_node(), true);
+ }
}
}
@@ -1135,22 +1174,21 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
SpaceNode &snode = *CTX_wm_space_node(C);
bNodeTree &node_tree = *snode.edittree;
- LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
- node->flag &= ~NODE_TEST;
- }
+ node_tree.ensure_topology_cache();
- LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
- if (nodeLinkIsHidden(link)) {
- continue;
- }
- if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) {
- link->fromnode->flag |= NODE_TEST;
- }
- }
+ Set<bNode *> initial_selection = get_selected_nodes(node_tree);
- LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) {
- if (node->flag & NODE_TEST) {
- nodeSetSelected(node, true);
+ for (bNode *node : initial_selection) {
+ for (bNodeSocket *input_socket : node->input_sockets()) {
+ if (!input_socket->is_available()) {
+ continue;
+ }
+ for (bNodeSocket *output_socket : input_socket->directly_linked_sockets()) {
+ if (!output_socket->is_available()) {
+ continue;
+ }
+ nodeSetSelected(&output_socket->owner_node(), true);
+ }
}
}
@@ -1298,7 +1336,7 @@ static void node_find_create_label(const bNode *node, char *str, int maxlen)
}
/* Generic search invoke. */
-static void node_find_update_fn(const struct bContext *C,
+static void node_find_update_fn(const bContext *C,
void *UNUSED(arg),
const char *str,
uiSearchItems *items,
@@ -1330,7 +1368,7 @@ static void node_find_update_fn(const struct bContext *C,
BLI_string_search_free(search);
}
-static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2)
+static void node_find_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *active = (bNode *)arg2;