Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c217
-rw-r--r--source/blender/makesdna/DNA_ID.h1
-rw-r--r--source/blender/makesdna/DNA_object_types.h1
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 */