Fix #112490: Always draw socket icons in "hidden" nodes

In #112326 the socket visibility functions were updated to take the
open/closed state of panels into account for visibility of the socket
icon. However, in "hidden" (collapsed) nodes the panels should be
ignored entirely, drawing all sockets on the root level. This requires
looking at the node flags to determine socket icon visibility, so a
simple method of `bNodeSocket` is not sufficient.

This patch moves the more complex visibility queries for sockets into
`bNode`, where both node and socket flags can be accessed. These should
be used for actual visibility rather than the plain flag accessors on
`bNodeSocket`.

Renamed `is_visible_or_panel_closed` back to just `is_visible`, the
other `is_visible` variant is now integrated in `bNode::is_socket_drawn`.

Pull Request: https://projects.blender.org/blender/blender/pulls/112520
This commit is contained in:
Lukas Tönne
2023-09-19 10:47:21 +02:00
parent 75748f9d7a
commit 78315faf8f
7 changed files with 43 additions and 33 deletions

View File

@@ -704,6 +704,16 @@ inline blender::Span<bNodeLink> bNode::internal_links() const
return this->runtime->internal_links;
}
inline bool bNode::is_socket_drawn(const bNodeSocket &socket) const
{
return socket.is_visible();
}
inline bool bNode::is_socket_icon_drawn(const bNodeSocket &socket) const
{
return socket.is_visible() && (this->flag & NODE_HIDDEN || !socket.is_panel_collapsed());
}
inline blender::Span<bNode *> bNode::direct_children_in_frame() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
@@ -794,14 +804,9 @@ inline bool bNodeSocket::is_panel_collapsed() const
return (this->flag & SOCK_PANEL_COLLAPSED) != 0;
}
inline bool bNodeSocket::is_visible_or_panel_collapsed() const
{
return !this->is_hidden() && this->is_available();
}
inline bool bNodeSocket::is_visible() const
{
return this->is_visible_or_panel_collapsed() && !this->is_panel_collapsed();
return !this->is_hidden() && this->is_available();
}
inline bNode &bNodeSocket::owner_node()

View File

