Geometry Node: Multi-input socket tooltip #104468

Merged
Jacques Lucke merged 33 commits from mod_moder/blender:multi_input_tooltip into main 2024-04-22 19:49:08 +02:00
2 changed files with 29 additions and 79 deletions
Showing only changes of commit 273c0b2a82 - Show all commits

View File

@ -929,27 +929,26 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
return mesh_in_bmain;
}
/* Make sure mesh only points original data-blocks, also increase users of materials and other
* possibly referenced data-blocks.
/* Make sure mesh only points to original data-blocks. Also increase user count of materials and
* other possibly referenced data-blocks.
*
* Going to original data-blocks is required to have bmain in a consistent state, where
* Changing to original data-blocks is required to have bmain in a consistent state, where
* everything is only allowed to reference original data-blocks.
*
* Note that user-count updates has to be done *after* mesh has been transferred to Main database
* (since doing reference-counting on non-Main IDs is forbidden). */
* Note that user-count updates have to be done *after* the mesh has been transferred to Main
* database (since doing reference-counting on non-Main IDs is forbidden). */
BKE_library_foreach_ID_link(
nullptr, &mesh->id, foreach_libblock_make_original_callback, nullptr, IDWALK_NOP);
/* Append the mesh to 'bmain'.
* We do it a bit longer way since there is no simple and clear way of adding existing data-block
* to the 'bmain'. So we allocate new empty mesh in the 'bmain' (which guarantees all the naming
* and orders and flags) and move the temporary mesh in place there. */
/* Add the mesh to 'bmain'. We do it in a bit longer way since there is no simple and clear way
* of adding existing data-blocks to the 'bmain'. So we create new empty mesh (which guarantees
* all the naming and order and flags) and move the temporary mesh in place there. */
Mesh *mesh_in_bmain = BKE_mesh_add(bmain, mesh->id.name + 2);
/* NOTE: BKE_mesh_nomain_to_mesh() does not copy materials and instead it preserves them in the
/* NOTE: BKE_mesh_nomain_to_mesh() does not copy materials and instead preserves them in the
* destination mesh. So we "steal" materials before calling it.
*
* TODO(sergey): We really better have a function which gets and ID and accepts it for the bmain.
* TODO(sergey): We really ought to have a function which gets an ID and accepts it into #Main.
*/
mesh_in_bmain->mat = mesh->mat;
mesh_in_bmain->totcol = mesh->totcol;

View File

