From ceca413bcbf816666b1ba08603e662a92d574693 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 6 Oct 2025 10:40:05 +0200 Subject: [PATCH] RNA: add callback to support dynamic property ui name This adds a new `PropertyRNA::name_func` property which is similar to the many existing functions like `editable`, `get_default`, etc. It allows dynamically getting a UI name for the property. This is especially useful for node sockets, because those all have the same hardcoded name "Default Value" which is not helpful. Since we already have custom tooltips for sockets, this is mostly not visible to the user anymore. The exception being menu sockets which draw the property name as title. Instead of "Default Value", this patch makes it show the correct title. Pull Request: https://projects.blender.org/blender/blender/pulls/147137 --- source/blender/editors/include/ED_node.hh | 2 ++ source/blender/editors/interface/interface.cc | 3 ++- .../blender/editors/space_node/node_intern.hh | 2 -- .../editors/space_node/node_socket_tooltip.cc | 2 ++ source/blender/makesrna/RNA_access.hh | 4 ++-- source/blender/makesrna/RNA_define.hh | 1 + source/blender/makesrna/intern/makesrna.cc | 3 ++- source/blender/makesrna/intern/rna_access.cc | 14 +++++++++-- source/blender/makesrna/intern/rna_define.cc | 12 ++++++++++ .../makesrna/intern/rna_internal_types.hh | 6 +++++ .../makesrna/intern/rna_node_socket.cc | 24 +++++++++++++++++++ 11 files changed, 65 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/include/ED_node.hh b/source/blender/editors/include/ED_node.hh index f586a3db52e..a631f564d9d 100644 --- a/source/blender/editors/include/ED_node.hh +++ b/source/blender/editors/include/ED_node.hh @@ -144,4 +144,6 @@ void ui_template_node_asset_menu_items(uiLayout &layout, /** See #SpaceNode_Runtime::node_can_sync_states. */ Map &node_can_sync_cache_get(SpaceNode &snode); +const char *node_socket_get_label(const bNodeSocket *socket, const char *panel_label = nullptr); + } // namespace blender::ed::space_node diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 70b1dc40776..70030171476 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -4582,7 +4582,8 @@ static void ui_def_but_rna__menu(bContext *C, uiLayout *layout, void *but_p) rows = totitems; } - const char *title = RNA_property_ui_name(but->rnaprop); + const char *title = RNA_property_ui_name( + but->rnaprop, RNA_pointer_is_null(&but->rnapoin) ? nullptr : &but->rnapoin); /* Is there a non-blank label before this button on the same row? */ uiBut *but_prev = but->block->prev_but(but); diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index e7d774116c0..ae7c0cdc84b 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -170,8 +170,6 @@ void node_socket_color_get(const bContext &C, const bNodeSocket &sock, float r_color[4]); -const char *node_socket_get_label(const bNodeSocket *socket, const char *panel_label); - void node_draw_space(const bContext &C, ARegion ®ion); void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, uiLayout &layout); diff --git a/source/blender/editors/space_node/node_socket_tooltip.cc b/source/blender/editors/space_node/node_socket_tooltip.cc index 30346b138a3..576bcbb60d3 100644 --- a/source/blender/editors/space_node/node_socket_tooltip.cc +++ b/source/blender/editors/space_node/node_socket_tooltip.cc @@ -25,6 +25,8 @@ #include "NOD_node_declaration.hh" #include "NOD_socket.hh" +#include "ED_node.hh" + #include "node_intern.hh" namespace geo_log = blender::nodes::geo_eval_log; diff --git a/source/blender/makesrna/RNA_access.hh b/source/blender/makesrna/RNA_access.hh index 997b570e6cd..a548d310c0a 100644 --- a/source/blender/makesrna/RNA_access.hh +++ b/source/blender/makesrna/RNA_access.hh @@ -276,8 +276,8 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name); */ int RNA_property_string_maxlength(PropertyRNA *prop); -const char *RNA_property_ui_name(const PropertyRNA *prop); -const char *RNA_property_ui_name_raw(const PropertyRNA *prop); +const char *RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr = nullptr); +const char *RNA_property_ui_name_raw(const PropertyRNA *prop, const PointerRNA *ptr = nullptr); const char *RNA_property_ui_description(const PropertyRNA *prop); const char *RNA_property_ui_description_raw(const PropertyRNA *prop); const char *RNA_property_translation_context(const PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_define.hh b/source/blender/makesrna/RNA_define.hh index 8720108cba0..b79e8564e89 100644 --- a/source/blender/makesrna/RNA_define.hh +++ b/source/blender/makesrna/RNA_define.hh @@ -493,6 +493,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value); void RNA_def_property_string_default(PropertyRNA *prop, const char *value); void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description); +void RNA_def_property_ui_name_func(PropertyRNA *prop, const char *name_func); void RNA_def_property_deprecated(PropertyRNA *prop, const char *note, diff --git a/source/blender/makesrna/intern/makesrna.cc b/source/blender/makesrna/intern/makesrna.cc index 7d8aa2ce0f6..15aa0bc4735 100644 --- a/source/blender/makesrna/intern/makesrna.cc +++ b/source/blender/makesrna/intern/makesrna.cc @@ -4428,13 +4428,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr prop->arraylength[2], prop->totarraylength); fprintf(f, - "\t%s%s, %d, %s, %s, %s, %s, %s,\n", + "\t%s%s, %d, %s, %s, %s, %s, %s, %s,\n", /* NOTE: void cast is needed to quiet function cast warning in C++. */ (prop->flag & PROP_CONTEXT_UPDATE) ? "(UpdateFunc)(void *)" : "", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable), rna_function_string(prop->itemeditable), + rna_function_string(prop->ui_name_func), rna_function_string(prop->override_diff), rna_function_string(prop->override_store), rna_function_string(prop->override_apply)); diff --git a/source/blender/makesrna/intern/rna_access.cc b/source/blender/makesrna/intern/rna_access.cc index 44831b21e06..1c56bc9e073 100644 --- a/source/blender/makesrna/intern/rna_access.cc +++ b/source/blender/makesrna/intern/rna_access.cc @@ -2208,13 +2208,23 @@ int RNA_property_enum_bitflag_identifiers( return 0; } -const char *RNA_property_ui_name(const PropertyRNA *prop) +const char *RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr) { + if (ptr && prop->magic == RNA_MAGIC && prop->ui_name_func) { + if (const char *name = prop->ui_name_func(ptr, prop, true)) { + return name; + } + } return CTX_IFACE_(RNA_property_translation_context(prop), rna_ensure_property_name(prop)); } -const char *RNA_property_ui_name_raw(const PropertyRNA *prop) +const char *RNA_property_ui_name_raw(const PropertyRNA *prop, const PointerRNA *ptr) { + if (ptr && prop->magic == RNA_MAGIC && prop->ui_name_func) { + if (const char *name = prop->ui_name_func(ptr, prop, false)) { + return name; + } + } return rna_ensure_property_name(prop); } diff --git a/source/blender/makesrna/intern/rna_define.cc b/source/blender/makesrna/intern/rna_define.cc index 19b037d3555..c818614c29e 100644 --- a/source/blender/makesrna/intern/rna_define.cc +++ b/source/blender/makesrna/intern/rna_define.cc @@ -3223,6 +3223,18 @@ void RNA_def_property_override_funcs(PropertyRNA *prop, } } +void RNA_def_property_ui_name_func(PropertyRNA *prop, const char *name_func) +{ + if (!DefRNA.preprocess) { + CLOG_ERROR(&LOG, "only during preprocessing."); + return; + } + + if (name_func) { + prop->ui_name_func = (PropUINameFunc)name_func; + } +} + void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func) { if (!DefRNA.preprocess) { diff --git a/source/blender/makesrna/intern/rna_internal_types.hh b/source/blender/makesrna/intern/rna_internal_types.hh index e07f2da0ddc..6a546cf22df 100644 --- a/source/blender/makesrna/intern/rna_internal_types.hh +++ b/source/blender/makesrna/intern/rna_internal_types.hh @@ -56,6 +56,9 @@ using ItemEditableFunc = int (*)(const PointerRNA *ptr, int index); using IDPropertiesFunc = IDProperty **(*)(PointerRNA * ptr); using StructRefineFunc = StructRNA *(*)(PointerRNA * ptr); using StructPathFunc = std::optional (*)(const PointerRNA *ptr); +using PropUINameFunc = const char *(*)(const PointerRNA *ptr, + const PropertyRNA *prop, + bool do_translate); using PropArrayLengthGetFunc = int (*)(const PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]); using PropBooleanGetFunc = bool (*)(PointerRNA *ptr); @@ -422,6 +425,9 @@ struct PropertyRNA { /** Callback for testing if array-item editable (if applicable). */ ItemEditableFunc itemeditable; + /** Optional function to dynamically override the user-readable #name. */ + PropUINameFunc ui_name_func; + /** Override handling callbacks (diff is also used for comparison). */ RNAPropOverrideDiff override_diff; RNAPropOverrideStore override_store; diff --git a/source/blender/makesrna/intern/rna_node_socket.cc b/source/blender/makesrna/intern/rna_node_socket.cc index 6e80d9de2b1..9eb5a3d976e 100644 --- a/source/blender/makesrna/intern/rna_node_socket.cc +++ b/source/blender/makesrna/intern/rna_node_socket.cc @@ -467,6 +467,17 @@ static void rna_NodeSocketStandard_draw_color_simple(StructRNA *type, float r_co typeinfo->draw_color_simple(typeinfo, r_color); } +static const char *rna_NodeSocketStandard_name_func(const PointerRNA *ptr, + const PropertyRNA * /*prop*/, + const bool do_translate) +{ + const bNodeSocket *socket = ptr->data_as(); + if (do_translate) { + return blender::ed::space_node::node_socket_get_label(socket); + } + return socket->name; +} + /* ******** Node Socket Subtypes ******** */ void rna_NodeSocketStandard_float_range( @@ -1027,6 +1038,7 @@ static void rna_def_node_socket_float(BlenderRNA *brna, RNA_def_property_float_funcs(prop, nullptr, nullptr, "rna_NodeSocketStandard_float_range"); RNA_def_property_float_default_func(prop, "rna_NodeSocketStandard_float_default"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1131,6 +1143,7 @@ static void rna_def_node_socket_int(BlenderRNA *brna, RNA_def_property_int_funcs(prop, nullptr, nullptr, "rna_NodeSocketStandard_int_range"); RNA_def_property_int_default_func(prop, "rna_NodeSocketStandard_int_default"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1200,6 +1213,7 @@ static void rna_def_node_socket_bool(BlenderRNA *brna, const char *identifier) prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "value", 1); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_boolean_default_func(prop, "rna_NodeSocketStandard_boolean_default"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1245,6 +1259,7 @@ static void rna_def_node_socket_rotation(BlenderRNA *brna, const char *identifie RNA_def_property_float_sdna(prop, nullptr, "value_euler"); // RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1320,6 +1335,7 @@ static void rna_def_node_socket_vector(BlenderRNA *brna, RNA_def_property_float_default_func(prop, "rna_NodeSocketStandard_vector_default"); RNA_def_property_float_funcs(prop, nullptr, nullptr, "rna_NodeSocketStandard_vector_range"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1399,6 +1415,7 @@ static void rna_def_node_socket_color(BlenderRNA *brna, const char *identifier) prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, nullptr, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_float_default_func(prop, "rna_NodeSocketStandard_color_default"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1445,6 +1462,7 @@ static void rna_def_node_socket_string(BlenderRNA *brna, prop = RNA_def_property(srna, "default_value", PROP_STRING, subtype); RNA_def_property_string_sdna(prop, nullptr, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1509,6 +1527,7 @@ static void rna_def_node_socket_menu(BlenderRNA *brna, const char *identifier) RNA_def_property_enum_funcs(prop, nullptr, nullptr, "RNA_node_socket_menu_itemf"); RNA_def_property_enum_default_func(prop, "rna_NodeSocketStandard_menu_default"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); @@ -1577,6 +1596,7 @@ static void rna_def_node_socket_object(BlenderRNA *brna, const char *identifier) RNA_def_property_pointer_sdna(prop, nullptr, "value"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update( prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); @@ -1621,6 +1641,7 @@ static void rna_def_node_socket_image(BlenderRNA *brna, const char *identifier) RNA_def_property_pointer_sdna(prop, nullptr, "value"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update( prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); @@ -1728,6 +1749,7 @@ static void rna_def_node_socket_collection(BlenderRNA *brna, const char *identif RNA_def_property_pointer_sdna(prop, nullptr, "value"); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update( prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); @@ -1772,6 +1794,7 @@ static void rna_def_node_socket_texture(BlenderRNA *brna, const char *identifier RNA_def_property_pointer_sdna(prop, nullptr, "value"); RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update( prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); @@ -1816,6 +1839,7 @@ static void rna_def_node_socket_material(BlenderRNA *brna, const char *identifie RNA_def_property_pointer_sdna(prop, nullptr, "value"); RNA_def_property_struct_type(prop, "Material"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_ui_name_func(prop, "rna_NodeSocketStandard_name_func"); RNA_def_property_update( prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);