UI: Show library status icons in search menus, rather than letter prefix

Rather than a `L` (linked), `O` (overridden) or `M` (missing) prefix for the
name, show the existing library status icons. See D7999 for screenshots.

Note that when using preview icons, or if the search menu contains items with
own icons (e.g. brush icons), we still fallback to the prefix solution.

Zero or fake user is still indicated with a prefix.

Differential Revision: https://developer.blender.org/D7999

Reviewed by: Bastien Montagne, William Reynish
This commit is contained in:
Julian Eisel 2020-06-29 17:19:43 +02:00
parent 5024c54271
commit 937d89afba
Notes: blender-bot 2024-03-22 15:57:27 +01:00
Referenced by commit 26d5c24f0a, Fix T80258: UILayout.prop_search() issues with datablock names
Referenced by issue #78588, Material preview not visible in selection list
8 changed files with 76 additions and 34 deletions

View File

@ -267,6 +267,7 @@ void BKE_main_id_repair_duplicate_names_listbase(struct ListBase *lb);
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id, char separator_str);
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 *BKE_id_to_unique_string_key(const struct ID *id);

View File

@ -2175,13 +2175,18 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa
*/
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)
{
name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
name[2] = ' ';
int i = 0;
BKE_id_full_name_get(name + 3, id, separator_char);
if (add_lib_hint) {
name[i++] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
}
name[i++] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
name[i++] = ' ';
BKE_id_full_name_get(name + i, id, separator_char);
}
/**

View File

@ -106,6 +106,7 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
int UI_idcode_icon_get(const int idcode);
int UI_library_icon_get(const struct ID *id);
#ifdef __cplusplus
}

View File

@ -2192,6 +2192,26 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
return iconid;
}
int UI_library_icon_get(const ID *id)
{
if (ID_IS_LINKED(id)) {
if (id->tag & LIB_TAG_MISSING) {
return ICON_LIBRARY_DATA_BROKEN;
}
else if (id->tag & LIB_TAG_INDIRECT) {
return ICON_LIBRARY_DATA_INDIRECT;
}
else {
return ICON_LIBRARY_DATA_DIRECT;
}
}
else if (ID_IS_OVERRIDE_LIBRARY(id)) {
return ICON_LIBRARY_DATA_OVERRIDE;
}
return ICON_NONE;
}
int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
{
ID *id = NULL;

View File

@ -77,6 +77,9 @@ struct uiSearchItems {
int *icons;
int *states;
/** Is there any item with an icon? */
bool has_icon;
AutoComplete *autocpl;
void *active;
};
@ -122,6 +125,10 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int
return true;
}
if (iconid) {
items->has_icon = true;
}
/* hijack for finding active item */
if (items->active) {
if (poin == items->active) {
@ -562,6 +569,10 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
/* widget itself */
if ((search_sep_len == 0) ||
!(name_sep_test = strstr(data->items.names[a], data->sep_string))) {
if (!icon && data->items.has_icon) {
/* If there is any icon item, make sure all items line up. */
icon = ICON_BLANK1;
}
/* Simple menu item. */
ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, use_sep_char, NULL);

View File

@ -361,11 +361,16 @@ static bool id_search_add(const bContext *C,
* followed by ID_NAME-2 characters from id->name
*/
char name_ui[MAX_ID_FULL_NAME_UI];
BKE_id_full_name_ui_prefix_get(name_ui, id, UI_SEP_CHAR);
int iconid = ui_id_icon_get(C, id, template_ui->preview);
bool has_sep_char = (id->lib != NULL);
/* When using previews, the library hint (linked, overriden, missing) is added with a
* character prefix, otherwise we can use a icon. */
BKE_id_full_name_ui_prefix_get(name_ui, id, template_ui->preview, UI_SEP_CHAR);
if (!template_ui->preview) {
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)) {
return false;

View File

@ -45,6 +45,7 @@
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "WM_api.h"
@ -384,6 +385,7 @@ typedef struct CollItemSearch {
char *name;
int index;
int iconid;
bool is_id;
uint has_sep_char : 1;
} CollItemSearch;
@ -418,6 +420,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
const bool skip_filter = data->search_but && !data->search_but->changed;
char name_buf[UI_MAX_DRAW_STR];
char *name;
bool has_id_icon = false;
/* build a temporary list of relevant items first */
RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
@ -437,16 +440,20 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
int iconid = ICON_NONE;
bool has_sep_char = false;
bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
if (is_id) {
iconid = ui_id_icon_get(C, itemptr.data, false);
if (!ELEM(iconid, 0, ICON_BLANK1)) {
has_id_icon = true;
}
if (requires_exact_data_name) {
name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
}
else {
const ID *id = itemptr.data;
BKE_id_full_name_ui_prefix_get(name_buf, id, UI_SEP_CHAR);
BKE_id_full_name_ui_prefix_get(name_buf, itemptr.data, true, UI_SEP_CHAR);
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;
@ -464,6 +471,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
cis->name = BLI_strdup(name);
cis->index = i;
cis->iconid = iconid;
cis->is_id = is_id;
cis->has_sep_char = has_sep_char;
BLI_addtail(items_list, cis);
}
@ -480,6 +488,17 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
/* add search items from temporary list */
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. */
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);
BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
strcpy(cis->name, name_buf);
}
if (!UI_search_item_add(items,
cis->name,
cis->data,

View File

@ -3108,33 +3108,13 @@ static void outliner_draw_tree_element(bContext *C,
offsx += 2 * ufac;
}
if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
if (tselem->id->tag & LIB_TAG_MISSING) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
(float)*starty + 2 * ufac,
ICON_LIBRARY_DATA_BROKEN,
alpha_fac);
if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
const BIFIconID lib_icon = UI_library_icon_get(tselem->id);
if (lib_icon != ICON_NONE) {
UI_icon_draw_alpha(
(float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, lib_icon, alpha_fac);
offsx += UI_UNIT_X + 4 * ufac;
}
else if (tselem->id->tag & LIB_TAG_INDIRECT) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
(float)*starty + 2 * ufac,
ICON_LIBRARY_DATA_INDIRECT,
alpha_fac);
}
else {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
(float)*starty + 2 * ufac,
ICON_LIBRARY_DATA_DIRECT,
alpha_fac);
}
offsx += UI_UNIT_X + 4 * ufac;
}
else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_OVERRIDE_LIBRARY(tselem->id)) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
(float)*starty + 2 * ufac,
ICON_LIBRARY_DATA_OVERRIDE,
alpha_fac);
offsx += UI_UNIT_X + 4 * ufac;
}
GPU_blend(false);