@@ -2756,8 +2756,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
bool nodeLinkIsHidden(const bNodeLink *link)
{
return !(link->fromsock->is_visible_or_panel_collapsed() &&
link->tosock->is_visible_or_panel_collapsed());
return !(link->fromsock->is_visible() && link->tosock->is_visible());
}
namespace blender::bke {

View File

@@ -407,8 +407,8 @@ static bool node_update_basis_socket(const bContext &C,
const int &locx,
int &locy)
{
if ((!input_socket || !input_socket->is_visible_or_panel_collapsed()) &&
(!output_socket || !output_socket->is_visible_or_panel_collapsed()))
if ((!input_socket || !input_socket->is_visible()) &&
(!output_socket || !output_socket->is_visible()))
{
return false;
}
@@ -701,7 +701,7 @@ static void node_update_basis_from_declaration(
}
else {
/* Space between items. */
if (!is_first && item.input->is_visible_or_panel_collapsed()) {
if (!is_first && item.input->is_visible()) {
locy -= NODE_SOCKDY;
}
}
@@ -714,7 +714,7 @@ static void node_update_basis_from_declaration(
}
else {
/* Space between items. */
if (!is_first && item.output->is_visible_or_panel_collapsed()) {
if (!is_first && item.output->is_visible()) {
locy -= NODE_SOCKDY;
}
}
@@ -865,12 +865,12 @@ static void node_update_hidden(bNode &node, uiBlock &block)
/* Calculate minimal radius. */
for (const bNodeSocket *socket : node.input_sockets()) {
if (socket->is_visible_or_panel_collapsed()) {
if (socket->is_visible()) {
totin++;
}
}
for (const bNodeSocket *socket : node.output_sockets()) {
if (socket->is_visible_or_panel_collapsed()) {
if (socket->is_visible()) {
totout++;
}
}
@@ -891,7 +891,7 @@ static void node_update_hidden(bNode &node, uiBlock &block)
float drad = rad;
for (bNodeSocket *socket : node.output_sockets()) {
if (socket->is_visible_or_panel_collapsed()) {
if (socket->is_visible()) {
/* Round the socket location to stop it from jiggling. */
socket->runtime->location = {
round(node.runtime->totr.xmax - hiddenrad + sinf(rad) * hiddenrad),
@@ -904,7 +904,7 @@ static void node_update_hidden(bNode &node, uiBlock &block)
rad = drad = -float(M_PI) / (1.0f + float(totin));
for (bNodeSocket *socket : node.input_sockets()) {
if (socket->is_visible_or_panel_collapsed()) {
if (socket->is_visible()) {
/* Round the socket location to stop it from jiggling. */
socket->runtime->location = {
round(node.runtime->totr.xmin + hiddenrad + sinf(rad) * hiddenrad),
@@ -1751,7 +1751,8 @@ static void node_draw_sockets(const View2D &v2d,
/* Socket inputs. */
int selected_input_len = 0;
for (const bNodeSocket *sock : node.input_sockets()) {
if (!sock->is_visible()) {
/* In "hidden" nodes: draw sockets even when panels are collapsed. */
if (!node.is_socket_icon_drawn(*sock)) {
continue;
}
if (select_all || (sock->flag & SELECT)) {
@@ -1774,7 +1775,8 @@ static void node_draw_sockets(const View2D &v2d,
int selected_output_len = 0;
if (draw_outputs) {
for (const bNodeSocket *sock : node.output_sockets()) {
if (!sock->is_visible()) {
/* In "hidden" nodes: draw sockets even when panels are collapsed. */
if (!node.is_socket_icon_drawn(*sock)) {
continue;
}
if (select_all || (sock->flag & SELECT)) {
@@ -1802,7 +1804,7 @@ static void node_draw_sockets(const View2D &v2d,
if (selected_input_len) {
/* Socket inputs. */
for (const bNodeSocket *sock : node.input_sockets()) {
if (!sock->is_visible()) {
if (!node.is_socket_icon_drawn(*sock)) {
continue;
}
/* Don't draw multi-input sockets here since they are drawn in a different batch. */
@@ -1831,7 +1833,7 @@ static void node_draw_sockets(const View2D &v2d,
if (selected_output_len) {
/* Socket outputs. */
for (const bNodeSocket *sock : node.output_sockets()) {
if (!sock->is_visible()) {
if (!node.is_socket_icon_drawn(*sock)) {
continue;
}
if (select_all || (sock->flag & SELECT)) {
@@ -1864,7 +1866,7 @@ static void node_draw_sockets(const View2D &v2d,
/* Draw multi-input sockets after the others because they are drawn with `UI_draw_roundbox`
* rather than with `GL_POINT`. */
for (const bNodeSocket *socket : node.input_sockets()) {
if (!socket->is_visible()) {
if (!node.is_socket_icon_drawn(*socket)) {
continue;
}
if (!(socket->flag & SOCK_MULTI_INPUT)) {

View File

@@ -1191,7 +1191,7 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
if (in_out & SOCK_IN) {
for (bNodeSocket *sock : node.input_sockets()) {
if (sock->is_visible()) {
if (node.is_socket_icon_drawn(*sock)) {
const float2 location = sock->runtime->location;
if (sock->flag & SOCK_MULTI_INPUT && !(node.flag & NODE_HIDDEN)) {
if (cursor_isect_multi_input_socket(cursor, *sock)) {
@@ -1210,7 +1210,7 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode,
}
if (in_out & SOCK_OUT) {
for (bNodeSocket *sock : node.output_sockets()) {
if (sock->is_visible()) {
if (node.is_socket_icon_drawn(*sock)) {
const float2 location = sock->runtime->location;
if (BLI_rctf_isect_pt(&rect, location.x, location.y)) {
if (!socket_is_occluded(location, node, snode)) {

View File

@@ -170,7 +170,7 @@ static void pick_input_link_by_link_intersect(const bContext &C,
static bool socket_is_available(bNodeTree * /*ntree*/, bNodeSocket *sock, const bool allow_used)
{
if (!sock->is_visible_or_panel_collapsed()) {
if (!sock->is_visible()) {
return false;
}
@@ -414,9 +414,9 @@ namespace viewer_linking {
* \{ */
/* Depending on the node tree type, different socket types are supported by viewer nodes. */
static bool socket_can_be_viewed(const bNodeSocket &socket)
static bool socket_can_be_viewed(const bNode &node, const bNodeSocket &socket)
{
if (!socket.is_visible()) {
if (!node.is_socket_icon_drawn(socket)) {
return false;
}
if (STREQ(socket.idname, "NodeSocketVirtual")) {
@@ -530,7 +530,7 @@ static bNodeSocket *determine_socket_to_view(bNode &node_to_view)
int last_linked_data_socket_index = -1;
bool has_linked_geometry_socket = false;
for (bNodeSocket *socket : node_to_view.output_sockets()) {
if (!socket_can_be_viewed(*socket)) {
if (!socket_can_be_viewed(node_to_view, *socket)) {
continue;
}
for (bNodeLink *link : socket->directly_linked_links()) {
@@ -554,7 +554,7 @@ static bNodeSocket *determine_socket_to_view(bNode &node_to_view)
if (last_linked_data_socket_index == -1 && !has_linked_geometry_socket) {
/* Return the first socket that can be viewed. */
for (bNodeSocket *socket : node_to_view.output_sockets()) {
if (socket_can_be_viewed(*socket)) {
if (socket_can_be_viewed(node_to_view, *socket)) {
return socket;
}
}
@@ -566,7 +566,7 @@ static bNodeSocket *determine_socket_to_view(bNode &node_to_view)
for (const int offset : IndexRange(1, tot_outputs)) {
const int index = (last_linked_data_socket_index + offset) % tot_outputs;
bNodeSocket &output_socket = node_to_view.output_socket(index);
if (!socket_can_be_viewed(output_socket)) {
if (!socket_can_be_viewed(node_to_view, output_socket)) {
continue;
}
if (has_linked_geometry_socket && output_socket.type == SOCK_GEOMETRY) {
@@ -2264,7 +2264,7 @@ bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_
int index;
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
const nodes::SocketDeclaration &socket_decl = *socket_decls[index];
if (!socket->is_visible_or_panel_collapsed()) {
if (!socket->is_visible()) {
continue;
}
if (socket_decl.is_default_link_socket) {
@@ -2285,7 +2285,7 @@ bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_
/* Try all priorities, starting from 'highest'. */
for (int priority = maxpriority; priority >= 0; priority--) {
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
if (!!sock->is_visible_or_panel_collapsed() && priority == get_main_socket_priority(sock)) {
if (!!sock->is_visible() && priority == get_main_socket_priority(sock)) {
return sock;
}
}

View File

@@ -189,7 +189,6 @@ typedef struct bNodeSocket {
bool is_hidden() const;
bool is_available() const;
bool is_panel_collapsed() const;
bool is_visible_or_panel_collapsed() const;
bool is_visible() const;
bool is_multi_input() const;
bool is_input() const;
@@ -428,6 +427,11 @@ typedef struct bNode {
/** A span containing all internal links when the node is muted. */
blender::Span<bNodeLink> internal_links() const;
/* True if the socket is visible and has a valid location. The icon may not be visible. */
bool is_socket_drawn(const bNodeSocket &socket) const;
/* True if the socket is drawn and the icon is visible. */
bool is_socket_icon_drawn(const bNodeSocket &socket) const;
/* The following methods are only available when #bNodeTree.ensure_topology_cache has been
* called. */

View File

@@ -124,7 +124,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
/* If the source node has a geometry socket, connect it to the new viewer node as well. */
LISTBASE_FOREACH (bNodeSocket *, socket, &params.node.outputs) {
if (socket->type == SOCK_GEOMETRY && socket->is_visible_or_panel_collapsed()) {
if (socket->type == SOCK_GEOMETRY && socket->is_visible()) {
nodeAddLink(&params.node_tree,
&params.node,
socket,