UI: Support copy-paste of enum value

In nodes it is common to have a lot of enum value properties to control
different things, and ability to easily propagate them at UI level would
be very welcome. This patch add support of that.

Details: this works as if this would be a python action: identified of
active item is pushed into clipboard buffer so one might looks like:
`VECTOR` or `STEPPED` or so. When string is pasted on a property then
code tries to set this identifier to active in enum.

This mean to works in 100% when this is different instances of the same
enum in different copies of the same node. But there are a bunch of
nodes with the same enum but different identifiers of items (`VECTOR`
vs `FLOAT_VECTOR`) so this is not always possible to propagate
specific enum value between some node groups.

Pull Request: https://projects.blender.org/blender/blender/pulls/152533
This commit is contained in:
Iliya Katushenock 2026-02-10 18:23:58 +01:00 • committed by Hans Goudey
parent 8aed1a1bc1
commit f84fc76b54

View file

@ -2791,14 +2791,73 @@ static void ui_but_copy_operator(bContext *C, Button *but, char *output, int out
BLI_strncpy_utf8(output, str.c_str(), output_maxncpy);
}
static bool ui_but_copy_menu(Button *but, char *output, int output_maxncpy)
static bool ui_but_copy_menu(bContext *C, Button *but, char *output, int output_maxncpy)
{
MenuType *mt = button_menutype_get(but);
if (mt) {
BLI_snprintf_utf8(output, output_maxncpy, "bpy.ops.wm.call_menu(name=\"%s\")", mt->idname);
return true;
}
return false;
PropertyRNA *prop = but->rnaprop;
if (prop == nullptr) {
return false;
}
const int type = RNA_property_type(prop);
if (type != PROP_ENUM) {
return false;
}
const int active_item = RNA_property_enum_get(&but->rnapoin, prop);
EnumPropertyItem item;
const bool found = RNA_property_enum_item_from_value(C, &but->rnapoin, prop, active_item, &item);
if (!found) {
return false;
}
if (item.identifier == nullptr) {
return false;
}
if (item.identifier == StringRef("")) {
return false;
}
BLI_strncpy_utf8(output, item.identifier, output_maxncpy);
return true;
}
static void ui_but_paste_menu(bContext *C, Button *but, const StringRef value)
{
if (button_menutype_get(but) != nullptr) {
return;
}
if (value.is_empty()) {
return;
}
PropertyRNA *prop = but->rnaprop;
if (prop == nullptr) {
return;
}
const int type = RNA_property_type(prop);
if (type != PROP_ENUM) {
return;
}
int item_index;
const bool found = RNA_property_enum_value(
C, &but->rnapoin, prop, std::string(value).c_str(), &item_index);
if (!found) {
WM_global_reportf(
RPT_ERROR, "Paste of \"%s\": cannot assign value to property", std::string(value).c_str());
return;
}
RNA_property_enum_set(&but->rnapoin, prop, item_index);
RNA_property_update(C, &but->rnapoin, prop);
}
static bool ui_but_copy_popover(Button *but, char *output, int output_maxncpy)
@ -2887,9 +2946,10 @@ static bool ui_but_copy(bContext *C, Button *but, const bool copy_array)
is_buf_set = true;
break;
case ButtonType::Row:
case ButtonType::Menu:
case ButtonType::Pulldown:
if (ui_but_copy_menu(but, buf, buf_maxncpy)) {
if (ui_but_copy_menu(C, but, buf, buf_maxncpy)) {
is_buf_set = true;
}
break;
@ -2972,6 +3032,12 @@ static void ui_but_paste(bContext *C, Button *but, HandleButtonData *data, const
case ButtonType::CurveProfile:
ui_but_paste_CurveProfile(C, but);
break;
case ButtonType::Row:
case ButtonType::Menu:
ui_but_paste_menu(C, but, {buf_paste, buf_paste_len});
break;
case ButtonType::ViewItem: {
ButtonViewItem *viewitem_but = static_cast<ButtonViewItem *>(but);
viewitem_but->view_item->rename(*C, buf_paste);