diff options
author | Nathan Craddock <nzcraddock@gmail.com> | 2020-08-19 06:22:43 +0300 |
---|---|---|
committer | Nathan Craddock <nzcraddock@gmail.com> | 2020-08-19 06:23:43 +0300 |
commit | 093294e167508ff04362030350e05e9921683ca2 (patch) | |
tree | 51e0f37c0814e51643a2f9e799b245729f0b7d67 | |
parent | 349eebd7d1459fa2525850751040963899ef7535 (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.
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); } } |