Refactor: Nodes: Generate socket tooltips in more generic way #120496

Merged
Hans Goudey merged 6 commits from mod_moder/blender:refactor_socket_tooltips into main 2024-04-11 17:53:13 +02:00
1 changed files with 55 additions and 33 deletions

View File

@ -1480,8 +1480,7 @@ static void create_inspection_string_for_geometry_info(const geo_log::GeometryIn
}
static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
const nodes::decl::Geometry *socket_decl,
const bool after_log)
const nodes::decl::Geometry *socket_decl)
{
/* If the geometry declaration is null, as is the case for input to group output,
* or it is an output socket don't show supported types. */
@ -1489,10 +1488,6 @@ static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
return;
}
if (after_log) {
ss << ".\n\n";
}
Span<bke::GeometryComponent::Type> supported_types = socket_decl->supported_types();
if (supported_types.is_empty()) {
ss << TIP_("Supported: All Types");
@ -1536,17 +1531,34 @@ static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
}
}
static std::optional<std::string> create_socket_inspection_string(
geo_log::GeoTreeLog &geo_tree_log, const bNodeSocket &socket)
static std::optional<std::string> create_description_inspection_string(const bNodeSocket &socket)
{
if (socket.runtime->declaration == nullptr) {
return std::nullopt;
}
const blender::nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration;
blender::StringRefNull description = socket_decl.description;
if (description.is_empty()) {
return std::nullopt;
}
mod_moder marked this conversation as resolved Outdated

I think it's incorrect to use .data() here, TIP_ expects a null terminated C string

I think it's incorrect to use `.data()` here, `TIP_` expects a null terminated C string

Well, this is how it was in the main. I can fix this.

Well, this is how it was in the main. I can fix this.

Oh, sorry, I missed that. But yeah, it should be simple to just not use a temporary variable for the description. Thanks.

Oh, sorry, I missed that. But yeah, it should be simple to just not use a temporary variable for the description. Thanks.
a03c3d16d85a3461a8d1eb8665b5ada84d0ce8ed
return TIP_(description.c_str());
}
static std::optional<std::string> create_log_inspection_string(geo_log::GeoTreeLog *geo_tree_log,
const bNodeSocket &socket)
{
using namespace blender::nodes::geo_eval_log;
if (geo_tree_log == nullptr) {
return std::nullopt;
}
if (socket.typeinfo->base_cpp_type == nullptr) {
return std::nullopt;
}
geo_tree_log.ensure_socket_values();
ValueLog *value_log = geo_tree_log.find_socket_value_log(socket);
geo_tree_log->ensure_socket_values();
ValueLog *value_log = geo_tree_log->find_socket_value_log(socket);
std::stringstream ss;
if (const geo_log::GenericValueLog *generic_value_log =
dynamic_cast<const geo_log::GenericValueLog *>(value_log))
@ -1564,11 +1576,20 @@ static std::optional<std::string> create_socket_inspection_string(
create_inspection_string_for_geometry_info(*geo_value_log, ss);
}
std::string str = ss.str();
if (str.empty()) {
return std::nullopt;
}
return str;
}
static std::optional<std::string> create_declaration_inspection_string(const bNodeSocket &socket)
{
std::stringstream ss;
if (const nodes::decl::Geometry *socket_decl = dynamic_cast<const nodes::decl::Geometry *>(
socket.runtime->declaration))
{
const bool after_log = value_log != nullptr;
create_inspection_string_for_geometry_socket(ss, socket_decl, after_log);
create_inspection_string_for_geometry_socket(ss, socket_decl);
}
std::string str = ss.str();
@ -1590,15 +1611,6 @@ static std::string node_socket_get_tooltip(const SpaceNode *snode,
}
}
std::stringstream output;
if (socket.runtime->declaration != nullptr) {
const blender::nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration;
blender::StringRefNull description = socket_decl.description;
if (!description.is_empty()) {
output << TIP_(description.c_str());
}
}
geo_log::GeoTreeLog *geo_tree_log = [&]() -> geo_log::GeoTreeLog * {
const bNodeTreeZones *zones = ntree.zones();
if (!zones) {
@ -1608,27 +1620,37 @@ static std::string node_socket_get_tooltip(const SpaceNode *snode,
return tree_draw_ctx.geo_log_by_zone.lookup_default(zone, nullptr);
}();
if (ntree.type == NTREE_GEOMETRY && geo_tree_log != nullptr) {
if (!output.str().empty()) {
Vector<std::string> inspection_strings;
if (std::optional<std::string> info = create_description_inspection_string(socket)) {
inspection_strings.append(std::move(*info));
}
if (std::optional<std::string> info = create_log_inspection_string(geo_tree_log, socket)) {
inspection_strings.append(std::move(*info));
}
if (std::optional<std::string> info = create_declaration_inspection_string(socket)) {
inspection_strings.append(std::move(*info));
}
std::stringstream output;
for (const std::string &info : inspection_strings) {
output << info;
if (&info != &inspection_strings.last()) {
output << ".\n\n";
}
}
std::optional<std::string> socket_inspection_str = create_socket_inspection_string(
*geo_tree_log, socket);
if (socket_inspection_str.has_value()) {
output << *socket_inspection_str;
}
else {
if (inspection_strings.is_empty()) {
output << bke::nodeSocketLabel(&socket);
if (ntree.type == NTREE_GEOMETRY) {
output << ".\n\n";
output << TIP_(
"Unknown socket value. Either the socket was not used or its value was not logged "
"during the last evaluation");
}
}
if (output.str().empty()) {
output << bke::nodeSocketLabel(&socket);
}
return output.str();
}