Fix #105720: crash when adding viewer node #105877

Merged
Jacques Lucke merged 3 commits from JacquesLucke/blender:remove-socket-locations-array into blender-v3.5-release 2023-03-19 07:03:13 +01:00
7 changed files with 75 additions and 158 deletions

View File

@ -151,13 +151,6 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
Vector<bNode *> root_frames; Vector<bNode *> root_frames;
Vector<bNodeSocket *> interface_inputs; Vector<bNodeSocket *> interface_inputs;
Vector<bNodeSocket *> interface_outputs; Vector<bNodeSocket *> interface_outputs;
/**
* The location of all sockets in the tree, calculated while drawing the nodes.
* Indexed with #bNodeSocket::index_in_tree(). In the node tree's "world space"
* (the same as #bNode::runtime::totr).
*/
Vector<float2> all_socket_locations;
}; };
/** /**
@ -183,6 +176,13 @@ class bNodeSocketRuntime : NonCopyable, NonMovable {
*/ */
short total_inputs = 0; short total_inputs = 0;
/**
* The location of the socket in the tree, calculated while drawing the nodes and invalid if the
* node tree hasn't been drawn yet. In the node tree's "world space" (the same as
* #bNode::runtime::totr).
*/
float2 location;
/** Only valid when #topology_cache_is_dirty is false. */ /** Only valid when #topology_cache_is_dirty is false. */
Vector<bNodeLink *> directly_linked_links; Vector<bNodeLink *> directly_linked_links;
Vector<bNodeSocket *> directly_linked_sockets; Vector<bNodeSocket *> directly_linked_sockets;

View File

