diff options
-rw-r--r-- | source/blender/editors/space_outliner/outliner_draw.c | 217 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_ID.h | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 1 |
3 files changed, 177 insertions, 42 deletions
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 75d9b256b91..4368b74f8a7 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -51,6 +51,7 @@ #include "BKE_deform.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_idcode.h" #include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" @@ -905,7 +906,7 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg, static void tselem_draw_icon( uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, - float alpha) + float alpha, const bool is_clickable) { struct DrawIconArg arg; float aspect; @@ -926,6 +927,7 @@ static void tselem_draw_icon( arg.y = y; #define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha) +#define ICON_CLICK_DRAW(_icon) if (!is_clickable) ICON_DRAW(_icon); else tselem_draw_icon_uibut(&arg, _icon) if (tselem->type) { switch (tselem->type) { @@ -1197,33 +1199,33 @@ static void tselem_draw_icon( Object *ob = (Object *)tselem->id; switch (ob->type) { case OB_LAMP: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LAMP); break; case OB_MESH: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_MESH); break; case OB_CAMERA: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_CAMERA); break; case OB_CURVE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_CURVE); break; case OB_MBALL: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_META); break; case OB_LATTICE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LATTICE); break; case OB_ARMATURE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_ARMATURE); break; case OB_FONT: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_FONT); break; case OB_SURF: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_SURFACE); break; case OB_SPEAKER: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_SPEAKER); break; case OB_LIGHTPROBE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break; + ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHTPROBE); break; case OB_EMPTY: if (ob->dup_group) { - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_GROUP_INSTANCE); + ICON_CLICK_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE); } else { - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); + ICON_CLICK_DRAW(ICON_OUTLINER_OB_EMPTY); } break; } @@ -1331,13 +1333,137 @@ static void tselem_draw_icon( #undef ICON_DRAW } +/** + * For icon-only children of a collapsed tree, + * Draw small number over the icon to show how many items of this type are displayed. + */ +static void outliner_draw_iconrow_number( + const uiFontStyle *fstyle, + int offsx, int ys, + const eOLDrawState active, + const int num_elements) +{ + float color[4] = {0.4f, 0.4f, 0.4f, 0.9f}; + copy_v3_fl(color, 0.2f); + if (active != OL_DRAWSEL_NONE) { + copy_v3_fl(color, 0.65f); + color[3] = 1.0f; + } + + float ufac = 0.25f * UI_UNIT_X; + float offset_x = (float) offsx + UI_UNIT_X * 0.35f; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, + offset_x + ufac, + (float)ys - UI_UNIT_Y * 0.2f + ufac, + offset_x + UI_UNIT_X - ufac, + (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, + (float)UI_UNIT_Y / 2.0f - ufac, + color); + + /* Now the numbers. */ + unsigned char text_col[4]; + + UI_GetThemeColor4ubv(TH_TEXT_HI, text_col); + text_col[3] = 255; + + uiFontStyle fstyle_small = *fstyle; + fstyle_small.points *= 0.8f; + + /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */ + int num_digits = 4; + char number_text[4] = "+99\0"; + if (num_elements < 100) { + BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements); + num_digits = num_elements < 10 ? 1 : 2; + } + UI_fontstyle_draw_simple(&fstyle_small, + (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f), + (float)ys - UI_UNIT_Y * 0.095f + ufac, + number_text, text_col); + UI_fontstyle_set(fstyle); + glEnable(GL_BLEND); /* Roundbox and text drawing disables. */ +} + +static void outliner_draw_iconrow_doit( + uiBlock *block, TreeElement *te, + const uiFontStyle *fstyle, + int xmax, int *offsx, int ys, float alpha_fac, + const eOLDrawState active, + const int num_elements) +{ + TreeStoreElem *tselem = TREESTORE(te); + + if (active != OL_DRAWSEL_NONE) { + float ufac = UI_UNIT_X / 20.0f; + float color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + color[3] *= alpha_fac; + + UI_draw_roundbox_aa(true, + (float) *offsx + 1.0f * ufac, + (float)ys + 1.0f * ufac, + (float)*offsx + UI_UNIT_X - 1.0f * ufac, + (float)ys + UI_UNIT_Y - ufac, + (float)UI_UNIT_Y / 2.0f - ufac, + color); + glEnable(GL_BLEND); /* Roundbox disables. */ + } + + /* No inlined icon should be clickable. */ + tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac, false); + te->xs = *offsx; + te->ys = ys; + te->xend = (short)*offsx + UI_UNIT_X; + + if (num_elements > 1) { + outliner_draw_iconrow_number(fstyle, *offsx, ys, active, num_elements); + } + (*offsx) += UI_UNIT_X; +} + +/** + * Return the index to use based on the TreeElement ID and object type + * + * We use a continuum of indeces until we get to the object datablocks + * and we then make room for the object types. + */ +static int tree_element_id_type_to_index(TreeElement *te) +{ + TreeStoreElem *tselem = TREESTORE(te); + + const int id_index = tselem->type == 0 ? BKE_idcode_to_index(te->idcode) : INDEX_ID_GR; + if (id_index < INDEX_ID_OB) { + return id_index; + } + else if (id_index == INDEX_ID_OB) { + const Object *ob = (Object *)tselem->id; + return INDEX_ID_OB + ob->type; + } + else { + return id_index + OB_TYPE_MAX; + } +} + static void outliner_draw_iconrow( - bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, + bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac) { eOLDrawState active; const Object *obact = OBACT(view_layer); + struct { + eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX]; + int num_elements[INDEX_ID_MAX + OB_TYPE_MAX]; + TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX]; + } data = { + .active = {0}, + .num_elements = {0}, + .tree_element = {NULL}, + }; + for (TreeElement *te = lb->first; te; te = te->next) { /* exit drawing early */ if ((*offsx) - UI_UNIT_X > xmax) @@ -1363,41 +1489,48 @@ static void outliner_draw_iconrow( active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false); } - if (active != OL_DRAWSEL_NONE) { - float ufac = UI_UNIT_X / 20.0f; - float color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - color[3] *= alpha_fac; - - UI_draw_roundbox_aa( - true, - (float) *offsx + 1.0f * ufac, - (float)ys + 1.0f * ufac, - (float)*offsx + UI_UNIT_X - 1.0f * ufac, - (float)ys + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 2.0f - ufac, - color); - glEnable(GL_BLEND); /* roundbox disables */ + if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) { + outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1); + } + else { + const int index = tree_element_id_type_to_index(te); + data.num_elements[index]++; + if ((data.tree_element[index] == NULL) || + (active > data.active[index])) + { + data.tree_element[index] = te; + } + data.active[index] = MAX2(active, data.active[index]); } - - tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac); - te->xs = *offsx; - te->ys = ys; - te->xend = (short)*offsx + UI_UNIT_X; - te->flag |= TE_ICONROW; // for click - - (*offsx) += UI_UNIT_X; } /* this tree element always has same amount of branches, so don't draw */ if (tselem->type != TSE_R_LAYER) { outliner_draw_iconrow( - C, block, scene, view_layer, soops, + C, block, fstyle, scene, view_layer, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac); } } + for (int i = 0; i < INDEX_ID_MAX; i++) { + const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1; + /* See tree_element_id_type_to_index for the index logic. */ + int index_base = i; + if (i > INDEX_ID_OB){ + index_base += OB_TYPE_MAX; + } + for (int j = 0; j < num_subtypes; j++) { + const int index = index_base + j; + if (data.num_elements[index] != 0) { + outliner_draw_iconrow_doit(block, + data.tree_element[index], + fstyle, + xmax, offsx, ys, alpha_fac, + data.active[index], + data.num_elements[index]); + } + } + } } /* closed tree element */ @@ -1538,7 +1671,7 @@ static void outliner_draw_tree_element( /* datatype icon */ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) { - tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac); + tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true); offsx += UI_UNIT_X + 2 * ufac; } else @@ -1622,7 +1755,7 @@ static void outliner_draw_tree_element( } outliner_draw_iconrow( - C, block, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx, + C, block, fstyle, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx, *starty, alpha_fac); glDisable(GL_BLEND); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 62f8f1395c5..fa97fd53f32 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -576,6 +576,7 @@ enum { INDEX_ID_WM, INDEX_ID_MSK, INDEX_ID_NULL, + INDEX_ID_MAX, }; #ifdef __cplusplus diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 45029e8d412..7eb920002f3 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -367,6 +367,7 @@ enum { /* 23 and 24 are for life and sector (old file compat.) */ OB_ARMATURE = 25, + OB_TYPE_MAX, }; /* ObjectDisplay.flag */ |