@ -1480,7 +1480,8 @@ 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)
static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
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. */
@ -1531,29 +1532,6 @@ static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
}
}
static void create_inspection_string_for_default_socket_value(const bNodeSocket &socket, std::stringstream &ss)
{
if (!socket.is_input()) {
return;
}
if (socket.is_directly_linked()) {
return;
}
if (socket.flag & SOCK_HIDE_VALUE) {
return;
}
if (socket.typeinfo->base_cpp_type == nullptr) {
return;
}
const CPPType &value_type = *socket.typeinfo->base_cpp_type;
BUFFER_FOR_CPP_TYPE_VALUE(value_type, socket_value);
socket.typeinfo->get_base_cpp_value(socket.default_value, socket_value);
create_inspection_string_for_generic_value(socket, GPointer(value_type, socket_value), ss);
value_type.destruct(socket_value);
}
static std::optional<std::string> create_description_inspection_string(const bNodeSocket &socket)
{
if (socket.runtime->declaration == nullptr) {
@ -1564,11 +1542,12 @@ static std::optional<std::string> create_description_inspection_string(const bNo
if (description.is_empty()) {
return std::nullopt;
}
return TIP_(description.data());
}
static std::optional<std::string> create_log_inspection_string(geo_log::GeoTreeLog *geo_tree_log, const bNodeSocket &socket)
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;
@ -1582,15 +1561,18 @@ static std::optional<std::string> create_log_inspection_string(geo_log::GeoTreeL
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))
if (const geo_log::GenericValueLog *generic_value_log =
dynamic_cast<const geo_log::GenericValueLog *>(value_log))
{
create_inspection_string_for_generic_value(socket, generic_value_log->value, ss);
}
else if (const geo_log::FieldInfoLog *gfield_value_log = dynamic_cast<const geo_log::FieldInfoLog *>(value_log))
else if (const geo_log::FieldInfoLog *gfield_value_log =
dynamic_cast<const geo_log::FieldInfoLog *>(value_log))
{
create_inspection_string_for_field_info(socket, *gfield_value_log, ss);
}
else if (const geo_log::GeometryInfoLog *geo_value_log = dynamic_cast<const geo_log::GeometryInfoLog *>(value_log))
else if (const geo_log::GeometryInfoLog *geo_value_log =
dynamic_cast<const geo_log::GeometryInfoLog *>(value_log))
{
create_inspection_string_for_geometry_info(*geo_value_log, ss);
}
@ -1605,12 +1587,13 @@ static std::optional<std::string> create_log_inspection_string(geo_log::GeoTreeL
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))
if (const nodes::decl::Geometry *socket_decl = dynamic_cast<const nodes::decl::Geometry *>(
socket.runtime->declaration))
{
create_inspection_string_for_geometry_socket(ss, socket_decl);
}
if (const const nodes::SocketDeclaration * socket_decl = socket.runtime->declaration) {
if (const nodes::SocketDeclaration *socket_decl = socket.runtime->declaration) {
if (socket_decl->input_field_type == nodes::InputSocketFieldType::Implicit) {
if (!ss.str().empty()) {
ss << ".\n\n";
@ -1626,23 +1609,6 @@ static std::optional<std::string> create_declaration_inspection_string(const bNo
return str;
}
static std::optional<std::string> create_default_value_inspection_string(const bNodeSocket &socket)
{
std::stringstream ss;
create_inspection_string_for_default_socket_value(socket, ss);
std::string str = ss.str();
if (str.empty()) {
return std::nullopt;
}
return str;
}
static bool node_socket_has_tooltip(const bNodeTree &ntree, const bNodeSocket &socket)
{
return true;
}
static std::string node_socket_get_tooltip(const SpaceNode *snode,
const bNodeTree &ntree,
const bNodeSocket &socket)
@ -1650,11 +1616,11 @@ static std::string node_socket_get_tooltip(const SpaceNode *snode,
TreeDrawContext tree_draw_ctx;
if (snode != nullptr) {
if (ntree.type == NTREE_GEOMETRY) {
tree_draw_ctx.geo_log_by_zone = geo_log::GeoModifierLog::get_tree_log_by_zone_for_node_editor(*snode);
tree_draw_ctx.geo_log_by_zone =
geo_log::GeoModifierLog::get_tree_log_by_zone_for_node_editor(*snode);
}
}
bool value_is_mentioned = false;
Vector<std::string> inspection_strings;
geo_log::GeoTreeLog *geo_tree_log = [&]() -> geo_log::GeoTreeLog * {
@ -1671,16 +1637,10 @@ static std::string node_socket_get_tooltip(const SpaceNode *snode,
}
if (std::optional<std::string> info = create_log_inspection_string(geo_tree_log, socket)) {
inspection_strings.append(std::move(*info));
value_is_mentioned = true;
}
if (std::optional<std::string> info = create_declaration_inspection_string(socket)) {
inspection_strings.append(std::move(*info));
}
if (!value_is_mentioned) {
if (std::optional<std::string> info = create_default_value_inspection_string(socket)) {
inspection_strings.append(std::move(*info));
}
}
std::stringstream output;
for (const std::string &info : inspection_strings) {
@ -1695,7 +1655,9 @@ static std::string node_socket_get_tooltip(const SpaceNode *snode,
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");
output << TIP_(
"Unknown socket value. Either the socket was not used or its value was not logged "
"during the last evaluation");
}
}
@ -1706,9 +1668,6 @@ static void node_socket_add_tooltip_in_node_editor(const bNodeTree &ntree,
const bNodeSocket &sock,
uiLayout &layout)
{
if (!node_socket_has_tooltip(ntree, sock)) {
return;
}
uiLayoutSetTooltipFunc(
&layout,
[](bContext *C, void *argN, const char * /*tip*/) {
@ -1725,10 +1684,6 @@ static void node_socket_add_tooltip_in_node_editor(const bNodeTree &ntree,
void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, uiLayout &layout)
{
if (!node_socket_has_tooltip(ntree, sock)) {
return;
}
struct SocketTooltipData {
const bNodeTree *ntree;
const bNodeSocket *socket;
@ -1782,10 +1737,6 @@ static void node_socket_draw_nested(const bContext &C,
size_id,
outline_col_id);
if (!node_socket_has_tooltip(ntree, sock)) {
return;
}
/* Ideally sockets themselves should be buttons, but they aren't currently. So add an invisible
* button on top of them for the tooltip. */
const eUIEmbossType old_emboss = UI_block_emboss_get(&block);