UI: support operator enums in Quick Favorites #107616

Merged
Philipp Oeser merged 5 commits from lichtwerk/blender:59244 into main 2023-05-08 09:14:52 +02:00
4 changed files with 63 additions and 12 deletions

View File

@ -609,9 +609,15 @@ bool ED_operator_camera_poll(struct bContext *C);
bUserMenu **ED_screen_user_menus_find(const struct bContext *C, uint *r_len);
struct bUserMenu *ED_screen_user_menu_ensure(struct bContext *C);
/** Finds a menu item associated with an operator in user menus (aka Quick Favorites)
*
* \param op_prop_enum: name of an operator property when the operator is called with an enum (to
* be an empty string otherwise)

Doc-string should note this is to be an empty string when not set.

Doc-string should note this is to be an empty string when not set.

done

done
*/
struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(struct ListBase *lb,
const struct wmOperatorType *ot,
struct IDProperty *prop,
const char *op_prop_enum,
wmOperatorCallContext opcontext);
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(struct ListBase *lb,
const struct MenuType *mt);
@ -624,6 +630,7 @@ void ED_screen_user_menu_item_add_operator(struct ListBase *lb,
const char *ui_name,
const struct wmOperatorType *ot,
const struct IDProperty *prop,
const char *op_prop_enum,
wmOperatorCallContext opcontext);
void ED_screen_user_menu_item_add_menu(struct ListBase *lb,
const char *ui_name,

View File

@ -326,6 +326,9 @@ static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but)
else if (UI_but_menutype_get(but)) {
result = true;
}
else if (UI_but_operatortype_get_from_enum_menu(but, nullptr)) {
result = true;
}
return result;
}
@ -335,7 +338,7 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *
if (but->optype) {
IDProperty *prop = (but->opptr) ? static_cast<IDProperty *>(but->opptr->data) : nullptr;
return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
&um->items, but->optype, prop, but->opcontext);
&um->items, but->optype, prop, "", but->opcontext);
}
if (but->rnaprop) {
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
@ -346,6 +349,13 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *
return umi;
}
wmOperatorType *ot = nullptr;
PropertyRNA *prop_enum = nullptr;
if ((ot = UI_but_operatortype_get_from_enum_menu(but, &prop_enum))) {
return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
&um->items, ot, nullptr, RNA_property_identifier(prop_enum), but->opcontext);
}
MenuType *mt = UI_but_menutype_get(but);
if (mt != nullptr) {
return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(&um->items, mt);
@ -360,7 +370,11 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
char drawstr[sizeof(but->drawstr)];
ui_but_drawstr_without_sep_char(but, drawstr, sizeof(drawstr));
/* Used for USER_MENU_TYPE_MENU. */
MenuType *mt = nullptr;
/* Used for USER_MENU_TYPE_OPERATOR (property enum used). */
wmOperatorType *ot = nullptr;
PropertyRNA *prop = nullptr;
if (but->optype) {
if (drawstr[0] == '\0') {
/* Hard code overrides for generic operators. */
@ -397,6 +411,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
drawstr,
but->optype,
but->opptr ? static_cast<const IDProperty *>(but->opptr->data) : nullptr,
"",
but->opcontext);
}
else if (but->rnaprop) {
@ -410,6 +425,14 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
else if ((mt = UI_but_menutype_get(but))) {
ED_screen_user_menu_item_add_menu(&um->items, drawstr, mt);
}
else if ((ot = UI_but_operatortype_get_from_enum_menu(but, &prop))) {
ED_screen_user_menu_item_add_operator(&um->items,
WM_operatortype_name(ot, nullptr),
ot,
nullptr,
RNA_property_identifier(prop),
but->opcontext);
}
}
static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void * /*arg2*/)

View File

@ -97,13 +97,18 @@ bUserMenu *ED_screen_user_menu_ensure(bContext *C)
bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
const wmOperatorType *ot,
IDProperty *prop,
const char *op_prop_enum,
wmOperatorCallContext opcontext)
{
LISTBASE_FOREACH (bUserMenuItem *, umi, lb) {
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
if (STREQ(ot->idname, umi_op->op_idname) && (opcontext == umi_op->opcontext) &&
IDP_EqualsProperties(prop, umi_op->prop))
const bool ok_idprop = prop ? IDP_EqualsProperties(prop, umi_op->prop) : true;
const bool ok_prop_enum = (umi_op->op_prop_enum[0] != '\0') ?
STREQ(umi_op->op_prop_enum, op_prop_enum) :
true;
if (STREQ(ot->idname, umi_op->op_idname) && (opcontext == umi_op->opcontext) && ok_idprop &&
ok_prop_enum)
{
return umi_op;
}
@ -148,6 +153,7 @@ void ED_screen_user_menu_item_add_operator(ListBase *lb,
const char *ui_name,
const wmOperatorType *ot,
const IDProperty *prop,
const char *op_prop_enum,
wmOperatorCallContext opcontext)
{
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(
@ -157,6 +163,7 @@ void ED_screen_user_menu_item_add_operator(ListBase *lb,
STRNCPY(umi_op->item.ui_name, ui_name);
}
STRNCPY(umi_op->op_idname, ot->idname);
STRNCPY(umi_op->op_prop_enum, op_prop_enum);
umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL;
}
@ -216,15 +223,28 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
wmOperatorType *ot = WM_operatortype_find(umi_op->op_idname, false);
if (ot != NULL) {
IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
uiItemFullO_ptr(menu->layout,
ot,
CTX_IFACE_(ot->translation_context, ui_name),
ICON_NONE,
prop,
umi_op->opcontext,
0,
NULL);
if (umi_op->op_prop_enum[0] == '\0') {
IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
uiItemFullO_ptr(menu->layout,
ot,
CTX_IFACE_(ot->translation_context, ui_name),
ICON_NONE,
prop,
umi_op->opcontext,
0,
NULL);
}
else {
/* umi_op->prop could be used to set other properties but it's currently unsupported.
*/
uiItemMenuEnumFullO_ptr(menu->layout,
Review

It's possible we want to support assigning additional properties even with op_prop_enum set, although I'm not sure if there are practical cases which would use this of hand.

Nevertheless, it's worth adding a comment that umi_op->prop could be used to set other properties but it's currently unsupported.

It's possible we want to support assigning additional properties even with `op_prop_enum` set, although I'm not sure if there are practical cases which would use this of hand. Nevertheless, it's worth adding a comment that `umi_op->prop` could be used to set other properties but it's currently unsupported.
Review

added that comment

added that comment
C,
ot,
umi_op->op_prop_enum,
CTX_IFACE_(ot->translation_context, ui_name),
ICON_NONE,
NULL);
}
is_empty = false;
}
else {

View File

@ -565,6 +565,7 @@ typedef struct bUserMenuItem_Op {
bUserMenuItem item;
char op_idname[64];
struct IDProperty *prop;
char op_prop_enum[64];
char opcontext; /* #wmOperatorCallContext */
char _pad0[7];
} bUserMenuItem_Op;