UI: Outliner "File Mode" Manage User Count #118691

Merged
Harley Acheson merged 10 commits from Harley/blender:OutlinerUserCount into main 2024-04-20 02:50:21 +02:00
6 changed files with 89 additions and 47 deletions

View File

@ -1686,6 +1686,8 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name);
*/
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number);
void UI_but_icon_indicator_set(uiBut *but, const char *string);
void UI_but_icon_indicator_color_set(uiBut *but, const uchar color[4]);
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]);

View File

@ -30,6 +30,7 @@ struct IconFile {
struct IconTextOverlay {
char text[5];
uchar color[4] = {0};
Review

I think the zero initialization here is unnecessary?

I think the zero initialization here is unnecessary?
Review

Weirdly it is. At least with my compiler...

uiBut initializes this like this:

IconTextOverlay icon_overlay_text = {};

And I would expect with C++17 that the above would recursively initialize all parts of this to zero. But instead I see the color value with initial 204 junk value instead. I have only managed to start off with zeros by initializing in the struct itself.

Weirdly it is. At least with my compiler... uiBut initializes this like this: ``` IconTextOverlay icon_overlay_text = {}; ``` And I would expect with C++17 that the above would recursively initialize all parts of this to zero. But instead I see the color value with initial 204 junk value instead. I have only managed to start off with zeros by initializing in the struct itself.
Review

Good to know! No big deal, thanks for checking.

Good to know! No big deal, thanks for checking.
};
#define UI_NO_ICON_OVERLAY_TEXT NULL

View File

@ -6258,6 +6258,16 @@ void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number)
UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number);
}
void UI_but_icon_indicator_set(uiBut *but, const char *string)
{
STRNCPY(but->icon_overlay_text.text, string);
}
void UI_but_icon_indicator_color_set(uiBut *but, const uchar color[4])
{
copy_v4_v4_uchar(but->icon_overlay_text.color, color);
}
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
{
but->flag |= UI_BUT_NODE_LINK;

View File

@ -1883,8 +1883,12 @@ static void icon_draw_texture(float x,
if (show_indicator) {
/* Handle the little numbers on top of the icon. */
uchar text_color[4];
UI_GetThemeColor3ubv(TH_TEXT, text_color);
text_color[3] = 255;
if (text_overlay->color[3]) {
copy_v4_v4_uchar(text_color, text_overlay->color);
}
else {
UI_GetThemeColor4ubv(TH_TEXT, text_color);
}
uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET;
fstyle_small.points *= zoom_factor;

View File

@ -1761,56 +1761,83 @@ static void outliner_draw_userbuts(uiBlock *block,
}
const TreeStoreElem *tselem = TREESTORE(te);
if (tselem->type != TSE_SOME_ID) {
ID *id = tselem->id;
if (tselem->type != TSE_SOME_ID || id->tag & LIB_TAG_EXTRAUSER) {
return;
}
uiBut *bt;
ID *id = tselem->id;
const char *tip = nullptr;
char buf[BLI_STR_FORMAT_INT32_GROUPED_SIZE] = "";
int but_flag = UI_BUT_DRAG_LOCK;
const int real_users = id->us - ID_FAKE_USERS(id);
const bool has_fake_user = id->flag & LIB_FAKEUSER;
const bool is_linked = ID_IS_LINKED(id);
const bool is_object = GS(id->name) == ID_OB;
char overlay[5];
BLI_str_format_integer_unit(overlay, id->us);
if (ID_IS_LINKED(id)) {
but_flag |= UI_BUT_DISABLED;
}
BLI_str_format_int_grouped(buf, id->us);
bt = uiDefBut(block,
UI_BTYPE_BUT,
1,
buf,
int(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
nullptr,
0.0,
0.0,
TIP_("Number of users of this data-block"));
UI_but_flag_enable(bt, but_flag);
if (id->flag & LIB_FAKEUSER) {
tip = TIP_("Data-block will be retained using a fake user");
if (is_object) {
bt = uiDefBut(block,
UI_BTYPE_BUT,
0,
overlay,
int(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
nullptr,
0.0,
0.0,
TIP_("Number of users"));
}
else {
tip = TIP_("Data-block has no users and will be deleted");
if (has_fake_user) {
tip = is_linked ? TIP_("Item is protected from deletion") :
TIP_("Click to remove protection from deletion");
}
else {
if (real_users) {
tip = is_linked ? TIP_("Item is not protected from deletion") :
TIP_("Click to add protection from deletion");
}
else {
tip = is_linked ?
TIP_("Item has no users and will be removed") :
TIP_("Item has no users and will be removed.\nClick to protect from deletion");
}
}
bt = uiDefIconButBitS(block,
UI_BTYPE_ICON_TOGGLE,
LIB_FAKEUSER,
1,
ICON_FAKE_USER_OFF,
int(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
&id->flag,
0,
0,
tip);
if (is_linked) {
UI_but_flag_enable(bt, UI_BUT_DISABLED);
}
else {
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, nullptr);
/* Allow _inaccurate_ dragging over multiple toggles. */

Could you add a comment about why UI_BUT_DRAG_LOCK is set here? I think it was discussed in the PR but I'm not sure myself here now.

Could you add a comment about why `UI_BUT_DRAG_LOCK` is set here? I think it was discussed in the PR but I'm not sure myself here now.

I'm not adding this flag here, it is also set here in existing code.

But I wasn't sure what it did to be honest until now. It does not enable you to drag down a column of items to set/unset them all at once easily - that is allowed regardless.

What this adds is it allows you to drag inaccurately once dragging starts. Without this flag you must stay within the bounds of the checkboxes, but with it you can veer off quite a bit and it will toggle them. Nice feature.

Will add a comment.

I'm not adding this flag here, it is also set here in existing code. But I wasn't sure what it did to be honest until now. It does not enable you to drag down a column of items to set/unset them all at once easily - that is allowed regardless. What this adds is it allows you to drag **inaccurately** once dragging starts. Without this flag you must stay within the bounds of the checkboxes, but with it you can veer off quite a bit and it will toggle them. Nice feature. Will add a comment.
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
if (!real_users && !has_fake_user) {
uchar overlay_color[4];
UI_GetThemeColor4ubv(TH_REDALERT, overlay_color);
UI_but_icon_indicator_color_set(bt, overlay_color);
}
UI_but_icon_indicator_set(bt, overlay);
}
bt = uiDefIconButBitS(block,
UI_BTYPE_ICON_TOGGLE,
LIB_FAKEUSER,
1,
ICON_FAKE_USER_OFF,
int(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
&id->flag,
0,
0,
tip);
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, nullptr);
UI_but_flag_enable(bt, but_flag);
});
}
@ -4040,8 +4067,7 @@ void draw_outliner(const bContext *C)
outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x);
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
}
else if (space_outliner->outlinevis == SO_ID_ORPHANS) {
/* draw user toggle columns */
else if (ELEM(space_outliner->outlinevis, SO_ID_ORPHANS, SO_LIBRARIES)) {
outliner_draw_userbuts(block, region, space_outliner);
}
else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {

View File

@ -203,8 +203,7 @@ enum eOLSetState {
/* size constants */
#define OL_Y_OFFSET 2
#define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X + V2D_SCROLL_WIDTH)
#define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 1.2f + V2D_SCROLL_WIDTH)
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)