From 338c1060d5d7b6a8bd3ec5632f543738de4c103c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 5 Dec 2021 16:45:41 -0500 Subject: Cleanup: Remove unnecessary node type callbacks for drawing Currently there are a few callbacks on `bNodeType` that do the same thing for every node type except reroutes and frame nodes. Having a callback for basic things complicates code and makes it harder to understand, and reroutes and frames are special cases in larger way. Arguably frame nodes shouldn't even be drawn like regular nodes, given that it adds a case of O(N^2) looping through all nodes. "Unrolling" the callbacks makes it easier to see what's happening, and therefore easier to optimize. Differential Revision: https://developer.blender.org/D13463 --- source/blender/editors/space_node/node_draw.cc | 120 +++++++++++++++++++------ 1 file changed, 91 insertions(+), 29 deletions(-) (limited to 'source/blender/editors/space_node/node_draw.cc') diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index fd07e6e0aba..c2187d1d479 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -663,26 +663,6 @@ static void node_update_hidden(bNode &node) node.totr.ymax); } -void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node) -{ - if (node->flag & NODE_HIDDEN) { - node_update_hidden(*node); - } - else { - node_update_basis(*C, *ntree, *node); - } -} - -int node_select_area_default(bNode *node, int x, int y) -{ - return BLI_rctf_isect_pt(&node->totr, x, y); -} - -int node_tweak_area_default(bNode *node, int x, int y) -{ - return BLI_rctf_isect_pt(&node->totr, x, y); -} - int node_get_colorid(bNode &node) { switch (node.typeinfo->nclass) { @@ -2323,7 +2303,7 @@ void node_set_cursor(wmWindow &win, SpaceNode &snode, const float2 &cursor) } } if (node) { - NodeResizeDirection dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]); + NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]); wmcursor = node_get_resize_cursor(dir); } @@ -2346,13 +2326,6 @@ void node_draw_default(const bContext *C, } } -static void node_update(const bContext &C, bNodeTree &ntree, bNode &node) -{ - if (node.typeinfo->draw_nodetype_prepare) { - node.typeinfo->draw_nodetype_prepare(&C, &ntree, &node); - } -} - static void count_multi_input_socket_links(bNodeTree &ntree, SpaceNode &snode) { Map counts; @@ -2381,6 +2354,82 @@ static void count_multi_input_socket_links(bNodeTree &ntree, SpaceNode &snode) } } +/* XXX Does a bounding box update by iterating over all children. + * Not ideal to do this in every draw call, but doing as transform callback doesn't work, + * since the child node totr rects are not updated properly at that point. + */ +static void frame_node_prepare_for_draw(bNodeTree &ntree, bNode &node) +{ + const float margin = 1.5f * U.widget_unit; + NodeFrame *data = (NodeFrame *)node.storage; + + /* init rect from current frame size */ + rctf rect; + node_to_view(node, node.offsetx, node.offsety, &rect.xmin, &rect.ymax); + node_to_view( + node, node.offsetx + node.width, node.offsety - node.height, &rect.xmax, &rect.ymin); + + /* frame can be resized manually only if shrinking is disabled or no children are attached */ + data->flag |= NODE_FRAME_RESIZEABLE; + /* for shrinking bbox, initialize the rect from first child node */ + bool bbinit = (data->flag & NODE_FRAME_SHRINK); + /* fit bounding box to all children */ + LISTBASE_FOREACH (bNode *, tnode, &ntree.nodes) { + if (tnode->parent != &node) { + continue; + } + + /* add margin to node rect */ + rctf noderect = tnode->totr; + noderect.xmin -= margin; + noderect.xmax += margin; + noderect.ymin -= margin; + noderect.ymax += margin; + + /* first child initializes frame */ + if (bbinit) { + bbinit = false; + rect = noderect; + data->flag &= ~NODE_FRAME_RESIZEABLE; + } + else { + BLI_rctf_union(&rect, &noderect); + } + } + + /* now adjust the frame size from view-space bounding box */ + node_from_view(node, rect.xmin, rect.ymax, &node.offsetx, &node.offsety); + float xmax, ymax; + node_from_view(node, rect.xmax, rect.ymin, &xmax, &ymax); + node.width = xmax - node.offsetx; + node.height = -ymax + node.offsety; + + node.totr = rect; +} + +static void reroute_node_prepare_for_draw(bNode &node) +{ + /* get "global" coords */ + float locx, locy; + node_to_view(node, 0.0f, 0.0f, &locx, &locy); + + /* reroute node has exactly one input and one output, both in the same place */ + bNodeSocket *nsock = (bNodeSocket *)node.outputs.first; + nsock->locx = locx; + nsock->locy = locy; + + nsock = (bNodeSocket *)node.inputs.first; + nsock->locx = locx; + nsock->locy = locy; + + const float size = 8.0f; + node.width = size * 2; + node.totr.xmin = locx - size; + node.totr.xmax = locx + size; + node.totr.ymax = locy + size; + node.totr.ymin = locy - size; +} + void node_update_nodetree(const bContext &C, bNodeTree &ntree) { /* Make sure socket "used" tags are correct, for displaying value buttons. */ @@ -2391,7 +2440,20 @@ void node_update_nodetree(const bContext &C, bNodeTree &ntree) /* Update nodes front to back, so children sizes get updated before parents. */ LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { - node_update(C, ntree, *node); + if (node->type == NODE_FRAME) { + frame_node_prepare_for_draw(ntree, *node); + } + else if (node->type == NODE_REROUTE) { + reroute_node_prepare_for_draw(*node); + } + else { + if (node->flag & NODE_HIDDEN) { + node_update_hidden(*node); + } + else { + node_update_basis(C, ntree, *node); + } + } } } -- cgit v1.2.3