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_draw.cc')
-rw-r--r--source/blender/editors/space_node/node_draw.cc270
1 files changed, 230 insertions, 40 deletions
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 88ab7617932..47d35ced371 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,10 +73,9 @@
#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;
+using geo_log::NamedAttributeUsage;
extern "C" {
/* XXX interface.h */
@@ -374,6 +371,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 +503,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 +944,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 +975,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 +1078,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 +1110,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);
@@ -1626,10 +1685,127 @@ static std::string node_get_execution_time_label(const SpaceNode &snode, const b
struct NodeExtraInfoRow {
std::string text;
- const char *tooltip;
int icon;
+ const char *tooltip = nullptr;
+
+ uiButToolTipFunc tooltip_fn = nullptr;
+ void *tooltip_fn_arg = nullptr;
+ void (*tooltip_fn_free_arg)(void *) = nullptr;
};
+struct NamedAttributeTooltipArg {
+ Map<std::string, NamedAttributeUsage> usage_by_attribute;
+};
+
+static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
+{
+ NamedAttributeTooltipArg &arg = *static_cast<NamedAttributeTooltipArg *>(argN);
+
+ std::stringstream ss;
+ ss << TIP_("Accessed attribute names:\n");
+ Vector<std::pair<StringRefNull, NamedAttributeUsage>> sorted_used_attribute;
+ for (auto &&item : arg.usage_by_attribute.items()) {
+ sorted_used_attribute.append({item.key, item.value});
+ }
+ std::sort(sorted_used_attribute.begin(), sorted_used_attribute.end());
+ for (const std::pair<StringRefNull, NamedAttributeUsage> &attribute : sorted_used_attribute) {
+ const StringRefNull name = attribute.first;
+ const NamedAttributeUsage usage = attribute.second;
+ ss << " \u2022 \"" << name << "\": ";
+ Vector<std::string> usages;
+ if ((usage & NamedAttributeUsage::Read) != NamedAttributeUsage::None) {
+ usages.append(TIP_("read"));
+ }
+ if ((usage & NamedAttributeUsage::Write) != NamedAttributeUsage::None) {
+ usages.append(TIP_("write"));
+ }
+ if ((usage & NamedAttributeUsage::Remove) != NamedAttributeUsage::None) {
+ usages.append(TIP_("remove"));
+ }
+ for (const int i : usages.index_range()) {
+ ss << usages[i];
+ if (i < usages.size() - 1) {
+ ss << ", ";
+ }
+ }
+ ss << "\n";
+ }
+ ss << "\n";
+ ss << TIP_(
+ "Attributes with these names used within the group may conflict with existing attributes");
+ return BLI_strdup(ss.str().c_str());
+}
+
+static NodeExtraInfoRow row_from_used_named_attribute(
+ const Map<std::string, NamedAttributeUsage> &usage_by_attribute_name)
+{
+ NodeExtraInfoRow row;
+ row.text = TIP_("Attributes");
+ row.icon = ICON_SPREADSHEET;
+ row.tooltip_fn = named_attribute_tooltip;
+ row.tooltip_fn_arg = new NamedAttributeTooltipArg{usage_by_attribute_name};
+ row.tooltip_fn_free_arg = [](void *arg) { delete static_cast<NamedAttributeTooltipArg *>(arg); };
+ return row;
+}
+
+static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const SpaceNode &snode,
+ const bNode &node)
+{
+ if (node.type == NODE_GROUP) {
+ const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
+ snode);
+ if (root_tree_log == nullptr) {
+ return std::nullopt;
+ }
+ const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node.name);
+ if (tree_log == nullptr) {
+ return std::nullopt;
+ }
+
+ Map<std::string, NamedAttributeUsage> usage_by_attribute;
+ tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
+ for (const geo_log::UsedNamedAttribute &used_attribute : node_log.used_named_attributes()) {
+ usage_by_attribute.lookup_or_add_as(used_attribute.name,
+ used_attribute.usage) |= used_attribute.usage;
+ }
+ });
+ if (usage_by_attribute.is_empty()) {
+ return std::nullopt;
+ }
+
+ return row_from_used_named_attribute(usage_by_attribute);
+ }
+ if (ELEM(node.type,
+ GEO_NODE_STORE_NAMED_ATTRIBUTE,
+ GEO_NODE_REMOVE_ATTRIBUTE,
+ GEO_NODE_INPUT_NAMED_ATTRIBUTE)) {
+ /* Only show the overlay when the name is passed in from somewhere else. */
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
+ if (STREQ(socket->name, "Name")) {
+ if ((socket->flag & SOCK_IN_USE) == 0) {
+ return std::nullopt;
+ }
+ }
+ }
+ const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
+ snode, node.name);
+ if (node_log == nullptr) {
+ return std::nullopt;
+ }
+ Map<std::string, NamedAttributeUsage> usage_by_attribute;
+ for (const geo_log::UsedNamedAttribute &used_attribute : node_log->used_named_attributes()) {
+ usage_by_attribute.lookup_or_add_as(used_attribute.name,
+ used_attribute.usage) |= used_attribute.usage;
+ }
+ if (usage_by_attribute.is_empty()) {
+ return std::nullopt;
+ }
+ return row_from_used_named_attribute(usage_by_attribute);
+ }
+
+ return std::nullopt;
+}
+
static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, const bNode &node)
{
Vector<NodeExtraInfoRow> rows;
@@ -1660,6 +1836,14 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons
rows.append(std::move(row));
}
}
+
+ if (snode.overlay.flag & SN_OVERLAY_SHOW_NAMED_ATTRIBUTES &&
+ snode.edittree->type == NTREE_GEOMETRY) {
+ if (std::optional<NodeExtraInfoRow> row = node_get_accessed_attributes_row(snode, node)) {
+ rows.append(std::move(*row));
+ }
+ }
+
return rows;
}
@@ -1669,20 +1853,20 @@ static void node_draw_extra_info_row(const bNode &node,
const int row,
const NodeExtraInfoRow &extra_info_row)
{
- uiBut *but_timing = uiDefBut(&block,
- UI_BTYPE_LABEL,
- 0,
- extra_info_row.text.c_str(),
- (int)(rect.xmin + 4.0f * U.dpi_fac + NODE_MARGIN_X + 0.4f),
- (int)(rect.ymin + row * (20.0f * U.dpi_fac)),
- (short)(rect.xmax - rect.xmin),
- (short)NODE_DY,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- "");
+ uiBut *but_text = uiDefBut(&block,
+ UI_BTYPE_LABEL,
+ 0,
+ extra_info_row.text.c_str(),
+ (int)(rect.xmin + 4.0f * U.dpi_fac + NODE_MARGIN_X + 0.4f),
+ (int)(rect.ymin + row * (20.0f * U.dpi_fac)),
+ (short)(rect.xmax - rect.xmin),
+ (short)NODE_DY,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
uiBut *but_icon = uiDefIconBut(&block,
UI_BTYPE_BUT,
@@ -1698,9 +1882,15 @@ static void node_draw_extra_info_row(const bNode &node,
0,
0,
extra_info_row.tooltip);
+ if (extra_info_row.tooltip_fn != nullptr) {
+ UI_but_func_tooltip_set(but_icon,
+ extra_info_row.tooltip_fn,
+ extra_info_row.tooltip_fn_arg,
+ extra_info_row.tooltip_fn_free_arg);
+ }
UI_block_emboss_set(&block, UI_EMBOSS);
if (node.flag & NODE_MUTED) {
- UI_but_flag_enable(but_timing, UI_BUT_INACTIVE);
+ UI_but_flag_enable(but_text, UI_BUT_INACTIVE);
UI_but_flag_enable(but_icon, UI_BUT_INACTIVE);
}
}