UI: support adding a search weight to menu entries for menu-search

The goal is to support better search experience in the cases where we want to
explicitly influence the ordering instead of relying only on general heuristics.
We used to support this already at some point I think, but not anymore since we
started using menu-search.

The implementation is fairly straight forward. It mainly just forwards the
search weight from the menu definition to the search code through various
required steps. The main annoying thing is that changing the signature of e.g.
`uiItemFullO_ptr` is fairly involved. Even using default parameters for these
functions is a bit annoying and becomes fairly unreadable and error-prone on the
call-site. For now, I worked around this by storing the search weight on the
`uiLayout` and to copy it to the `uiBut` from there. That seems preferable until
we have a better solution for adding parameters to all the `uiItem*` functions.

Pull Request: https://projects.blender.org/blender/blender/pulls/120572
This commit is contained in:
Jacques Lucke
2024-04-16 12:18:45 +02:00
parent 757da9dbc1
commit d1634b2a4a
7 changed files with 44 additions and 6 deletions

View File

@@ -11,7 +11,7 @@ from bpy.app.translations import (
)
def add_node_type(layout, node_type, *, label=None, poll=None):
def add_node_type(layout, node_type, *, label=None, poll=None, search_weight=0.0):
"""Add a node type to a menu."""
bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type)
if not label:
@@ -19,7 +19,7 @@ def add_node_type(layout, node_type, *, label=None, poll=None):
if poll is True or poll is None:
translation_context = bl_rna.translation_context if bl_rna else i18n_contexts.default
props = layout.operator("node.add_node", text=label, text_ctxt=translation_context)
props = layout.operator("node.add_node", text=label, text_ctxt=translation_context, search_weight=search_weight)
props.type = node_type
props.use_transform = True
return props

View File

@@ -169,7 +169,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeGeometryToInstance")
node_add_menu.add_node_type(layout, "GeometryNodeJoinGeometry")
node_add_menu.add_node_type(layout, "GeometryNodeJoinGeometry", search_weight=1.0)
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
@@ -216,7 +216,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeDuplicateElements")
node_add_menu.add_node_type(layout, "GeometryNodeMergeByDistance")
node_add_menu.add_node_type(layout, "GeometryNodeSortElements")
node_add_menu.add_node_type(layout, "GeometryNodeTransform")
node_add_menu.add_node_type(layout, "GeometryNodeTransform", search_weight=1.0)
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
node_add_menu.add_node_type(layout, "GeometryNodeSeparateGeometry")

View File

@@ -2209,6 +2209,7 @@ void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss);
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
int uiLayoutGetLocalDir(const uiLayout *layout);
void uiLayoutSetSearchWeight(uiLayout *layout, float weight);
wmOperatorCallContext uiLayoutGetOperatorContext(uiLayout *layout);
bool uiLayoutGetActive(uiLayout *layout);
@@ -2228,6 +2229,7 @@ eUIEmbossType uiLayoutGetEmboss(uiLayout *layout);
bool uiLayoutGetPropSep(uiLayout *layout);
bool uiLayoutGetPropDecorate(uiLayout *layout);
Panel *uiLayoutGetRootPanel(uiLayout *layout);
float uiLayoutGetSearchWeight(uiLayout *layout);
/* Layout create functions. */

View File

@@ -245,6 +245,9 @@ struct uiBut {
uchar unit_type = 0;
short iconadd = 0;
/** Affects the order if this uiBut is used in menu-search. */
float search_weight = 0.0f;
/** #UI_BTYPE_BLOCK data */
uiBlockCreateFunc block_create_func = nullptr;

View File

@@ -167,6 +167,8 @@ struct uiLayout {
eUIEmbossType emboss;
/** for fixed width or height to avoid UI size changes */
float units[2];
/** Is copied to uiButs created in this layout. */
float search_weight;
};
struct uiLayoutItemFlow {
@@ -5273,6 +5275,16 @@ void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
}
void uiLayoutSetSearchWeight(uiLayout *layout, const float weight)
{
layout->search_weight = weight;
}
float uiLayoutGetSearchWeight(uiLayout *layout)
{
return layout->search_weight;
}
Panel *uiLayoutGetRootPanel(uiLayout *layout)
{
return layout->root->block->panel;
@@ -5856,6 +5868,7 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
BLI_addtail(&layout->items, bitem);
}
but->layout = layout;
but->search_weight = layout->search_weight;
if (layout->context) {
but->context = layout->context;

View File

@@ -84,6 +84,7 @@ struct MenuSearch_Item {
const char *drawwstr_full;
int icon;
int state;
float weight;
MenuSearch_Parent *menu_parent;
MenuType *mt;
@@ -175,6 +176,7 @@ static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
item->type = MenuSearch_Item::Type::Operator;
item->weight = but->search_weight;
item->op.type = but->optype;
item->op.opcontext = but->opcontext;
@@ -218,6 +220,7 @@ static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
else {
item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
item->type = MenuSearch_Item::Type::RNA;
item->weight = but->search_weight;
item->rna.ptr = but->rnapoin;
item->rna.prop = but->rnaprop;
@@ -1007,7 +1010,7 @@ static void menu_search_update_fn(const bContext * /*C*/,
blender::ui::string_search::StringSearch<MenuSearch_Item> search;
LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
search.add(item->drawwstr_full, item);
search.add(item->drawwstr_full, item, item->weight);
}
const blender::Vector<MenuSearch_Item *> filtered_items = search.query(str);

View File

@@ -335,7 +335,8 @@ static PointerRNA rna_uiItemO(uiLayout *layout,
int icon,
bool emboss,
bool depress,
int icon_value)
int icon_value,
const float search_weight)
{
wmOperatorType *ot;
@@ -359,9 +360,14 @@ static PointerRNA rna_uiItemO(uiLayout *layout,
flag |= UI_ITEM_O_DEPRESS;
}
const float prev_weight = uiLayoutGetSearchWeight(layout);
uiLayoutSetSearchWeight(layout, search_weight);
PointerRNA opptr;
uiItemFullO_ptr(
layout, ot, name, icon, nullptr, uiLayoutGetOperatorContext(layout), flag, &opptr);
uiLayoutSetSearchWeight(layout, prev_weight);
return opptr;
}
@@ -1387,6 +1393,17 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "menu", nullptr, 0, "", "Identifier of the menu");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
}
else {
RNA_def_float(func,
"search_weight",
0.0f,
-FLT_MAX,
FLT_MAX,
"Search Weight",
"Influences the sorting when using menu-seach",
-FLT_MAX,
FLT_MAX);
}
parm = RNA_def_pointer(
func, "properties", "OperatorProperties", "", "Operator properties to fill in");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED | PARM_RNAPTR);