From 67002402bd60d701acaf9e22801bc4411ded21d7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Jul 2020 17:24:17 +1000 Subject: Fix T79162: 'prop_search' includes ID prefix in string properties Regression from d6cefef98f87a This also fixes an unreported issue where finding an exact match wasn't being detected for items that contained an ID prefix. --- source/blender/blenkernel/BKE_lib_id.h | 3 +- source/blender/blenkernel/intern/lib_id.c | 10 ++++- source/blender/editors/include/UI_interface.h | 8 +++- source/blender/editors/interface/interface.c | 3 +- .../editors/interface/interface_region_search.c | 50 +++++++++++++++++++--- .../interface/interface_template_search_menu.c | 2 +- .../interface/interface_template_search_operator.c | 2 +- .../editors/interface/interface_templates.c | 12 ++++-- source/blender/editors/interface/interface_utils.c | 14 ++++-- source/blender/editors/space_node/node_select.c | 2 +- .../editors/space_outliner/outliner_tools.c | 2 +- 11 files changed, 85 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 76bae6fa909..d46a03e90af 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -267,7 +267,8 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id, char void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id, const bool add_lib_hint, - char separator_char); + char separator_char, + int *r_prefix_len); char *BKE_id_to_unique_string_key(const struct ID *id); diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index eb440de1a6f..a64e550579d 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -2161,7 +2161,7 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa /** * Generate full name of the data-block (without ID code, but with library if any), - * with a 3-character prefix prepended indicating whether it comes from a library, + * with a 2 to 3 character prefix prepended indicating whether it comes from a library, * is overriding, has a fake or no user, etc. * * \note Result is unique to a given ID type in a given Main database. @@ -2170,11 +2170,13 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa * will be filled with generated string. * \param separator_char: Character to use for separating name and library name. Can be 0 to use * default (' '). + * \param r_prefix_len: The length of the prefix added. */ void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const ID *id, const bool add_lib_hint, - char separator_char) + char separator_char, + int *r_prefix_len) { int i = 0; @@ -2185,6 +2187,10 @@ void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], name[i++] = ' '; BKE_id_full_name_get(name + i, id, separator_char); + + if (r_prefix_len) { + *r_prefix_len = i; + } } /** diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7ce74a87ea0..e0bd1369a51 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1575,7 +1575,13 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, const bool compact); /* use inside searchfunc to add items */ -bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state); +bool UI_search_item_add(uiSearchItems *items, + const char *name, + void *poin, + int iconid, + int state, + uint8_t name_prefix_offset); + void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 106145005bd..12ff147b0a1 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -6431,7 +6431,8 @@ static void operator_enum_search_update_fn(const struct bContext *C, /* note: need to give the index rather than the * identifier because the enum can be freed */ if (BLI_strcasestr(item->name, str)) { - if (!UI_search_item_add(items, item->name, POINTER_FROM_INT(item->value), item->icon, 0)) { + if (!UI_search_item_add( + items, item->name, POINTER_FROM_INT(item->value), item->icon, 0, 0)) { break; } } diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 307bab5ad79..a9e87f4cc07 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -76,6 +76,7 @@ struct uiSearchItems { void **pointers; int *icons; int *states; + uint8_t *name_prefix_offsets; /** Is there any item with an icon? */ bool has_icon; @@ -117,7 +118,12 @@ typedef struct uiSearchboxData { * typically #UI_BUT_DISABLED / #UI_BUT_INACTIVE. * \return false if there is nothing to add. */ -bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state) +bool UI_search_item_add(uiSearchItems *items, + const char *name, + void *poin, + int iconid, + int state, + const uint8_t name_prefix_offset) { /* hijack for autocomplete */ if (items->autocpl) { @@ -159,6 +165,15 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int items->icons[items->totitem] = iconid; } + if (name_prefix_offset != 0) { + /* Lazy initialize, as this isn't used often. */ + if (items->name_prefix_offsets == NULL) { + items->name_prefix_offsets = MEM_callocN( + items->maxitem * sizeof(*items->name_prefix_offsets), "search name prefix offsets"); + } + items->name_prefix_offsets[items->totitem] = name_prefix_offset; + } + /* Limit flags that can be set so flags such as 'UI_SELECT' aren't accidentally set * which will cause problems, add others as needed. */ BLI_assert( @@ -184,10 +199,18 @@ int UI_searchbox_size_x(void) int UI_search_items_find_index(uiSearchItems *items, const char *name) { - int i; - for (i = 0; i < items->totitem; i++) { - if (STREQ(name, items->names[i])) { - return i; + if (items->name_prefix_offsets != NULL) { + for (int i = 0; i < items->totitem; i++) { + if (STREQ(name, items->names[i] + items->name_prefix_offsets[i])) { + return i; + } + } + } + else { + for (int i = 0; i < items->totitem; i++) { + if (STREQ(name, items->names[i])) { + return i; + } } } return -1; @@ -283,7 +306,12 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region) but->func_arg2 = NULL; if (data->active != -1) { - const char *name = data->items.names[data->active]; + const char *name = data->items.names[data->active] + + /* Never include the prefix in the button. */ + (data->items.name_prefix_offsets ? + data->items.name_prefix_offsets[data->active] : + 0); + const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL; BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) + 1 : data->items.maxstrlen); @@ -472,7 +500,10 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re int a; for (a = 0; a < data->items.totitem; a++) { - const char *name = data->items.names[a]; + const char *name = data->items.names[a] + + /* Never include the prefix in the button. */ + (data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] : + 0); const char *name_sep = data->use_sep ? strrchr(name, UI_SEP_CHAR) : NULL; if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) { data->active = a; @@ -634,6 +665,10 @@ static void ui_searchbox_region_free_cb(ARegion *region) MEM_freeN(data->items.icons); MEM_freeN(data->items.states); + if (data->items.name_prefix_offsets != NULL) { + MEM_freeN(data->items.name_prefix_offsets); + } + MEM_freeN(data); region->regiondata = NULL; } @@ -802,6 +837,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers"); data->items.icons = MEM_callocN(data->items.maxitem * sizeof(int), "search icons"); data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags"); + data->items.name_prefix_offsets = NULL; /* Lazy initialized as needed. */ for (i = 0; i < data->items.maxitem; i++) { data->items.names[i] = MEM_callocN(but->hardmax + 1, "search pointers"); } diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index ad5f897e5fe..0708714c659 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -1009,7 +1009,7 @@ static void menu_search_update_fn(const bContext *UNUSED(C), } if (index == words_len) { - if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) { + if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state, 0)) { break; } } diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c index cdf87103587..b8070ccbb25 100644 --- a/source/blender/editors/interface/interface_template_search_operator.c +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -109,7 +109,7 @@ static void operator_search_update_fn(const bContext *C, } } - if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) { + if (!UI_search_item_add(items, name, ot, ICON_NONE, 0, 0)) { break; } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 21696b9c1ab..d3487b635ce 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -367,13 +367,19 @@ static bool id_search_add(const bContext *C, /* When using previews, the library hint (linked, overridden, missing) is added with a * character prefix, otherwise we can use a icon. */ - BKE_id_full_name_ui_prefix_get(name_ui, id, use_lib_prefix, UI_SEP_CHAR); + int name_prefix_offset; + BKE_id_full_name_ui_prefix_get( + name_ui, id, use_lib_prefix, UI_SEP_CHAR, &name_prefix_offset); if (!use_lib_prefix) { iconid = UI_library_icon_get(id); } - if (!UI_search_item_add( - items, name_ui, id, iconid, has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0)) { + if (!UI_search_item_add(items, + name_ui, + id, + iconid, + has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0, + name_prefix_offset)) { return false; } } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 24f90f6b0a0..208fd7136da 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -382,6 +382,7 @@ typedef struct CollItemSearch { int index; int iconid; bool is_id; + int name_prefix_offset; uint has_sep_char : 1; } CollItemSearch; @@ -432,6 +433,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, } } + int name_prefix_offset = 0; int iconid = ICON_NONE; bool has_sep_char = false; bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type); @@ -447,7 +449,8 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, } else { const ID *id = itemptr.data; - BKE_id_full_name_ui_prefix_get(name_buf, itemptr.data, true, UI_SEP_CHAR); + BKE_id_full_name_ui_prefix_get( + name_buf, itemptr.data, true, UI_SEP_CHAR, &name_prefix_offset); BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI, "Name string buffer should be big enough to hold full UI ID name"); name = name_buf; @@ -459,13 +462,14 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, } if (name) { - if (skip_filter || BLI_strcasestr(name, str)) { + if (skip_filter || BLI_strcasestr(name + name_prefix_offset, str)) { cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch"); cis->data = itemptr.data; cis->name = BLI_strdup(name); cis->index = i; cis->iconid = iconid; cis->is_id = is_id; + cis->name_prefix_offset = name_prefix_offset; cis->has_sep_char = has_sep_char; BLI_addtail(items_list, cis); } @@ -484,11 +488,12 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, for (cis = items_list->first; cis; cis = cis->next) { /* If no item has an own icon to display, libraries can use the library icons rather than the * name prefix for showing the library status. */ + int name_prefix_offset = cis->name_prefix_offset; if (!has_id_icon && cis->is_id) { cis->iconid = UI_library_icon_get(cis->data); /* No need to re-allocate, string should be shorter than before (lib status prefix is * removed). */ - BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR); + BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR, &name_prefix_offset); BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name)); strcpy(cis->name, name_buf); } @@ -497,7 +502,8 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, cis->name, cis->data, cis->iconid, - cis->has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0)) { + cis->has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0, + name_prefix_offset)) { break; } } diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 316ba3fd2e4..90b824811d9 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -1182,7 +1182,7 @@ static void node_find_update_fn(const struct bContext *C, else { BLI_strncpy(name, node->name, 256); } - if (!UI_search_item_add(items, name, node, ICON_NONE, 0)) { + if (!UI_search_item_add(items, name, node, ICON_NONE, 0, 0)) { break; } } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index b59cd5bc128..6b998828c77 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -543,7 +543,7 @@ static void merged_element_search_cb_recursive( /* Don't allow duplicate named items */ if (UI_search_items_find_index(items, name) == -1) { - if (!UI_search_item_add(items, name, te, iconid, 0)) { + if (!UI_search_item_add(items, name, te, iconid, 0, 0)) { break; } } -- cgit v1.2.3