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:
authorNathan Craddock <nzcraddock@gmail.com>2020-08-19 06:22:43 +0300
committerNathan Craddock <nzcraddock@gmail.com>2020-08-19 06:23:43 +0300
commit093294e167508ff04362030350e05e9921683ca2 (patch)
tree51e0f37c0814e51643a2f9e799b245729f0b7d67
parent349eebd7d1459fa2525850751040963899ef7535 (diff)
Collections: Add color tagging & use in outliner
Add a color tag to collections and allow tagging from the outliner context menu. Show the colored icon in UI menus.
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c26
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py4
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py19
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c9
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/animation/keyingsets.c2
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c2
-rw-r--r--source/blender/editors/include/UI_icons.h11
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/include/UI_interface_icons.h2
-rw-r--r--source/blender/editors/interface/interface.c26
-rw-r--r--source/blender/editors/interface/interface_icons.c51
-rw-r--r--source/blender/editors/interface/interface_layout.c48
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/object/object_collection.c4
-rw-r--r--source/blender/editors/object/object_edit.c17
-rw-r--r--source/blender/editors/space_info/info_ops.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c63
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c255
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c3
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/makesdna/DNA_collection_types.h17
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h6
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/RNA_enum_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_collection.c19
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c24
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c6
34 files changed, 451 insertions, 190 deletions
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 4d48bb8eaac..1fbde066ef6 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -1101,6 +1101,32 @@ const bTheme U_theme_default = {
.active = RGBA(0x000000ff),
},
},
+ .collection_color = {
+ {
+ .color = RGBA(0xe4312bff),
+ },
+ {
+ .color = RGBA(0xef7e42ff),
+ },
+ {
+ .color = RGBA(0xe4dd52ff),
+ },
+ {
+ .color = RGBA(0x9ac546ff),
+ },
+ {
+ .color = RGBA(0x46bcc2ff),
+ },
+ {
+ .color = RGBA(0x8b65dcff),
+ },
+ {
+ .color = RGBA(0x999999ff),
+ },
+ {
+ .color = RGBA(0x06d4432ff),
+ },
+ },
};
/* clang-format on */
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 5a54d4ca2d8..0c8c4df0c51 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -239,6 +239,10 @@ class OUTLINER_MT_collection(Menu):
if space.display_mode == 'VIEW_LAYER':
layout.separator()
layout.menu("OUTLINER_MT_collection_view_layer", icon='RENDERLAYERS')
+ layout.separator()
+
+ row = layout.row(align=True)
+ row.operator_enum("outliner.collection_color_tag_set", "color", icon_only=True)
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 9548de20752..61b2489bb4a 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -1019,6 +1019,24 @@ class USERPREF_PT_theme_bone_color_sets(ThemePanel, CenterAlignMixIn, Panel):
flow.prop(ui, "active")
flow.prop(ui, "show_colored_constraints")
+class USERPREF_PT_theme_collection_colors(ThemePanel, CenterAlignMixIn, Panel):
+ bl_label = "Collection Colors"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, _context):
+ layout = self.layout
+
+ layout.label(icon='GROUP')
+
+ def draw_centered(self, context, layout):
+ theme = context.preferences.themes[0]
+
+ layout.use_property_split = True
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ for i, ui in enumerate(theme.collection_color, 1):
+ flow.prop(ui, "color", text=iface_(f"Color {i:d}"), translate=False)
+
# Base class for dynamically defined theme-space panels.
# This is not registered.
@@ -2254,6 +2272,7 @@ classes = (
USERPREF_PT_theme_interface_icons,
USERPREF_PT_theme_text_style,
USERPREF_PT_theme_bone_color_sets,
+ USERPREF_PT_theme_collection_colors,
USERPREF_PT_file_paths_data,
USERPREF_PT_file_paths_render,
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 0b116804481..475f618b1f4 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -217,6 +217,15 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
btheme->tui.transparent_checker_size = U_theme_default.tui.transparent_checker_size;
}
+ FROM_DEFAULT_V4_UCHAR(collection_color[0].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[1].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[2].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[3].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[4].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[5].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[6].color);
+ FROM_DEFAULT_V4_UCHAR(collection_color[7].color);
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 66d4882cf9d..e671a5b18f7 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1971,7 +1971,7 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UN
/* call the menu, which will call this operator again, hence the canceled */
pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
+ uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type", false);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 876740b889a..558a7be1df8 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -479,7 +479,7 @@ static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEve
/* call the menu, which will call this operator again, hence the canceled */
pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type");
+ uiItemsEnumO(layout, "ANIM_OT_keying_set_active_set", "type", false);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index d113e0693a4..c1668080d56 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -5922,7 +5922,7 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
if (nu->type == CU_NURBS) {
pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, op->type->idname, "direction");
+ uiItemsEnumO(layout, op->type->idname, "direction", false);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 348fb614977..ed78f9e81f6 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -1403,7 +1403,7 @@ static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEven
/* call the menu, which will call this operator again, hence the canceled */
pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer");
+ uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer", false);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 452a1fca111..e976aac27a2 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -320,7 +320,7 @@ DEF_ICON_OBJECT(OUTLINER_OB_GROUP_INSTANCE)
DEF_ICON_OBJECT(OUTLINER_OB_GREASEPENCIL)
DEF_ICON_OBJECT(OUTLINER_OB_LIGHTPROBE)
DEF_ICON_OBJECT(OUTLINER_OB_IMAGE)
-DEF_ICON_BLANK(321)
+DEF_ICON(OUTLINER_COLLECTION)
DEF_ICON(RESTRICT_COLOR_OFF)
DEF_ICON(RESTRICT_COLOR_ON)
DEF_ICON(HIDE_ON)
@@ -980,6 +980,15 @@ DEF_ICON_VECTOR(COLORSET_18_VEC)
DEF_ICON_VECTOR(COLORSET_19_VEC)
DEF_ICON_VECTOR(COLORSET_20_VEC)
+DEF_ICON_VECTOR(COLLECTION_COLOR_01)
+DEF_ICON_VECTOR(COLLECTION_COLOR_02)
+DEF_ICON_VECTOR(COLLECTION_COLOR_03)
+DEF_ICON_VECTOR(COLLECTION_COLOR_04)
+DEF_ICON_VECTOR(COLLECTION_COLOR_05)
+DEF_ICON_VECTOR(COLLECTION_COLOR_06)
+DEF_ICON_VECTOR(COLLECTION_COLOR_07)
+DEF_ICON_VECTOR(COLLECTION_COLOR_08)
+
/* Events */
DEF_ICON_COLOR(EVENT_A)
DEF_ICON_COLOR(EVENT_B)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 5d936cdfaa3..f942ca8bafa 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2208,7 +2208,10 @@ void uiItemEnumO_string(uiLayout *layout,
const char *opname,
const char *propname,
const char *value);
-void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname);
+void uiItemsEnumO(uiLayout *layout,
+ const char *opname,
+ const char *propname,
+ const bool icon_only);
void uiItemBooleanO(uiLayout *layout,
const char *name,
int icon,
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 7b59d45b203..0e0891cb526 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -32,6 +32,7 @@ struct PointerRNA;
struct PreviewImage;
struct Scene;
struct bContext;
+struct Collection;
enum eIconSizes;
@@ -106,6 +107,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);
+int UI_collection_color_icon_get(const struct Collection *collection);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index e04531bb1dd..4a68d7f861c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -383,13 +383,27 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset)
}
}
+ /* Keep aligned buttons in the same column. */
+ if (bt->alignnr && bt->next) {
+ int width = 0;
+ for (col_bt = bt; col_bt->rect.xmin < col_bt->next->rect.xmin; col_bt = col_bt->next) {
+ width += BLI_rctf_size_x(&col_bt->rect);
+ }
+ if (width > i) {
+ i = width;
+ }
+ bt = col_bt;
+ }
+
if (bt->next && bt->rect.xmin < bt->next->rect.xmin) {
/* End of this column, and it's not the last one. */
for (col_bt = init_col_bt; col_bt->prev != bt; col_bt = col_bt->next) {
- col_bt->rect.xmin = x1addval;
- col_bt->rect.xmax = x1addval + i + block->bounds;
+ if (!col_bt->alignnr) {
+ col_bt->rect.xmin = x1addval;
+ col_bt->rect.xmax = x1addval + i + block->bounds;
- ui_but_update(col_bt); /* clips text again */
+ ui_but_update(col_bt); /* clips text again */
+ }
}
/* And we prepare next column. */
@@ -401,8 +415,10 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset)
/* Last column. */
for (col_bt = init_col_bt; col_bt; col_bt = col_bt->next) {
- col_bt->rect.xmin = x1addval;
- col_bt->rect.xmax = max_ff(x1addval + i + block->bounds, offset + block->minbounds);
+ if (!col_bt->alignnr) {
+ col_bt->rect.xmin = x1addval;
+ col_bt->rect.xmax = max_ff(x1addval + i + block->bounds, offset + block->minbounds);
+ }
ui_but_update(col_bt); /* clips text again */
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index edf66d82cbc..a7a59fd8513 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
+#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_gpencil_types.h"
@@ -460,6 +461,33 @@ DEF_ICON_VECTOR_COLORSET_DRAW_NTH(20, 19)
# undef DEF_ICON_VECTOR_COLORSET_DRAW_NTH
+static void vicon_collection_color_draw(
+ short color, int x, int y, int UNUSED(w), int UNUSED(), float UNUSED(alpha))
+{
+ bTheme *btheme = UI_GetTheme();
+ const ThemeCollectionColor *collection_color = &btheme->collection_color[color - 1];
+
+ UI_icon_draw_ex(
+ x, y, ICON_OUTLINER_COLLECTION, U.inv_dpi_fac, 1.0f, 0.0f, collection_color->color, true);
+}
+
+# define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \
+ static void vicon_collection_color_draw_##index(int x, int y, int w, int h, float alpha) \
+ { \
+ vicon_collection_color_draw(color, x, y, w, h, alpha); \
+ }
+
+DEF_ICON_COLLECTION_COLOR_DRAW(01, COLLECTION_COLOR_01);
+DEF_ICON_COLLECTION_COLOR_DRAW(02, COLLECTION_COLOR_02);
+DEF_ICON_COLLECTION_COLOR_DRAW(03, COLLECTION_COLOR_03);
+DEF_ICON_COLLECTION_COLOR_DRAW(04, COLLECTION_COLOR_04);
+DEF_ICON_COLLECTION_COLOR_DRAW(05, COLLECTION_COLOR_05);
+DEF_ICON_COLLECTION_COLOR_DRAW(06, COLLECTION_COLOR_06);
+DEF_ICON_COLLECTION_COLOR_DRAW(07, COLLECTION_COLOR_07);
+DEF_ICON_COLLECTION_COLOR_DRAW(08, COLLECTION_COLOR_08);
+
+# undef DEF_ICON_COLLECTION_COLOR_DRAW
+
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
* This is not strictly a "vicon", as it needs access to icon->obj to get the color info,
* but it works in a very similar way.
@@ -985,6 +1013,15 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
+
+ def_internal_vicon(ICON_COLLECTION_COLOR_01, vicon_collection_color_draw_01);
+ def_internal_vicon(ICON_COLLECTION_COLOR_02, vicon_collection_color_draw_02);
+ def_internal_vicon(ICON_COLLECTION_COLOR_03, vicon_collection_color_draw_03);
+ def_internal_vicon(ICON_COLLECTION_COLOR_04, vicon_collection_color_draw_04);
+ def_internal_vicon(ICON_COLLECTION_COLOR_05, vicon_collection_color_draw_05);
+ def_internal_vicon(ICON_COLLECTION_COLOR_06, vicon_collection_color_draw_06);
+ def_internal_vicon(ICON_COLLECTION_COLOR_07, vicon_collection_color_draw_07);
+ def_internal_vicon(ICON_COLLECTION_COLOR_08, vicon_collection_color_draw_08);
}
# endif /* WITH_HEADLESS */
@@ -2148,6 +2185,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
case ID_SCR:
iconid = ui_id_screen_get_icon(C, id);
break;
+ case ID_GR:
+ iconid = UI_collection_color_icon_get((Collection *)id);
+ break;
default:
break;
}
@@ -2309,6 +2349,17 @@ int UI_idcode_icon_get(const int idcode)
}
}
+int UI_collection_color_icon_get(const Collection *collection)
+{
+ int icon = ICON_OUTLINER_COLLECTION;
+
+ if (collection->color != COLLECTION_COLOR_NONE) {
+ icon = ICON_COLLECTION_COLOR_01 + (collection->color - 1);
+ }
+
+ return icon;
+}
+
/* draws icon with dpi scale factor */
void UI_icon_draw(float x, float y, int icon_id)
{
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index ad76466b67c..f19596c7ba7 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1208,6 +1208,10 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout,
but->flag |= UI_SELECT_DRAW;
}
+ if (flag & UI_ITEM_R_ICON_ONLY) {
+ UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
+ }
+
if (layout->redalert) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
@@ -1428,6 +1432,13 @@ void uiItemsFullEnumO_items(uiLayout *layout,
if (radial) {
target = uiLayoutRadial(layout);
}
+ else if (layout->item.type == ITEM_LAYOUT_ROW && flag & UI_ITEM_R_ICON_ONLY) {
+ target = layout;
+
+ /* Add a blank button to the beginning of the row. */
+ uiDefIconBut(
+ block, UI_BTYPE_LABEL, 0, ICON_BLANK1, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ }
else {
split = uiLayoutSplit(layout, 0.0f, false);
target = uiLayoutColumn(split, layout->align);
@@ -1475,7 +1486,14 @@ void uiItemsFullEnumO_items(uiLayout *layout,
}
RNA_property_enum_set(&tptr, prop, item->value);
- uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag, NULL);
+ uiItemFullO_ptr(target,
+ ot,
+ (flag & UI_ITEM_R_ICON_ONLY) ? NULL : item->name,
+ item->icon,
+ tptr.data,
+ context,
+ flag,
+ NULL);
ui_but_tip_from_enum_item(block->buttons.last, item);
}
@@ -1599,9 +1617,14 @@ void uiItemsFullEnumO(uiLayout *layout,
}
}
-void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
+void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname, const bool icon_only)
{
- uiItemsFullEnumO(layout, opname, propname, NULL, layout->root->opcontext, 0);
+ uiItemsFullEnumO(layout,
+ opname,
+ propname,
+ NULL,
+ layout->root->opcontext,
+ icon_only ? UI_ITEM_R_ICON_ONLY : 0);
}
/* for use in cases where we have */
@@ -3372,7 +3395,7 @@ static void menu_item_enum_opname_menu(bContext *UNUSED(C), uiLayout *layout, vo
MenuItemLevel *lvl = (MenuItemLevel *)(((uiBut *)arg)->func_argN);
uiLayoutSetOperatorContext(layout, lvl->opcontext);
- uiItemsEnumO(layout, lvl->opname, lvl->propname);
+ uiItemsEnumO(layout, lvl->opname, lvl->propname, false);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
@@ -3718,18 +3741,18 @@ static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
}
}
-static void ui_litem_layout_column(uiLayout *litem, bool is_box)
+static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu)
{
- int itemh, x, y;
+ int itemw, itemh, x, y;
x = litem->x;
y = litem->y;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
- ui_item_size(item, NULL, &itemh);
+ ui_item_size(item, &itemw, &itemh);
y -= itemh;
- ui_item_position(item, x, y, litem->w, itemh);
+ ui_item_position(item, x, y, is_menu ? itemw : litem->w, itemh);
if (item->next && (!is_box || item != litem->items.first)) {
y -= litem->space;
@@ -3890,8 +3913,11 @@ static void ui_litem_layout_root(uiLayout *litem)
else if (litem->root->type == UI_LAYOUT_PIEMENU) {
ui_litem_layout_root_radial(litem);
}
+ else if (litem->root->type == UI_LAYOUT_MENU) {
+ ui_litem_layout_column(litem, false, true);
+ }
else {
- ui_litem_layout_column(litem, false);
+ ui_litem_layout_column(litem, false, false);
}
}
@@ -3935,7 +3961,7 @@ static void ui_litem_layout_box(uiLayout *litem)
litem->h -= 2 * boxspace;
}
- ui_litem_layout_column(litem, true);
+ ui_litem_layout_column(litem, true, false);
litem->x -= boxspace;
litem->y -= boxspace;
@@ -5196,7 +5222,7 @@ static void ui_item_layout(uiItem *item)
switch (litem->item.type) {
case ITEM_LAYOUT_COLUMN:
- ui_litem_layout_column(litem, false);
+ ui_litem_layout_column(litem, false, false);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_layout_column_flow(litem);
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 1371c7524ae..5afef38ae0d 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -261,7 +261,7 @@ int UI_pie_menu_invoke_from_operator_enum(struct bContext *C,
layout = UI_pie_menu_layout(pie);
layout = uiLayoutRadial(layout);
- uiItemsEnumO(layout, opname, propname);
+ uiItemsEnumO(layout, opname, propname, false);
UI_pie_menu_end(C, pie);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index c1801290152..fa2f2b0d1b9 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2375,7 +2375,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
rect->xmin += 0.3f * U.widget_unit;
}
}
- else if (ui_block_is_menu(but->block)) {
+ else if (ui_block_is_menu(but->block) && but->alignnr == 0) {
rect->xmin += 0.2f * U.widget_unit;
}
diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c
index 24f6d8c79f9..5f14cdcd299 100644
--- a/source/blender/editors/object/object_collection.c
+++ b/source/blender/editors/object/object_collection.c
@@ -50,6 +50,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface_icons.h"
+
#include "object_intern.h"
/********************* 3d view operators ***********************/
@@ -94,7 +96,7 @@ static const EnumPropertyItem *collection_object_active_itemf(bContext *C,
collection = NULL;
while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
item_tmp.identifier = item_tmp.name = collection->id.name + 2;
- /* item_tmp.icon = ICON_ARMATURE_DATA; */
+ item_tmp.icon = UI_collection_color_icon_get(collection);
item_tmp.value = i;
RNA_enum_item_add(&item, &totitem, &item_tmp);
i++;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 04113f70e52..c911d62f392 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -100,6 +100,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface_icons.h"
+
#include "CLG_log.h"
/* for menu/popup icons etc etc*/
@@ -1761,7 +1763,7 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu)
*menu = NULL;
}
-static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
+static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *menu_v)
{
MoveToCollectionData *menu = menu_v;
const char *name = BKE_collection_ui_name_get(menu->collection);
@@ -1777,7 +1779,11 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout
uiItemS(layout);
- uiItemIntO(layout, name, ICON_SCENE_DATA, menu->ot->idname, "collection_index", menu->index);
+ Scene *scene = CTX_data_scene(C);
+ const int icon = (menu->collection == scene->master_collection) ?
+ ICON_SCENE_DATA :
+ UI_collection_color_icon_get(menu->collection);
+ uiItemIntO(layout, name, icon, menu->ot->idname, "collection_index", menu->index);
for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
submenu = submenu->next) {
@@ -1787,17 +1793,18 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout
static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
{
+ const int icon = UI_collection_color_icon_get(menu->collection);
+
if (BLI_listbase_is_empty(&menu->submenus)) {
uiItemIntO(layout,
menu->collection->id.name + 2,
- ICON_NONE,
+ icon,
menu->ot->idname,
"collection_index",
menu->index);
}
else {
- uiItemMenuF(
- layout, menu->collection->id.name + 2, ICON_NONE, move_to_collection_menu_create, menu);
+ uiItemMenuF(layout, menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu);
}
}
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 30f36509b41..dda4d8a6c78 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -256,7 +256,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
+ uiItemsEnumO(layout, "FILE_OT_unpack_all", "method", false);
UI_popup_menu_end(C, pup);
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index efb91528e14..a76ee2972cc 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -1529,3 +1529,66 @@ void OUTLINER_OT_unhide_all(wmOperatorType *ot)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Collection Color Tags
+ * \{ */
+
+static int outliner_color_tag_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+ const short color_tag = RNA_enum_get(op->ptr, "color");
+
+ struct IDsSelectedData selected = {
+ .selected_array = {NULL, NULL},
+ };
+
+ outliner_tree_traverse(space_outliner,
+ &space_outliner->tree,
+ 0,
+ TSE_SELECTED,
+ outliner_find_selected_collections,
+ &selected);
+
+ LISTBASE_FOREACH (LinkData *, link, &selected.selected_array) {
+ TreeElement *te_selected = (TreeElement *)link->data;
+
+ Collection *collection = outliner_collection_from_tree_element(te_selected);
+ if (collection == scene->master_collection) {
+ continue;
+ }
+ if (ID_IS_LINKED(collection)) {
+ BKE_report(op->reports, RPT_WARNING, "Can't add a color tag to a linked collection");
+ continue;
+ }
+
+ collection->color = color_tag;
+ };
+
+ BLI_freelistN(&selected.selected_array);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_color_tag_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Color Tag";
+ ot->idname = "OUTLINER_OT_collection_color_tag_set";
+ ot->description = "Set a color tag for the selected collections";
+
+ /* api callbacks */
+ ot->exec = outliner_color_tag_set_exec;
+ ot->poll = ED_outliner_collections_editor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(
+ ot->srna, "color", rna_enum_collection_color_items, COLLECTION_COLOR_NONE, "Color Tag", "");
+}
+
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 1705b9dd606..5cc42cbadbb 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -848,8 +848,8 @@ typedef struct RestrictProperties {
PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
PropertyRNA *base_hide_viewport;
PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
- PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only,
- *layer_collection_hide_viewport;
+ PropertyRNA *layer_collection_exclude, *layer_collection_holdout,
+ *layer_collection_indirect_only, *layer_collection_hide_viewport;
PropertyRNA *modifier_show_viewport, *modifier_show_render;
PropertyRNA *constraint_enable;
PropertyRNA *bone_hide_viewport;
@@ -865,6 +865,7 @@ typedef struct RestrictPropertiesActive {
bool collection_hide_viewport;
bool collection_hide_select;
bool collection_hide_render;
+ bool layer_collection_exclude;
bool layer_collection_holdout;
bool layer_collection_indirect_only;
bool layer_collection_hide_viewport;
@@ -954,8 +955,7 @@ static bool outliner_restrict_properties_collection_set(Scene *scene,
NULL;
Collection *collection = outliner_collection_from_tree_element(te);
- if ((collection->flag & COLLECTION_IS_MASTER) ||
- (layer_collection && ((layer_collection->flag & LAYER_COLLECTION_EXCLUDE) != 0))) {
+ if (collection->flag & COLLECTION_IS_MASTER) {
return false;
}
@@ -995,6 +995,8 @@ static void outliner_draw_restrictbuts(uiBlock *block,
"hide_viewport");
props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ props.layer_collection_exclude = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "exclude");
props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection,
"holdout");
props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection,
@@ -1012,6 +1014,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
struct {
+ int enable;
int select;
int hide;
int viewport;
@@ -1042,6 +1045,11 @@ static void outliner_draw_restrictbuts(uiBlock *block,
if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
}
+ if (space_outliner->outlinevis == SO_VIEW_LAYER &&
+ space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) {
+ restrict_offsets.enable = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+
BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) ==
outliner_restrict_columns_width(space_outliner));
@@ -1430,6 +1438,26 @@ static void outliner_draw_restrictbuts(uiBlock *block,
Collection *collection = outliner_collection_from_tree_element(te);
if (layer_collection != NULL) {
+ if (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(region->v2d.cur.xmax) - restrict_offsets.enable,
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_exclude,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
@@ -1823,7 +1851,6 @@ static void outliner_buttons(const bContext *C,
const float restrict_column_width,
TreeElement *te)
{
- SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
uiBut *bt;
TreeStoreElem *tselem;
int spx, dx, len;
@@ -1849,10 +1876,6 @@ static void outliner_buttons(const bContext *C,
}
spx = te->xs + 1.8f * UI_UNIT_X;
- if ((tselem->type == TSE_LAYER_COLLECTION) &&
- (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE)) {
- spx += UI_UNIT_X;
- }
dx = region->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
bt = uiDefBut(block,
@@ -2347,7 +2370,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
}
- data.icon = ICON_GROUP;
+ data.icon = ICON_OUTLINER_COLLECTION;
break;
}
case TSE_GP_LAYER: {
@@ -2578,60 +2601,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
return data;
}
-static void tselem_draw_layer_collection_enable_icon(
- Scene *scene, uiBlock *block, int xmax, float x, float y, TreeElement *te, float alpha)
-{
- /* Get RNA property (once for speed). */
- static PropertyRNA *exclude_prop = NULL;
- if (exclude_prop == NULL) {
- exclude_prop = RNA_struct_type_find_property(&RNA_LayerCollection, "exclude");
- }
-
- if (x >= xmax) {
- /* Placement of icons, copied from interface_widgets.c. */
- float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
- x += 2.0f * aspect;
- y += 2.0f * aspect;
-
- /* restrict column clip... it has been coded by simply overdrawing,
- * doesn't work for buttons */
- uchar color[4];
- int icon = RNA_property_ui_icon(exclude_prop);
- if (UI_icon_get_theme_color(icon, color)) {
- UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
- }
- else {
- UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
- }
- }
- else {
- LayerCollection *layer_collection = te->directdata;
- PointerRNA layer_collection_ptr;
- RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
-
- char emboss = UI_block_emboss_get(block);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiBut *bt = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- 0,
- x,
- y,
- UI_UNIT_X,
- UI_UNIT_Y,
- &layer_collection_ptr,
- exclude_prop,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_block_emboss_set(block, emboss);
- }
-}
-
static void tselem_draw_icon(uiBlock *block,
int xmax,
float x,
@@ -2647,8 +2616,30 @@ static void tselem_draw_icon(uiBlock *block,
return;
}
+ if (outliner_is_collection_tree_element(te)) {
+ Collection *collection = outliner_collection_from_tree_element(te);
+
+ /* placement of icons, copied from interface_widgets.c */
+ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+ if (collection->color != COLLECTION_COLOR_NONE) {
+ bTheme *btheme = UI_GetTheme();
+ UI_icon_draw_ex(x,
+ y,
+ data.icon,
+ U.inv_dpi_fac,
+ alpha,
+ 0.0f,
+ btheme->collection_color[collection->color - 1].color,
+ true);
+ }
+ else {
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, NULL, true);
+ }
+ }
/* Icon is covered by restrict buttons */
- if (!is_clickable || x >= xmax) {
+ else if (!is_clickable || x >= xmax) {
/* Reduce alpha to match icon buttons */
alpha *= 0.8f;
@@ -3039,15 +3030,6 @@ static void outliner_draw_tree_element(bContext *C,
else {
active = tree_element_type_active(C, tvc, space_outliner, te, tselem, OL_SETSEL_NONE, false);
/* active collection*/
- icon_bgcolor[3] = 0.2f;
- }
-
- /* Checkbox to enable collections. */
- if ((tselem->type == TSE_LAYER_COLLECTION) &&
- (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE)) {
- tselem_draw_layer_collection_enable_icon(
- tvc->scene, block, xmax, (float)startx + offsx + UI_UNIT_X, (float)*starty, te, 0.8f);
- offsx += UI_UNIT_X;
}
/* active circle */
@@ -3196,6 +3178,17 @@ static void outliner_draw_tree_element(bContext *C,
}
}
+static bool subtree_contains_object(ListBase *lb)
+{
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ return true;
+ }
+ }
+ return false;
+}
+
static void outliner_draw_hierarchy_lines_recursive(uint pos,
SpaceOutliner *space_outliner,
ListBase *lb,
@@ -3204,100 +3197,50 @@ static void outliner_draw_hierarchy_lines_recursive(uint pos,
bool draw_grayed_out,
int *starty)
{
- TreeElement *te, *te_vertical_line_last = NULL, *te_vertical_line_last_dashed = NULL;
- int y1, y2, y1_dashed, y2_dashed;
+ bTheme *btheme = UI_GetTheme();
+ int y = *starty;
+ short color = 0;
- if (BLI_listbase_is_empty(lb)) {
- return;
- }
+ /* Small vertical padding */
+ const short line_padding = UI_UNIT_Y / 4.0f;
- struct {
- int steps_num;
- int step_len;
- int gap_len;
- } dash = {
- .steps_num = 4,
- };
-
- dash.step_len = UI_UNIT_X / dash.steps_num;
- dash.gap_len = dash.step_len / 2;
-
- const uchar grayed_alpha = col[3] / 2;
-
- /* For vertical lines between objects. */
- y1 = y2 = y1_dashed = y2_dashed = *starty;
- for (te = lb->first; te; te = te->next) {
- bool draw_children_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING);
+ /* Draw vertical lines between collections */
+ bool draw_hierarchy_line;
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
+ draw_hierarchy_line = false;
+ *starty -= UI_UNIT_Y;
- if (draw_children_grayed_out) {
- immUniformColor3ubvAlpha(col, grayed_alpha);
- }
- else {
- immUniformColor4ubv(col);
- }
+ /* Only draw hierarchy lines for open collections. */
+ if (TSELEM_OPEN(tselem, space_outliner) && !BLI_listbase_is_empty(&te->subtree)) {
+ if (tselem->type == TSE_LAYER_COLLECTION) {
+ draw_hierarchy_line = true;
- if ((te->flag & TE_CHILD_NOT_IN_COLLECTION) == 0) {
- /* Horizontal Line? */
- if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) {
- immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - U.pixelsize);
+ Collection *collection = outliner_collection_from_tree_element(te);
+ color = collection->color;
- /* Vertical Line? */
- if (te->idcode == ID_OB) {
- te_vertical_line_last = te;
- y2 = *starty;
- }
- y1_dashed = *starty - UI_UNIT_Y;
+ y = *starty;
}
- }
- else {
- BLI_assert(te->idcode == ID_OB);
- /* Horizontal line - dashed. */
- int start = startx;
- for (int i = 0; i < dash.steps_num; i++) {
- immRecti(pos, start, *starty, start + dash.step_len - dash.gap_len, *starty - U.pixelsize);
- start += dash.step_len;
+ else if (tselem->type == 0 && te->idcode == ID_OB) {
+ if (subtree_contains_object(&te->subtree)) {
+ draw_hierarchy_line = true;
+ y = *starty;
+ }
}
- te_vertical_line_last_dashed = te;
- y2_dashed = *starty;
+ outliner_draw_hierarchy_lines_recursive(
+ pos, space_outliner, &te->subtree, startx + UI_UNIT_X, col, draw_grayed_out, starty);
}
- *starty -= UI_UNIT_Y;
-
- if (TSELEM_OPEN(tselem, space_outliner)) {
- outliner_draw_hierarchy_lines_recursive(pos,
- space_outliner,
- &te->subtree,
- startx + UI_UNIT_X,
- col,
- draw_children_grayed_out,
- starty);
- }
- }
-
- if (draw_grayed_out) {
- immUniformColor3ubvAlpha(col, grayed_alpha);
- }
- else {
- immUniformColor4ubv(col);
- }
-
- /* Vertical line. */
- te = te_vertical_line_last;
- if ((te != NULL) && (te->parent || lb->first != lb->last)) {
- immRecti(pos, startx, y1 + UI_UNIT_Y, startx + U.pixelsize, y2);
- }
+ if (draw_hierarchy_line) {
+ if (color != COLLECTION_COLOR_NONE) {
+ immUniformColor4ubv(btheme->collection_color[color - 1].color);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
- /* Children that are not in the collection are always in the end of the subtree.
- * This way we can draw their own dashed vertical lines. */
- te = te_vertical_line_last_dashed;
- if ((te != NULL) && (te->parent || lb->first != lb->last)) {
- const int steps_num = ((y1_dashed + UI_UNIT_Y) - y2_dashed) / dash.step_len;
- int start = y1_dashed + UI_UNIT_Y;
- for (int i = 0; i < steps_num; i++) {
- immRecti(pos, startx, start, startx + U.pixelsize, start - dash.step_len + dash.gap_len);
- start -= dash.step_len;
+ immRecti(pos, startx, y - line_padding, startx + (U.pixelsize * 1), *starty + line_padding);
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 33dbbb274c0..ad8f8a92b5f 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -482,6 +482,8 @@ void OUTLINER_OT_collection_disable_render(struct wmOperatorType *ot);
void OUTLINER_OT_hide(struct wmOperatorType *ot);
void OUTLINER_OT_unhide_all(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_color_tag_set(struct wmOperatorType *ot);
+
/* outliner_utils.c ---------------------------------------------- */
void outliner_viewcontext_init(const struct bContext *C, TreeViewContext *tvc);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index af7d97b6950..22541a0ab1f 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -117,6 +117,8 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_show_inside);
WM_operatortype_append(OUTLINER_OT_hide);
WM_operatortype_append(OUTLINER_OT_unhide_all);
+
+ WM_operatortype_append(OUTLINER_OT_collection_color_tag_set);
}
void outliner_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 6532ff189b5..965e6d1177a 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -2588,7 +2588,7 @@ static int outliner_operator_menu(bContext *C, const char *opname)
/* set this so the default execution context is the same as submenus */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
- uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop));
+ uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop), false);
uiItemS(layout);
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index 1da44b5e51e..1e01a62875c 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -359,6 +359,9 @@ float outliner_restrict_columns_width(const SpaceOutliner *space_outliner)
num_columns = 3;
break;
case SO_VIEW_LAYER:
+ if (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) {
+ num_columns++;
+ }
if (space_outliner->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
num_columns++;
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index ab9548ad52e..2fa4c77f028 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -187,7 +187,7 @@ static int select_orientation_invoke(bContext *C,
pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
+ uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation", false);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h
index 6cf02137fa6..1584642b449 100644
--- a/source/blender/makesdna/DNA_collection_types.h
+++ b/source/blender/makesdna/DNA_collection_types.h
@@ -58,7 +58,9 @@ typedef struct Collection {
short flag;
/* Runtime-only, always cleared on file load. */
short tag;
- char _pad[4];
+
+ short color;
+ char _pad[2];
/* Runtime. Cache of objects in this collection and all its
* children. This is created on demand when e.g. some physics
@@ -92,3 +94,16 @@ enum {
* Using a generic tag like LIB_TAG_DOIT for this is just impossible, we need our very own. */
COLLECTION_TAG_RELATION_REBUILD = (1 << 0),
};
+
+/* Collection->color */
+enum {
+ COLLECTION_COLOR_NONE = 0,
+ COLLECTION_COLOR_01 = 1,
+ COLLECTION_COLOR_02 = 2,
+ COLLECTION_COLOR_03 = 3,
+ COLLECTION_COLOR_04 = 4,
+ COLLECTION_COLOR_05 = 5,
+ COLLECTION_COLOR_06 = 6,
+ COLLECTION_COLOR_07 = 7,
+ COLLECTION_COLOR_08 = 8,
+};
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 136fe3744ef..2754304a582 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -455,6 +455,10 @@ typedef enum eWireColor_Flags {
/* TH_WIRECOLOR_TEXTCOLS = (1 << 1), */ /* UNUSED */
} eWireColor_Flags;
+typedef struct ThemeCollectionColor {
+ unsigned char color[4];
+} ThemeCollectionColor;
+
/**
* A theme.
*
@@ -493,6 +497,8 @@ typedef struct bTheme {
ThemeWireColor tarm[20];
/*ThemeWireColor tobj[20];*/
+ ThemeCollectionColor collection_color[8];
+
int active_theme_area;
char _pad0[4];
} bTheme;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 6acd9d16f80..ce4251d00ed 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -633,6 +633,7 @@ extern StructRNA RNA_TextureNodeViewer;
extern StructRNA RNA_TextureSlot;
extern StructRNA RNA_Theme;
extern StructRNA RNA_ThemeBoneColorSet;
+extern StructRNA RNA_ThemeCollectionColor;
extern StructRNA RNA_ThemeConsole;
extern StructRNA RNA_ThemeDopeSheet;
extern StructRNA RNA_ThemeFileBrowser;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index fb9b62e729a..18af71d83db 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -229,6 +229,8 @@ extern const EnumPropertyItem rna_enum_context_mode_items[];
extern const EnumPropertyItem rna_enum_curveprofile_preset_items[];
extern const EnumPropertyItem rna_enum_preference_section_items[];
+extern const EnumPropertyItem rna_enum_collection_color_items[];
+
/* API calls */
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
int rna_node_tree_idname_to_enum(const char *idname);
diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c
index 9c6c95f2819..ecf7adfa925 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -30,6 +30,19 @@
#include "WM_types.h"
+const EnumPropertyItem rna_enum_collection_color_items[] = {
+ {COLLECTION_COLOR_NONE, "NONE", ICON_X, "None", "Assign no color tag to the collection"},
+ {COLLECTION_COLOR_01, "COLOR_01", ICON_COLLECTION_COLOR_01, "Color 01", ""},
+ {COLLECTION_COLOR_02, "COLOR_02", ICON_COLLECTION_COLOR_02, "Color 02", ""},
+ {COLLECTION_COLOR_03, "COLOR_03", ICON_COLLECTION_COLOR_03, "Color 03", ""},
+ {COLLECTION_COLOR_04, "COLOR_04", ICON_COLLECTION_COLOR_04, "Color 04", ""},
+ {COLLECTION_COLOR_05, "COLOR_05", ICON_COLLECTION_COLOR_05, "Color 05", ""},
+ {COLLECTION_COLOR_06, "COLOR_06", ICON_COLLECTION_COLOR_06, "Color 06", ""},
+ {COLLECTION_COLOR_07, "COLOR_07", ICON_COLLECTION_COLOR_07, "Color 07", ""},
+ {COLLECTION_COLOR_08, "COLOR_08", ICON_COLLECTION_COLOR_08, "Color 08", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "DNA_object_types.h"
@@ -474,6 +487,12 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
+ prop = RNA_def_property(srna, "color", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "color");
+ RNA_def_property_enum_items(prop, rna_enum_collection_color_items);
+ RNA_def_property_ui_text(prop, "Collection Color", "Color tag for a collection");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
RNA_define_lib_overridable(false);
}
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 8dfa54b95da..5c98044f975 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -977,6 +977,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in operator");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in buttons, no text");
func = RNA_def_function(srna, "operator_menu_enum", "rna_uiItemMenuEnumO");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 90873fa73f4..c5e08f3e54c 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3615,6 +3615,23 @@ static void rna_def_userdef_theme_colorset(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
}
+static void rna_def_userdef_theme_collection_color(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThemeCollectionColor", NULL);
+ RNA_def_struct_sdna(srna, "ThemeCollectionColor");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Theme Collection Color", "Theme settings for collection colors");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "color");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Collection Color Tag");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+}
+
static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3931,6 +3948,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "tarm", "");
RNA_def_property_struct_type(prop, "ThemeBoneColorSet");
RNA_def_property_ui_text(prop, "Bone Color Sets", "");
+
+ prop = RNA_def_property(srna, "collection_color", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_collection_sdna(prop, NULL, "collection_color", "");
+ RNA_def_property_struct_type(prop, "ThemeCollectionColor");
+ RNA_def_property_ui_text(prop, "Collection Color", "");
}
static void rna_def_userdef_addon(BlenderRNA *brna)
@@ -4172,6 +4195,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna)
rna_def_userdef_theme_space_topbar(brna);
rna_def_userdef_theme_space_statusbar(brna);
rna_def_userdef_theme_colorset(brna);
+ rna_def_userdef_theme_collection_color(brna);
rna_def_userdef_themes(brna);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 9b25d660ff6..1fee0991372 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3991,6 +3991,12 @@ static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C),
if (local == false || !ID_IS_LINKED(id)) {
item_tmp.identifier = item_tmp.name = id->name + 2;
item_tmp.value = i++;
+
+ /* Show collection color tag icons in menus. */
+ if (GS(id->name) == ID_GR) {
+ item_tmp.icon = UI_collection_color_icon_get((Collection *)id);
+ }
+
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
}