diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2022-04-11 03:02:12 +0300 |
---|---|---|
committer | Lukas Stockner <lukas.stockner@freenet.de> | 2022-04-12 00:40:48 +0300 |
commit | 484a9146479e05946d291e9886cdf3febca6d05d (patch) | |
tree | 977dfae2383938826d27cfcf6827031f9c50ff9a /source/blender/editors/space_node/node_draw.cc | |
parent | b3525c3487ca893aac5bb8241ce154f491508224 (diff) |
UI: Add support for showing socket descriptions in tooltips
Currently, hovering over a socket itself shows no tooltip at all, while
hovering over its value field shows "Default value", which is not helpful.
This patch therefore implements socket tooltips following the proposal at
https://blender.community/c/rightclickselect/2Qgbbc/.
A lot of the basic functionality was already implemented for Geometry Nodes,
where hovering over the socket itself shows introspection info.
This patch extends this by:
- Supporting dynamic tooltips on labels, which is important for good tooltip
coverage in a socket's region of the node.
- Adding a function to setting a dynamic tooltip for an entire uiLayout, which
avoids needing to set it manually for a wide variety of socket types.
- Hiding the property label field in a tooltip when dynamic tooltip is also
provided. If really needed, this label can be restored through the dynamic
tooltip, but in all current cases the label is actually pointless anyways
since the dynamic tooltip gives more accurate and specific information.
- Adding dynamic tooltips to a socket's UI layout row if it has a description
configured, both in the Node Editor as well as in the Material Properties.
Note that the patch does not add any actual tooltip content yet, just the
infrastructure to show them. By default, sockets without a description still
show the old "Default value" tooltip.
For an example of how to add socket descriptions, check the Cylinder node
in the Geometry Nodes.
Differential Revision: https://developer.blender.org/D9967
Diffstat (limited to 'source/blender/editors/space_node/node_draw.cc')
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 106 |
1 files changed, 82 insertions, 24 deletions
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 88ab7617932..013413adfe9 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -26,12 +26,10 @@ #include "BLI_span.hh" #include "BLI_string_ref.hh" #include "BLI_vector.hh" -#include "BLI_vector_set.hh" #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_geometry_set.hh" #include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -75,8 +73,6 @@ #include "node_intern.hh" /* own include */ using blender::GPointer; -using blender::fn::FieldCPPType; -using blender::fn::FieldInput; using blender::fn::GField; namespace geo_log = blender::nodes::geometry_nodes_eval_log; @@ -374,6 +370,8 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, const char *socket_label = nodeSocketLabel(nsock); nsock->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); + node_socket_add_tooltip(&ntree, &node, nsock, row); + UI_block_align_end(&block); UI_block_layout_resolve(&block, nullptr, &buty); @@ -504,6 +502,8 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, const char *socket_label = nodeSocketLabel(nsock); nsock->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); + node_socket_add_tooltip(&ntree, &node, nsock, row); + UI_block_align_end(&block); UI_block_layout_resolve(&block, nullptr, &buty); @@ -943,6 +943,10 @@ static std::optional<std::string> create_socket_inspection_string(bContext *C, bNodeSocket &socket) { SpaceNode *snode = CTX_wm_space_node(C); + if (snode == nullptr) { + return {}; + }; + const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context( *snode, node, socket); if (socket_log == nullptr) { @@ -970,6 +974,78 @@ static std::optional<std::string> create_socket_inspection_string(bContext *C, return ss.str(); } +static bool node_socket_has_tooltip(bNodeTree *ntree, bNodeSocket *socket) +{ + if (ntree->type == NTREE_GEOMETRY) { + return true; + } + + if (socket->declaration != nullptr) { + const blender::nodes::SocketDeclaration &socket_decl = *socket->declaration; + return !socket_decl.description().is_empty(); + } + + return false; +} + +static char *node_socket_get_tooltip(bContext *C, + bNodeTree *ntree, + bNode *node, + bNodeSocket *socket) +{ + std::stringstream output; + if (socket->declaration != nullptr) { + const blender::nodes::SocketDeclaration &socket_decl = *socket->declaration; + blender::StringRef description = socket_decl.description(); + if (!description.is_empty()) { + output << TIP_(description.data()); + } + } + + if (ntree->type == NTREE_GEOMETRY) { + if (!output.str().empty()) { + output << ".\n\n"; + } + + std::optional<std::string> socket_inspection_str = create_socket_inspection_string( + C, *node, *socket); + if (socket_inspection_str.has_value()) { + output << *socket_inspection_str; + } + else { + output << TIP_("The socket value has not been computed yet"); + } + } + + if (output.str().empty()) { + output << nodeSocketLabel(socket); + } + + return BLI_strdup(output.str().c_str()); +} + +void node_socket_add_tooltip(bNodeTree *ntree, bNode *node, bNodeSocket *sock, uiLayout *layout) +{ + if (!node_socket_has_tooltip(ntree, sock)) { + return; + } + + SocketTooltipData *data = MEM_cnew<SocketTooltipData>(__func__); + data->ntree = ntree; + data->node = node; + data->socket = sock; + + uiLayoutSetTooltipFunc( + layout, + [](bContext *C, void *argN, const char *UNUSED(tip)) { + SocketTooltipData *data = static_cast<SocketTooltipData *>(argN); + return node_socket_get_tooltip(C, data->ntree, data->node, data->socket); + }, + data, + MEM_dupallocN, + MEM_freeN); +} + static void node_socket_draw_nested(const bContext &C, bNodeTree &ntree, PointerRNA &node_ptr, @@ -1001,8 +1077,7 @@ static void node_socket_draw_nested(const bContext &C, size_id, outline_col_id); - if (ntree.type != NTREE_GEOMETRY) { - /* Only geometry nodes has socket value tooltips currently. */ + if (!node_socket_has_tooltip(&ntree, &sock)) { return; } @@ -1034,24 +1109,7 @@ static void node_socket_draw_nested(const bContext &C, but, [](bContext *C, void *argN, const char *UNUSED(tip)) { SocketTooltipData *data = (SocketTooltipData *)argN; - std::optional<std::string> socket_inspection_str = create_socket_inspection_string( - C, *data->node, *data->socket); - - std::stringstream output; - if (data->socket->declaration != nullptr) { - const blender::nodes::SocketDeclaration &socket_decl = *data->socket->declaration; - blender::StringRef description = socket_decl.description(); - if (!description.is_empty()) { - output << TIP_(description.data()) << ".\n\n"; - } - } - if (socket_inspection_str.has_value()) { - output << *socket_inspection_str; - } - else { - output << TIP_("The socket value has not been computed yet"); - } - return BLI_strdup(output.str().c_str()); + return node_socket_get_tooltip(C, data->ntree, data->node, data->socket); }, data, MEM_freeN); |