Refactor: UI: Replace uiItemsEnumO with class method uiLayout::op_enum

This converts the public uiItemsEnumO and uiItemsFullEnumO functions
to an object-oriented API (as uiLayout::op_enum overloads), matching
recent changes in the API.

Part of: #117604

Pull Request: https://projects.blender.org/blender/blender/pulls/141748
This commit is contained in:
Guillermo Venegas
2025-07-11 15:25:30 +02:00
committed by Hans Goudey
parent db39daf9e7
commit 1f34dc9155
11 changed files with 91 additions and 105 deletions

View File

@@ -434,7 +434,7 @@ static wmOperatorStatus keyingset_active_menu_invoke(bContext *C,
/* Call the menu, which will call this operator again, hence the canceled. */
pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type");
layout->op_enum("ANIM_OT_keying_set_active_set", "type");
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;

View File

@@ -5971,7 +5971,7 @@ static wmOperatorStatus toggle_cyclic_invoke(bContext *C,
if (nu->type == CU_NURBS) {
pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, op->type->idname, "direction");
layout->op_enum(op->type->idname, "direction");
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}

View File

@@ -445,6 +445,41 @@ struct uiLayout : uiItem, blender::NonCopyable, blender::NonMovable {
int icon,
wmOperatorCallContext context,
eUI_Item_Flag flag);
/**
* Expands and sets each enum property value as an operator button.
* \param propname: Name of the operator's enum property.
* \param properties: Extra operator properties values to set.
* \param active: an optional item to highlight.
*/
void op_enum(blender::StringRefNull opname,
blender::StringRefNull propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const int active = -1);
/**
* Expands and sets each enum property value as an operator button.
* \param propname: Name of the operator's enum property.
*/
void op_enum(blender::StringRefNull opname, blender::StringRefNull propname);
/**
* Expands and sets each enum property value as an operator button.
* \param prop: Operator's enum property.
* \param properties: Extra operator properties values to set.
* \param item_array: Precalculated item array, could be a subset of the enum property values.
* \param active: an optional item to highlight.
*/
void op_enum_items(wmOperatorType *ot,
const PointerRNA &ptr,
PropertyRNA *prop,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem,
int active = -1);
/**
* Adds a operator item, places a button in the layout to call the operator, if the button is
* held down, a menu will be displayed instead.
@@ -837,41 +872,6 @@ void uiLayoutListItemAddPadding(uiLayout *layout);
bool uiLayoutEndsWithPanelHeader(const uiLayout &layout);
/* items */
void uiItemsEnumO(uiLayout *layout,
blender::StringRefNull opname,
blender::StringRefNull propname);
/**
* Create a list of enum items.
*
* \param active: an optional item to highlight.
*/
void uiItemsFullEnumO(uiLayout *layout,
blender::StringRefNull opname,
blender::StringRefNull propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const int active = -1);
/**
* Create UI items for enum items in \a item_array.
*
* A version of #uiItemsFullEnumO that takes pre-calculated item array.
* \param active: if not -1, will highlight that item.
*/
void uiItemsFullEnumO_items(uiLayout *layout,
wmOperatorType *ot,
const PointerRNA &ptr,
PropertyRNA *prop,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem,
int active = -1);
struct uiPropertySplitWrapper {
uiLayout *label_column;
uiLayout *property_row;

View File

@@ -1400,16 +1400,15 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout)
(layout->root_->type == blender::ui::LayoutType::PieMenu));
}
void uiItemsFullEnumO_items(uiLayout *layout,
wmOperatorType *ot,
const PointerRNA &ptr,
PropertyRNA *prop,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem,
int active)
void uiLayout::op_enum_items(wmOperatorType *ot,
const PointerRNA &ptr,
PropertyRNA *prop,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const EnumPropertyItem *item_array,
int totitem,
int active)
{
const StringRefNull propname = RNA_property_identifier(prop);
if (RNA_property_type(prop) != PROP_ENUM) {
@@ -1418,16 +1417,16 @@ void uiItemsFullEnumO_items(uiLayout *layout,
}
uiLayout *target, *split = nullptr;
uiBlock *block = layout->block();
const bool radial = ui_layout_is_radial(layout);
uiBlock *block = this->block();
const bool radial = ui_layout_is_radial(this);
if (radial) {
target = &layout->menu_pie();
target = &this->menu_pie();
}
else if ((layout->local_direction() == blender::ui::LayoutDirection::Horizontal) &&
else if ((this->local_direction() == blender::ui::LayoutDirection::Horizontal) &&
(flag & UI_ITEM_R_ICON_ONLY))
{
target = layout;
target = this;
UI_block_layout_set_current(block, target);
/* Add a blank button to the beginning of the row. */
@@ -1445,8 +1444,8 @@ void uiItemsFullEnumO_items(uiLayout *layout,
std::nullopt);
}
else {
split = &layout->split(0.0f, false);
target = &split->column(layout->align_);
split = &this->split(0.0f, false);
target = &split->column(align_);
}
bool last_iter = false;
@@ -1497,7 +1496,7 @@ void uiItemsFullEnumO_items(uiLayout *layout,
else {
if (item->name) {
if (item != item_array && !radial && split != nullptr) {
target = &split->column(layout->align_);
target = &split->column(align_);
}
uiBut *but;
@@ -1540,18 +1539,17 @@ void uiItemsFullEnumO_items(uiLayout *layout,
}
}
void uiItemsFullEnumO(uiLayout *layout,
const StringRefNull opname,
const StringRefNull propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const int active)
void uiLayout::op_enum(const StringRefNull opname,
const StringRefNull propname,
IDProperty *properties,
wmOperatorCallContext context,
eUI_Item_Flag flag,
const int active)
{
wmOperatorType *ot = WM_operatortype_find(opname.c_str(), false); /* print error next */
if (!ot || !ot->srna) {
ui_item_disabled(layout, opname.c_str());
ui_item_disabled(this, opname.c_str());
RNA_warning("%s '%s'", ot ? "operator missing srna" : "unknown operator", opname.c_str());
return;
}
@@ -1565,13 +1563,13 @@ void uiItemsFullEnumO(uiLayout *layout,
/* don't let bad properties slip through */
BLI_assert((prop == nullptr) || (RNA_property_type(prop) == PROP_ENUM));
uiBlock *block = layout->block();
uiBlock *block = this->block();
if (prop && RNA_property_type(prop) == PROP_ENUM) {
const EnumPropertyItem *item_array = nullptr;
int totitem;
bool free;
if (ui_layout_is_radial(layout)) {
if (ui_layout_is_radial(this)) {
/* XXX: While "_all()" guarantees spatial stability,
* it's bad when an enum has > 8 items total,
* but only a small subset will ever be shown at once
@@ -1588,14 +1586,13 @@ void uiItemsFullEnumO(uiLayout *layout,
else {
bContext *C = static_cast<bContext *>(block->evil_C);
const bContextStore *previous_ctx = CTX_store_get(C);
CTX_store_set(C, layout->context_);
CTX_store_set(C, context_);
RNA_property_enum_items_gettexted(C, &ptr, prop, &item_array, &totitem, &free);
CTX_store_set(C, previous_ctx);
}
/* add items */
uiItemsFullEnumO_items(
layout, ot, ptr, prop, properties, context, flag, item_array, totitem, active);
this->op_enum_items(ot, ptr, prop, properties, context, flag, item_array, totitem, active);
if (free) {
MEM_freeN(item_array);
@@ -1611,9 +1608,9 @@ void uiItemsFullEnumO(uiLayout *layout,
}
}
void uiItemsEnumO(uiLayout *layout, const StringRefNull opname, const StringRefNull propname)
void uiLayout::op_enum(const StringRefNull opname, const StringRefNull propname)
{
uiItemsFullEnumO(layout, opname, propname, nullptr, layout->root_->opcontext, UI_ITEM_NONE);
this->op_enum(opname, propname, nullptr, root_->opcontext, UI_ITEM_NONE);
}
PointerRNA uiLayout::op(wmOperatorType *ot, const std::optional<StringRef> name, int icon)
@@ -3282,8 +3279,7 @@ static void menu_item_enum_opname_menu(bContext *C, uiLayout *layout, void *arg)
const int active = menu_item_enum_opname_menu_active(C, but, lvl);
layout->operator_context_set(lvl->opcontext);
uiItemsFullEnumO(
layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE, active);
layout->op_enum(lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE, active);
/* override default, needed since this was assumed pre 2.70 */
UI_block_direction_set(layout->block(), UI_DIR_DOWN);

View File

@@ -233,7 +233,7 @@ wmOperatorStatus UI_pie_menu_invoke(bContext *C, const char *idname, const wmEve
/** \name Pie Menu Levels
*
* Pie menus can't contain more than 8 items (yet).
* When using #uiItemsFullEnumO, a "More" button is created that calls
* When using ##uiLayout::operator_enum, a "More" button is created that calls
* a new pie menu if the enum has too many items. We call this a new "level".
* Indirect recursion is used, so that a theoretically unlimited number of items is supported.
*
@@ -249,7 +249,7 @@ struct PieMenuLevelData {
int icon; /* parent pie icon, copied for level */
int totitem; /* total count of *remaining* items */
/* needed for calling uiItemsFullEnumO_array again for new level */
/* needed for calling #uiLayout::operator_enum_items again for new level */
wmOperatorType *ot;
blender::StringRefNull propname;
IDProperty *properties;
@@ -279,15 +279,8 @@ static void ui_pie_menu_level_invoke(bContext *C, void *argN, void *arg2)
PropertyRNA *prop = RNA_struct_find_property(&ptr, lvl->propname.c_str());
if (prop) {
uiItemsFullEnumO_items(layout,
lvl->ot,
ptr,
prop,
lvl->properties,
lvl->context,
lvl->flag,
item_array,
lvl->totitem);
layout->op_enum_items(
lvl->ot, ptr, prop, lvl->properties, lvl->context, lvl->flag, item_array, lvl->totitem);
}
else {
RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), lvl->propname.c_str());

View File

@@ -1104,12 +1104,11 @@ static wmOperatorStatus unpack_single_bake_invoke(bContext *C,
layout = UI_popup_menu_layout(pup);
layout->operator_context_set(WM_OP_EXEC_DEFAULT);
uiItemsFullEnumO(layout,
op->type->idname,
"method",
static_cast<IDProperty *>(op->ptr->data),
WM_OP_EXEC_REGION_WIN,
UI_ITEM_NONE);
layout->op_enum(op->type->idname,
"method",
static_cast<IDProperty *>(op->ptr->data),
WM_OP_EXEC_REGION_WIN,
UI_ITEM_NONE);
UI_popup_menu_end(C, pup);

View File

@@ -273,7 +273,7 @@ static wmOperatorStatus unpack_all_invoke(bContext *C, wmOperator *op, const wmE
layout = UI_popup_menu_layout(pup);
layout->operator_context_set(WM_OP_EXEC_DEFAULT);
uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
layout->op_enum("FILE_OT_unpack_all", "method");
UI_popup_menu_end(C, pup);
@@ -367,12 +367,11 @@ static wmOperatorStatus unpack_item_invoke(bContext *C, wmOperator *op, const wm
layout = UI_popup_menu_layout(pup);
layout->operator_context_set(WM_OP_EXEC_DEFAULT);
uiItemsFullEnumO(layout,
op->type->idname,
"method",
static_cast<IDProperty *>(op->ptr->data),
WM_OP_EXEC_REGION_WIN,
UI_ITEM_NONE);
layout->op_enum(op->type->idname,
"method",
static_cast<IDProperty *>(op->ptr->data),
WM_OP_EXEC_REGION_WIN,
UI_ITEM_NONE);
UI_popup_menu_end(C, pup);

View File

@@ -3624,7 +3624,7 @@ static wmOperatorStatus outliner_operator_menu(bContext *C, const char *opname)
layout->operator_context_set(WM_OP_INVOKE_REGION_WIN);
if (WM_operator_poll(C, ot)) {
uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop));
layout->op_enum(ot->idname, RNA_property_identifier(ot->prop));
layout->separator();
}

View File

@@ -202,7 +202,7 @@ static wmOperatorStatus select_orientation_invoke(bContext *C,
pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
layout->op_enum("TRANSFORM_OT_select_orientation", "orientation");
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;

View File

@@ -432,7 +432,7 @@ static void rna_uiItemsEnumO(uiLayout *layout,
const bool icon_only)
{
eUI_Item_Flag flag = icon_only ? UI_ITEM_R_ICON_ONLY : UI_ITEM_NONE;
uiItemsFullEnumO(layout, opname, propname, nullptr, layout->operator_context(), flag);
layout->op_enum(opname, propname, nullptr, layout->operator_context(), flag);
}
static PointerRNA rna_uiItemMenuEnumO(uiLayout *layout,

View File

@@ -1107,12 +1107,11 @@ wmOperatorStatus WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallCo
uiLayout *layout = UI_popup_menu_layout(pup);
/* Set this so the default execution context is the same as submenus. */
layout->operator_context_set(opcontext);
uiItemsFullEnumO(layout,
op->type->idname,
RNA_property_identifier(prop),
static_cast<IDProperty *>(op->ptr->data),
opcontext,
UI_ITEM_NONE);
layout->op_enum(op->type->idname,
RNA_property_identifier(prop),
static_cast<IDProperty *>(op->ptr->data),
opcontext,
UI_ITEM_NONE);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}