@ -1589,12 +1589,11 @@ void draw_nodespace_back_pix(const bContext &C,
GPU_matrix_pop(); GPU_matrix_pop();
} }
static float2 socket_link_connection_location(const Span<float2> socket_locations, static float2 socket_link_connection_location(const bNode &node,
const bNode &node,
const bNodeSocket &socket, const bNodeSocket &socket,
const bNodeLink &link) const bNodeLink &link)
{ {
const float2 socket_location = socket_locations[socket.index_in_tree()]; const float2 socket_location = socket.runtime->location;
if (socket.is_multi_input() && socket.is_input() && !(node.flag & NODE_HIDDEN)) { if (socket.is_multi_input() && socket.is_input() && !(node.flag & NODE_HIDDEN)) {
return node_link_calculate_multi_input_position( return node_link_calculate_multi_input_position(
socket_location, link.multi_input_socket_index, socket.runtime->total_inputs); socket_location, link.multi_input_socket_index, socket.runtime->total_inputs);
@ -1628,13 +1627,11 @@ static void calculate_inner_link_bezier_points(std::array<float2, 4> &points)
} }
} }
static std::array<float2, 4> node_link_bezier_points(const Span<float2> socket_locations, static std::array<float2, 4> node_link_bezier_points(const bNodeLink &link)
const bNodeLink &link)
{ {
std::array<float2, 4> points; std::array<float2, 4> points;
points[0] = socket_link_connection_location( points[0] = socket_link_connection_location(*link.fromnode, *link.fromsock, link);
socket_locations, *link.fromnode, *link.fromsock, link); points[3] = socket_link_connection_location(*link.tonode, *link.tosock, link);
points[3] = socket_link_connection_location(socket_locations, *link.tonode, *link.tosock, link);
calculate_inner_link_bezier_points(points); calculate_inner_link_bezier_points(points);
return points; return points;
} }
@ -1650,11 +1647,10 @@ static bool node_link_draw_is_visible(const View2D &v2d, const std::array<float2
return true; return true;
} }
void node_link_bezier_points_evaluated(const Span<float2> socket_locations, void node_link_bezier_points_evaluated(const bNodeLink &link,
const bNodeLink &link,
std::array<float2, NODE_LINK_RESOL + 1> &coords) std::array<float2, NODE_LINK_RESOL + 1> &coords)
{ {
const std::array<float2, 4> points = node_link_bezier_points(socket_locations, link); const std::array<float2, 4> points = node_link_bezier_points(link);
/* The extra +1 in size is required by these functions and would be removed ideally. */ /* The extra +1 in size is required by these functions and would be removed ideally. */
BKE_curve_forward_diff_bezier(points[0].x, BKE_curve_forward_diff_bezier(points[0].x,
@ -2041,9 +2037,7 @@ static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C,
const bNodeTree &node_tree = *snode.edittree; const bNodeTree &node_tree = *snode.edittree;
draw_config.dim_factor = selected ? 1.0f : draw_config.dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link);
node_link_dim_factor(
node_tree.runtime->all_socket_locations, v2d, link);
bTheme *btheme = UI_GetTheme(); bTheme *btheme = UI_GetTheme();
draw_config.dash_alpha = btheme->space_node.dash_alpha; draw_config.dash_alpha = btheme->space_node.dash_alpha;
@ -2167,8 +2161,7 @@ void node_draw_link_bezier(const bContext &C,
const bool selected) const bool selected)
{ {
const bNodeTree &node_tree = *snode.edittree; const bNodeTree &node_tree = *snode.edittree;
const std::array<float2, 4> points = node_link_bezier_points( const std::array<float2, 4> points = node_link_bezier_points(link);
node_tree.runtime->all_socket_locations, link);
if (!node_link_draw_is_visible(v2d, points)) { if (!node_link_draw_is_visible(v2d, points)) {
return; return;
} }
@ -2231,15 +2224,10 @@ static std::array<float2, 4> node_link_bezier_points_dragged(const SpaceNode &sn
const float2 cursor = snode.runtime->cursor * UI_DPI_FAC; const float2 cursor = snode.runtime->cursor * UI_DPI_FAC;
std::array<float2, 4> points; std::array<float2, 4> points;
points[0] = link.fromsock ? points[0] = link.fromsock ?
socket_link_connection_location(node_tree.runtime->all_socket_locations, socket_link_connection_location(*link.fromnode, *link.fromsock, link) :
*link.fromnode,
*link.fromsock,
link) :
cursor;
points[3] = link.tosock ?
socket_link_connection_location(
node_tree.runtime->all_socket_locations, *link.tonode, *link.tosock, link) :
cursor; cursor;
points[3] = link.tosock ? socket_link_connection_location(*link.tonode, *link.tosock, link) :
cursor;
calculate_inner_link_bezier_points(points); calculate_inner_link_bezier_points(points);
return points; return points;
} }

View File

@ -109,12 +109,10 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location)
/** \name Add Reroute Operator /** \name Add Reroute Operator
* \{ */ * \{ */
std::optional<float2> link_path_intersection(const Span<float2> socket_locations, std::optional<float2> link_path_intersection(const bNodeLink &link, const Span<float2> path)
const bNodeLink &link,
const Span<float2> path)
{ {
std::array<float2, NODE_LINK_RESOL + 1> coords; std::array<float2, NODE_LINK_RESOL + 1> coords;
node_link_bezier_points_evaluated(socket_locations, link, coords); node_link_bezier_points_evaluated(link, coords);
for (const int i : path.index_range().drop_back(1)) { for (const int i : path.index_range().drop_back(1)) {
for (const int j : IndexRange(NODE_LINK_RESOL)) { for (const int j : IndexRange(NODE_LINK_RESOL)) {
@ -140,7 +138,6 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
const ARegion &region = *CTX_wm_region(C); const ARegion &region = *CTX_wm_region(C);
SpaceNode &snode = *CTX_wm_space_node(C); SpaceNode &snode = *CTX_wm_space_node(C);
bNodeTree &ntree = *snode.edittree; bNodeTree &ntree = *snode.edittree;
const Span<float2> socket_locations = ntree.runtime->all_socket_locations;
Vector<float2> path; Vector<float2> path;
RNA_BEGIN (op->ptr, itemptr, "path") { RNA_BEGIN (op->ptr, itemptr, "path") {
@ -172,10 +169,10 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
Map<bNodeSocket *, RerouteCutsForSocket> cuts_per_socket; Map<bNodeSocket *, RerouteCutsForSocket> cuts_per_socket;
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue; continue;
} }
const std::optional<float2> cut = link_path_intersection(socket_locations, *link, path); const std::optional<float2> cut = link_path_intersection(*link, path);
if (!cut) { if (!cut) {
continue; continue;
} }

View File

@ -268,9 +268,6 @@ void node_sort(bNodeTree &ntree)
ntree.runtime->nodes_by_id.add_new(sort_nodes[i]); ntree.runtime->nodes_by_id.add_new(sort_nodes[i]);
sort_nodes[i]->runtime->index_in_tree = i; sort_nodes[i]->runtime->index_in_tree = i;
} }
/* Nodes have been reordered; the socket locations are invalid until the node tree is redrawn. */
ntree.runtime->all_socket_locations.clear();
} }
static Array<uiBlock *> node_uiblocks_init(const bContext &C, const Span<bNode *> nodes) static Array<uiBlock *> node_uiblocks_init(const bContext &C, const Span<bNode *> nodes)
@ -321,8 +318,7 @@ static void node_update_basis(const bContext &C,
const TreeDrawContext & /*tree_draw_ctx*/, const TreeDrawContext & /*tree_draw_ctx*/,
bNodeTree &ntree, bNodeTree &ntree,
bNode &node, bNode &node,
uiBlock &block, uiBlock &block)
MutableSpan<float2> socket_locations)
{ {
PointerRNA nodeptr; PointerRNA nodeptr;
RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr); RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr);
@ -392,8 +388,7 @@ static void node_update_basis(const bContext &C,
buty = min_ii(buty, dy - NODE_DY); buty = min_ii(buty, dy - NODE_DY);
/* Round the socket location to stop it from jiggling. */ /* Round the socket location to stop it from jiggling. */
socket_locations[socket->index_in_tree()] = float2(round(loc.x + NODE_WIDTH(node)), socket->runtime->location = float2(round(loc.x + NODE_WIDTH(node)), round(dy - NODE_DYS));
round(dy - NODE_DYS));
dy = buty; dy = buty;
if (socket->next) { if (socket->next) {
@ -525,7 +520,7 @@ static void node_update_basis(const bContext &C,
buty = min_ii(buty, dy - NODE_DY); buty = min_ii(buty, dy - NODE_DY);
/* Round the socket vertical position to stop it from jiggling. */ /* Round the socket vertical position to stop it from jiggling. */
socket_locations[socket->index_in_tree()] = float2(loc.x, round(dy - NODE_DYS)); socket->runtime->location = float2(loc.x, round(dy - NODE_DYS));
dy = buty - multi_input_socket_offset * 0.5; dy = buty - multi_input_socket_offset * 0.5;
if (socket->next) { if (socket->next) {
@ -555,7 +550,7 @@ static void node_update_basis(const bContext &C,
/** /**
* Based on settings in node, sets drawing rect info. * Based on settings in node, sets drawing rect info.
*/ */
static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan<float2> socket_locations) static void node_update_hidden(bNode &node, uiBlock &block)
{ {
int totin = 0, totout = 0; int totin = 0, totout = 0;
@ -595,7 +590,7 @@ static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan<float2>
for (bNodeSocket *socket : node.output_sockets()) { for (bNodeSocket *socket : node.output_sockets()) {
if (socket->is_visible()) { if (socket->is_visible()) {
/* Round the socket location to stop it from jiggling. */ /* Round the socket location to stop it from jiggling. */
socket_locations[socket->index_in_tree()] = { socket->runtime->location = {
round(node.runtime->totr.xmax - hiddenrad + sinf(rad) * hiddenrad), round(node.runtime->totr.xmax - hiddenrad + sinf(rad) * hiddenrad),
round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)}; round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)};
rad += drad; rad += drad;
@ -608,7 +603,7 @@ static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan<float2>
for (bNodeSocket *socket : node.input_sockets()) { for (bNodeSocket *socket : node.input_sockets()) {
if (socket->is_visible()) { if (socket->is_visible()) {
/* Round the socket location to stop it from jiggling. */ /* Round the socket location to stop it from jiggling. */
socket_locations[socket->index_in_tree()] = { socket->runtime->location = {
round(node.runtime->totr.xmin + hiddenrad + sinf(rad) * hiddenrad), round(node.runtime->totr.xmin + hiddenrad + sinf(rad) * hiddenrad),
round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)}; round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)};
rad += drad; rad += drad;
@ -1188,7 +1183,6 @@ void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, ui
static void node_socket_draw_nested(const bContext &C, static void node_socket_draw_nested(const bContext &C,
const bNodeTree &ntree, const bNodeTree &ntree,
const Span<float2> socket_locations,
PointerRNA &node_ptr, PointerRNA &node_ptr,
uiBlock &block, uiBlock &block,
const bNodeSocket &sock, const bNodeSocket &sock,
@ -1200,7 +1194,7 @@ static void node_socket_draw_nested(const bContext &C,
const float size, const float size,
const bool selected) const bool selected)
{ {
const float2 location = socket_locations[sock.index_in_tree()]; const float2 location = sock.runtime->location;
float color[4]; float color[4];
float outline_color[4]; float outline_color[4];
@ -1402,7 +1396,6 @@ static void node_draw_shadow(const SpaceNode &snode,
static void node_draw_sockets(const View2D &v2d, static void node_draw_sockets(const View2D &v2d,
const bContext &C, const bContext &C,
const bNodeTree &ntree, const bNodeTree &ntree,
const Span<float2> socket_locations,
const bNode &node, const bNode &node,
uiBlock &block, uiBlock &block,
const bool draw_outputs, const bool draw_outputs,
@ -1462,7 +1455,6 @@ static void node_draw_sockets(const View2D &v2d,
node_socket_draw_nested(C, node_socket_draw_nested(C,
ntree, ntree,
socket_locations,
node_ptr, node_ptr,
block, block,
*sock, *sock,
@ -1489,7 +1481,6 @@ static void node_draw_sockets(const View2D &v2d,
node_socket_draw_nested(C, node_socket_draw_nested(C,
ntree, ntree,
socket_locations,
node_ptr, node_ptr,
block, block,
*sock, *sock,
@ -1528,7 +1519,6 @@ static void node_draw_sockets(const View2D &v2d,
if (select_all || (sock->flag & SELECT)) { if (select_all || (sock->flag & SELECT)) {
node_socket_draw_nested(C, node_socket_draw_nested(C,
ntree, ntree,
socket_locations,
node_ptr, node_ptr,
block, block,
*sock, *sock,
@ -1556,7 +1546,6 @@ static void node_draw_sockets(const View2D &v2d,
if (select_all || (sock->flag & SELECT)) { if (select_all || (sock->flag & SELECT)) {
node_socket_draw_nested(C, node_socket_draw_nested(C,
ntree, ntree,
socket_locations,
node_ptr, node_ptr,
block, block,
*sock, *sock,
@ -1602,7 +1591,7 @@ static void node_draw_sockets(const View2D &v2d,
node_socket_color_get(C, ntree, node_ptr, *socket, color); node_socket_color_get(C, ntree, node_ptr, *socket, color);
node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color); node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color);
const float2 location = socket_locations[socket->index_in_tree()]; const float2 location = socket->runtime->location;
node_socket_draw_multi_input(color, outline_color, width, height, location); node_socket_draw_multi_input(color, outline_color, width, height, location);
} }
} }
@ -2109,7 +2098,6 @@ static void node_draw_basis(const bContext &C,
const View2D &v2d, const View2D &v2d,
const SpaceNode &snode, const SpaceNode &snode,
bNodeTree &ntree, bNodeTree &ntree,
const Span<float2> socket_locations,
const bNode &node, const bNode &node,
uiBlock &block, uiBlock &block,
bNodeInstanceKey key) bNodeInstanceKey key)
@ -2410,7 +2398,7 @@ static void node_draw_basis(const bContext &C,
/* Skip slow socket drawing if zoom is small. */ /* Skip slow socket drawing if zoom is small. */
if (scale > 0.2f) { if (scale > 0.2f) {
node_draw_sockets(v2d, C, ntree, socket_locations, node, block, true, false); node_draw_sockets(v2d, C, ntree, node, block, true, false);
} }
/* Preview. */ /* Preview. */
@ -2434,7 +2422,6 @@ static void node_draw_hidden(const bContext &C,
const View2D &v2d, const View2D &v2d,
const SpaceNode &snode, const SpaceNode &snode,
bNodeTree &ntree, bNodeTree &ntree,
const Span<float2> socket_locations,
bNode &node, bNode &node,
uiBlock &block) uiBlock &block)
{ {
@ -2604,7 +2591,7 @@ static void node_draw_hidden(const bContext &C,
immUnbindProgram(); immUnbindProgram();
GPU_blend(GPU_BLEND_NONE); GPU_blend(GPU_BLEND_NONE);
node_draw_sockets(v2d, C, ntree, socket_locations, node, block, true, false); node_draw_sockets(v2d, C, ntree, node, block, true, false);
UI_block_end(&C, &block); UI_block_end(&C, &block);
UI_block_draw(&C, &block); UI_block_draw(&C, &block);
@ -2739,13 +2726,13 @@ static void frame_node_prepare_for_draw(bNode &node, Span<bNode *> nodes)
node.runtime->totr = rect; node.runtime->totr = rect;
} }
static void reroute_node_prepare_for_draw(bNode &node, MutableSpan<float2> socket_locations) static void reroute_node_prepare_for_draw(bNode &node)
{ {
const float2 loc = node_to_view(node, float2(0)); const float2 loc = node_to_view(node, float2(0));
/* Reroute node has exactly one input and one output, both in the same place. */ /* Reroute node has exactly one input and one output, both in the same place. */
socket_locations[node.input_socket(0).index_in_tree()] = loc; node.input_socket(0).runtime->location = loc;
socket_locations[node.output_socket(0).index_in_tree()] = loc; node.output_socket(0).runtime->location = loc;
const float size = 8.0f; const float size = 8.0f;
node.width = size * 2; node.width = size * 2;
@ -2759,8 +2746,7 @@ static void node_update_nodetree(const bContext &C,
TreeDrawContext &tree_draw_ctx, TreeDrawContext &tree_draw_ctx,
bNodeTree &ntree, bNodeTree &ntree,
Span<bNode *> nodes, Span<bNode *> nodes,
Span<uiBlock *> blocks, Span<uiBlock *> blocks)
MutableSpan<float2> socket_locations)
{ {
/* Make sure socket "used" tags are correct, for displaying value buttons. */ /* Make sure socket "used" tags are correct, for displaying value buttons. */
SpaceNode *snode = CTX_wm_space_node(&C); SpaceNode *snode = CTX_wm_space_node(&C);
@ -2776,14 +2762,14 @@ static void node_update_nodetree(const bContext &C,
} }
if (node.is_reroute()) { if (node.is_reroute()) {
reroute_node_prepare_for_draw(node, socket_locations); reroute_node_prepare_for_draw(node);
} }
else { else {
if (node.flag & NODE_HIDDEN) { if (node.flag & NODE_HIDDEN) {
node_update_hidden(node, block, socket_locations); node_update_hidden(node, block);
} }
else { else {
node_update_basis(C, tree_draw_ctx, ntree, node, block, socket_locations); node_update_basis(C, tree_draw_ctx, ntree, node, block);
} }
} }
} }
@ -2936,12 +2922,8 @@ static void frame_node_draw(const bContext &C,
UI_block_draw(&C, &block); UI_block_draw(&C, &block);
} }
static void reroute_node_draw(const bContext &C, static void reroute_node_draw(
ARegion &region, const bContext &C, ARegion &region, bNodeTree &ntree, const bNode &node, uiBlock &block)
bNodeTree &ntree,
const Span<float2> socket_locations,
const bNode &node,
uiBlock &block)
{ {
/* Skip if out of view. */ /* Skip if out of view. */
const rctf &rct = node.runtime->totr; const rctf &rct = node.runtime->totr;
@ -2979,8 +2961,7 @@ static void reroute_node_draw(const bContext &C,
/* Only draw input socket as they all are placed on the same position highlight /* Only draw input socket as they all are placed on the same position highlight
* if node itself is selected, since we don't display the node body separately. */ * if node itself is selected, since we don't display the node body separately. */
node_draw_sockets( node_draw_sockets(region.v2d, C, ntree, node, block, false, node.flag & SELECT);
region.v2d, C, ntree, socket_locations, node, block, false, node.flag & SELECT);
UI_block_end(&C, &block); UI_block_end(&C, &block);
UI_block_draw(&C, &block); UI_block_draw(&C, &block);
@ -2991,7 +2972,6 @@ static void node_draw(const bContext &C,
ARegion &region, ARegion &region,
const SpaceNode &snode, const SpaceNode &snode,
bNodeTree &ntree, bNodeTree &ntree,
const Span<float2> socket_locations,
bNode &node, bNode &node,
uiBlock &block, uiBlock &block,
bNodeInstanceKey key) bNodeInstanceKey key)
@ -3000,15 +2980,15 @@ static void node_draw(const bContext &C,
frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block); frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block);
} }
else if (node.is_reroute()) { else if (node.is_reroute()) {
reroute_node_draw(C, region, ntree, socket_locations, node, block); reroute_node_draw(C, region, ntree, node, block);
} }
else { else {
const View2D &v2d = region.v2d; const View2D &v2d = region.v2d;
if (node.flag & NODE_HIDDEN) { if (node.flag & NODE_HIDDEN) {
node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, socket_locations, node, block); node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, node, block);
} }
else { else {
node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, socket_locations, node, block, key); node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, node, block, key);
} }
} }
} }
@ -3020,7 +3000,6 @@ static void node_draw_nodetree(const bContext &C,
ARegion &region, ARegion &region,
SpaceNode &snode, SpaceNode &snode,
bNodeTree &ntree, bNodeTree &ntree,
const Span<float2> socket_locations,
Span<bNode *> nodes, Span<bNode *> nodes,
Span<uiBlock *> blocks, Span<uiBlock *> blocks,
bNodeInstanceKey parent_key) bNodeInstanceKey parent_key)
@ -3042,8 +3021,7 @@ static void node_draw_nodetree(const bContext &C,
} }
const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]);
node_draw( node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key);
C, tree_draw_ctx, region, snode, ntree, socket_locations, *nodes[i], *blocks[i], key);
} }
/* Node lines. */ /* Node lines. */
@ -3073,8 +3051,7 @@ static void node_draw_nodetree(const bContext &C,
} }
const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]);
node_draw( node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key);
C, tree_draw_ctx, region, snode, ntree, socket_locations, *nodes[i], *blocks[i], key);
} }
} }
@ -3181,19 +3158,9 @@ static void draw_nodetree(const bContext &C,
else if (ntree.type == NTREE_COMPOSIT) { else if (ntree.type == NTREE_COMPOSIT) {
tree_draw_ctx.used_by_realtime_compositor = realtime_compositor_is_in_use(C); tree_draw_ctx.used_by_realtime_compositor = realtime_compositor_is_in_use(C);
} }
ntree.runtime->all_socket_locations.reinitialize(ntree.all_sockets().size());
node_update_nodetree( node_update_nodetree(C, tree_draw_ctx, ntree, nodes, blocks);
C, tree_draw_ctx, ntree, nodes, blocks, ntree.runtime->all_socket_locations); node_draw_nodetree(C, tree_draw_ctx, region, *snode, ntree, nodes, blocks, parent_key);
node_draw_nodetree(C,
tree_draw_ctx,
region,
*snode,
ntree,
ntree.runtime->all_socket_locations,
nodes,
blocks,
parent_key);
} }
/** /**

View File

@ -1099,12 +1099,10 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
} }
} }
static bool cursor_isect_multi_input_socket(const Span<float2> socket_locations, static bool cursor_isect_multi_input_socket(const float2 &cursor, const bNodeSocket &socket)
const float2 &cursor,
const bNodeSocket &socket)
{ {
const float node_socket_height = node_socket_calculate_height(socket); const float node_socket_height = node_socket_calculate_height(socket);
const float2 location = socket_locations[socket.index_in_tree()]; const float2 location = socket.runtime->location;
/* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f` /* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f`
* would be the same behavior as for regular sockets. * would be the same behavior as for regular sockets.
* But keep it smaller because for multi-input socket you * But keep it smaller because for multi-input socket you
@ -1131,11 +1129,6 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
bNodeTree &node_tree = *snode.edittree; bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache(); node_tree.ensure_topology_cache();
const Span<float2> socket_locations = node_tree.runtime->all_socket_locations;
if (socket_locations.size() != node_tree.all_sockets().size()) {
/* Sockets haven't been drawn yet, e.g. when the file is currently opening. */
return nullptr;
}
const Span<bNode *> nodes = node_tree.all_nodes(); const Span<bNode *> nodes = node_tree.all_nodes();
if (nodes.is_empty()) { if (nodes.is_empty()) {
return nullptr; return nullptr;
@ -1160,9 +1153,9 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
if (in_out & SOCK_IN) { if (in_out & SOCK_IN) {
for (bNodeSocket *sock : node.input_sockets()) { for (bNodeSocket *sock : node.input_sockets()) {
if (sock->is_visible()) { if (sock->is_visible()) {
const float2 location = socket_locations[sock->index_in_tree()]; const float2 location = sock->runtime->location;
if (sock->flag & SOCK_MULTI_INPUT && !(node.flag & NODE_HIDDEN)) { if (sock->flag & SOCK_MULTI_INPUT && !(node.flag & NODE_HIDDEN)) {
if (cursor_isect_multi_input_socket(socket_locations, cursor, *sock)) { if (cursor_isect_multi_input_socket(cursor, *sock)) {
if (!socket_is_occluded(location, node, snode)) { if (!socket_is_occluded(location, node, snode)) {
return sock; return sock;
} }
@ -1179,7 +1172,7 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
if (in_out & SOCK_OUT) { if (in_out & SOCK_OUT) {
for (bNodeSocket *sock : node.output_sockets()) { for (bNodeSocket *sock : node.output_sockets()) {
if (sock->is_visible()) { if (sock->is_visible()) {
const float2 location = socket_locations[sock->index_in_tree()]; const float2 location = sock->runtime->location;
if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { if (BLI_rctf_isect_pt(&rect, location.x, location.y)) {
if (!socket_is_occluded(location, node, snode)) { if (!socket_is_occluded(location, node, snode)) {
return sock; return sock;
@ -1199,16 +1192,14 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
/** \name Node Link Dimming /** \name Node Link Dimming
* \{ */ * \{ */
float node_link_dim_factor(const Span<float2> socket_locations, float node_link_dim_factor(const View2D &v2d, const bNodeLink &link)
const View2D &v2d,
const bNodeLink &link)
{ {
if (link.fromsock == nullptr || link.tosock == nullptr) { if (link.fromsock == nullptr || link.tosock == nullptr) {
return 1.0f; return 1.0f;
} }
const float2 from = socket_locations[link.fromsock->index_in_tree()]; const float2 from = link.fromsock->runtime->location;
const float2 to = socket_locations[link.tosock->index_in_tree()]; const float2 to = link.tosock->runtime->location;
const float min_endpoint_distance = std::min( const float min_endpoint_distance = std::min(
std::max(BLI_rctf_length_x(&v2d.cur, from.x), BLI_rctf_length_y(&v2d.cur, from.y)), std::max(BLI_rctf_length_x(&v2d.cur, from.x), BLI_rctf_length_y(&v2d.cur, from.y)),
@ -1221,11 +1212,9 @@ float node_link_dim_factor(const Span<float2> socket_locations,
return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f); return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f);
} }
bool node_link_is_hidden_or_dimmed(const Span<float2> socket_locations, bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
const View2D &v2d,
const bNodeLink &link)
{ {
return nodeLinkIsHidden(&link) || node_link_dim_factor(socket_locations, v2d, link) < 0.5f; return nodeLinkIsHidden(&link) || node_link_dim_factor(v2d, link) < 0.5f;
} }
/** \} */ /** \} */

View File

@ -247,13 +247,10 @@ void node_draw_link_bezier(const bContext &C,
int th_col3, int th_col3,
bool selected); bool selected);
void node_link_bezier_points_evaluated(Span<float2> all_socket_locations, void node_link_bezier_points_evaluated(const bNodeLink &link,
const bNodeLink &link,
std::array<float2, NODE_LINK_RESOL + 1> &coords); std::array<float2, NODE_LINK_RESOL + 1> &coords);
std::optional<float2> link_path_intersection(Span<float2> socket_locations, std::optional<float2> link_path_intersection(const bNodeLink &link, Span<float2> path);
const bNodeLink &link,
Span<float2> path);
void draw_nodespace_back_pix(const bContext &C, void draw_nodespace_back_pix(const bContext &C,
ARegion &region, ARegion &region,
@ -325,12 +322,8 @@ int node_render_changed_exec(bContext *, wmOperator *);
bNodeSocket *node_find_indicated_socket(SpaceNode &snode, bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
const float2 &cursor, const float2 &cursor,
eNodeSocketInOut in_out); eNodeSocketInOut in_out);
float node_link_dim_factor(Span<float2> socket_locations, float node_link_dim_factor(const View2D &v2d, const bNodeLink &link);
const View2D &v2d, bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link);
const bNodeLink &link);
bool node_link_is_hidden_or_dimmed(Span<float2> socket_locations,
const View2D &v2d,
const bNodeLink &link);
void NODE_OT_duplicate(wmOperatorType *ot); void NODE_OT_duplicate(wmOperatorType *ot);
void NODE_OT_delete(wmOperatorType *ot); void NODE_OT_delete(wmOperatorType *ot);

View File

@ -122,10 +122,6 @@ static void pick_input_link_by_link_intersect(const bContext &C,
{ {
SpaceNode *snode = CTX_wm_space_node(&C); SpaceNode *snode = CTX_wm_space_node(&C);
bNodeTree &node_tree = *snode->edittree; bNodeTree &node_tree = *snode->edittree;
const Span<float2> socket_locations = node_tree.runtime->all_socket_locations;
if (socket_locations.is_empty()) {
return;
}
float2 drag_start; float2 drag_start;
RNA_float_get_array(op.ptr, "drag_start", drag_start); RNA_float_get_array(op.ptr, "drag_start", drag_start);
@ -140,7 +136,7 @@ static void pick_input_link_by_link_intersect(const bContext &C,
for (bNodeLink *link : socket->directly_linked_links()) { for (bNodeLink *link : socket->directly_linked_links()) {
/* Test if the cursor is near a link. */ /* Test if the cursor is near a link. */
std::array<float2, NODE_LINK_RESOL + 1> coords; std::array<float2, NODE_LINK_RESOL + 1> coords;
node_link_bezier_points_evaluated(socket_locations, *link, coords); node_link_bezier_points_evaluated(*link, coords);
for (const int i : IndexRange(coords.size() - 1)) { for (const int i : IndexRange(coords.size() - 1)) {
const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]); const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]);
@ -293,12 +289,11 @@ struct LinkAndPosition {
float2 multi_socket_position; float2 multi_socket_position;
}; };
static void sort_multi_input_socket_links_with_drag(const Span<float2> socket_locations, static void sort_multi_input_socket_links_with_drag(bNodeSocket &socket,
bNodeSocket &socket,
bNodeLink &drag_link, bNodeLink &drag_link,
const float2 &cursor) const float2 &cursor)
{ {
const float2 &socket_location = socket_locations[socket.index_in_tree()]; const float2 &socket_location = socket.runtime->location;
Vector<LinkAndPosition, 8> links; Vector<LinkAndPosition, 8> links;
for (bNodeLink *link : socket.directly_linked_links()) { for (bNodeLink *link : socket.directly_linked_links()) {
@ -646,8 +641,7 @@ static int view_socket(const bContext &C,
} }
} }
if (viewer_node == nullptr) { if (viewer_node == nullptr) {
const float2 socket_location = const float2 socket_location = bsocket_to_view.runtime->location;
btree.runtime->all_socket_locations[bsocket_to_view.index_in_tree()];
const int viewer_type = get_default_viewer_type(&C); const int viewer_type = get_default_viewer_type(&C);
const float2 location{socket_location.x / UI_DPI_FAC + 100, socket_location.y / UI_DPI_FAC}; const float2 location{socket_location.x / UI_DPI_FAC + 100, socket_location.y / UI_DPI_FAC};
viewer_node = add_static_node(C, viewer_type, location); viewer_node = add_static_node(C, viewer_type, location);
@ -1114,12 +1108,7 @@ static void node_link_cancel(bContext *C, wmOperator *op)
static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cursor) static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cursor)
{ {
SpaceNode &snode = *CTX_wm_space_node(&C); SpaceNode &snode = *CTX_wm_space_node(&C);
bNodeTree &node_tree = *snode.edittree;
bNodeLinkDrag &nldrag = *static_cast<bNodeLinkDrag *>(op.customdata); bNodeLinkDrag &nldrag = *static_cast<bNodeLinkDrag *>(op.customdata);
const Span<float2> socket_locations = node_tree.runtime->all_socket_locations;
if (socket_locations.is_empty()) {
return;
}
if (nldrag.in_out == SOCK_OUT) { if (nldrag.in_out == SOCK_OUT) {
if (bNodeSocket *tsock = node_find_indicated_socket(snode, cursor, SOCK_IN)) { if (bNodeSocket *tsock = node_find_indicated_socket(snode, cursor, SOCK_IN)) {
@ -1150,7 +1139,7 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur
continue; continue;
} }
if (tsock && tsock->is_multi_input()) { if (tsock && tsock->is_multi_input()) {
sort_multi_input_socket_links_with_drag(socket_locations, *tsock, link, cursor); sort_multi_input_socket_links_with_drag(*tsock, link, cursor);
} }
} }
} }
@ -1523,15 +1512,14 @@ static int cut_links_exec(bContext *C, wmOperator *op)
bNodeTree &node_tree = *snode.edittree; bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache(); node_tree.ensure_topology_cache();
const Span<float2> socket_locations = node_tree.runtime->all_socket_locations;
Set<bNodeLink *> links_to_remove; Set<bNodeLink *> links_to_remove;
LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue; continue;
} }
if (link_path_intersection(socket_locations, *link, path)) { if (link_path_intersection(*link, path)) {
if (!found) { if (!found) {
/* TODO(sergey): Why did we kill jobs twice? */ /* TODO(sergey): Why did we kill jobs twice? */
@ -1609,7 +1597,6 @@ static int mute_links_exec(bContext *C, wmOperator *op)
SpaceNode &snode = *CTX_wm_space_node(C); SpaceNode &snode = *CTX_wm_space_node(C);
const ARegion &region = *CTX_wm_region(C); const ARegion &region = *CTX_wm_region(C);
bNodeTree &ntree = *snode.edittree; bNodeTree &ntree = *snode.edittree;
const Span<float2> socket_locations = ntree.runtime->all_socket_locations;
Vector<float2> path; Vector<float2> path;
RNA_BEGIN (op->ptr, itemptr, "path") { RNA_BEGIN (op->ptr, itemptr, "path") {
@ -1634,10 +1621,10 @@ static int mute_links_exec(bContext *C, wmOperator *op)
Set<bNodeLink *> affected_links; Set<bNodeLink *> affected_links;
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue; continue;
} }
if (!link_path_intersection(socket_locations, *link, path)) { if (!link_path_intersection(*link, path)) {
continue; continue;
} }
affected_links.add(link); affected_links.add(link);
@ -2092,10 +2079,6 @@ void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion &region)
{ {
bNodeTree &node_tree = *snode.edittree; bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache(); node_tree.ensure_topology_cache();
const Span<float2> socket_locations = node_tree.runtime->all_socket_locations;
if (socket_locations.is_empty()) {
return;
}
node_insert_on_link_flags_clear(node_tree); node_insert_on_link_flags_clear(node_tree);
@ -2108,12 +2091,12 @@ void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion &region)
bNodeLink *selink = nullptr; bNodeLink *selink = nullptr;
float dist_best = FLT_MAX; float dist_best = FLT_MAX;
LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue; continue;
} }
std::array<float2, NODE_LINK_RESOL + 1> coords; std::array<float2, NODE_LINK_RESOL + 1> coords;
node_link_bezier_points_evaluated(socket_locations, *link, coords); node_link_bezier_points_evaluated(*link, coords);
float dist = FLT_MAX; float dist = FLT_MAX;
/* Loop over link coords to find shortest dist to upper left node edge of a intersected line /* Loop over link coords to find shortest dist to upper left node edge of a intersected line