diff options
8 files changed, 167 insertions, 12 deletions
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index a586f268128..8bcd50161bd 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -79,6 +79,7 @@ #include "RNA_access.h" #include "outliner_intern.h" +#include "tree/tree_display.h" /* Disable - this is far too slow - campbell. */ /* #define USE_GROUP_SELECT */ @@ -2143,6 +2144,80 @@ static void outliner_draw_mode_column(const bContext *C, } } +/* Returns `true` if some warning was drawn for that element or one of its sub-elements (if it is + * not open). */ +static bool outliner_draw_warning_tree_element(uiBlock *block, + SpaceOutliner *space_outliner, + TreeElement *te, + TreeStoreElem *tselem, + const bool use_mode_column, + const int te_ys) +{ + if ((te->flag & TE_HAS_WARNING) == 0) { + /* If given element has no warning, recusively try to display the first sub-elements' warning. + */ + if (!TSELEM_OPEN(tselem, space_outliner)) { + LISTBASE_FOREACH (TreeElement *, sub_te, &te->subtree) { + TreeStoreElem *sub_tselem = TREESTORE(sub_te); + + if (outliner_draw_warning_tree_element( + block, space_outliner, sub_te, sub_tselem, use_mode_column, te_ys)) { + return true; + } + } + } + return false; + } + + int icon = ICON_NONE; + const char *tip = ""; + const bool has_warning = outliner_element_warnings_get(te, &icon, &tip); + BLI_assert(has_warning); + UNUSED_VARS_NDEBUG(has_warning); + + /* Move the warnings a unit left in view layer mode. */ + const short mode_column_offset = (use_mode_column && (space_outliner->outlinevis == SO_SCENES)) ? + UI_UNIT_X : + 0; + + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); + uiBut *but = uiDefIconBut(block, + UI_BTYPE_ICON_TOGGLE, + 0, + icon, + mode_column_offset, + te_ys, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + tip); + /* No need for undo here, this is a pure info widget. */ + UI_but_flag_disable(but, UI_BUT_UNDO); + + return true; +} + +static void outliner_draw_warning_column(const bContext *C, + uiBlock *block, + SpaceOutliner *space_outliner, + const bool use_mode_column, + ListBase *tree) +{ + LISTBASE_FOREACH (TreeElement *, te, tree) { + TreeStoreElem *tselem = TREESTORE(te); + + outliner_draw_warning_tree_element(block, space_outliner, te, tselem, use_mode_column, te->ys); + + if (TSELEM_OPEN(tselem, space_outliner)) { + outliner_draw_warning_column(C, block, space_outliner, use_mode_column, &te->subtree); + } + } +} + /* ****************************************************** */ /* Normal Drawing... */ @@ -3612,17 +3687,22 @@ static void outliner_draw_tree(bContext *C, SpaceOutliner *space_outliner, const float restrict_column_width, const bool use_mode_column, + const bool use_warning_column, TreeElement **te_edit) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; int starty, startx; /* Move the tree a unit left in view layer mode */ - short mode_column_offset = (use_mode_column && (space_outliner->outlinevis == SO_SCENES)) ? - UI_UNIT_X : - 0; + short columns_offset = (use_mode_column && (space_outliner->outlinevis == SO_SCENES)) ? + UI_UNIT_X : + 0; if (!use_mode_column && (space_outliner->outlinevis == SO_VIEW_LAYER)) { - mode_column_offset -= UI_UNIT_X; + columns_offset -= UI_UNIT_X; + } + + if (use_warning_column) { + columns_offset += UI_UNIT_X; } GPU_blend(GPU_BLEND_ALPHA); /* Only once. */ @@ -3650,12 +3730,12 @@ static void outliner_draw_tree(bContext *C, /* Draw hierarchy lines for collections and object children. */ starty = (int)region->v2d.tot.ymax - OL_Y_OFFSET; - startx = mode_column_offset + UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; + startx = columns_offset + UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty); /* Items themselves. */ starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; - startx = mode_column_offset; + startx = columns_offset; LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) { outliner_draw_tree_element(C, block, @@ -3786,6 +3866,10 @@ void draw_outliner(const bContext *C) const bool use_mode_column = (space_outliner->flag & SO_MODE_COLUMN) && (ELEM(space_outliner->outlinevis, SO_VIEW_LAYER, SO_SCENES)); + const bool use_warning_column = + ELEM(space_outliner->outlinevis, SO_LIBRARIES, SO_OVERRIDES_LIBRARY) && + outliner_tree_display_warnings_poll(space_outliner->runtime->tree_display); + /* Draw outliner stuff (background, hierarchy lines and names). */ const float restrict_column_width = outliner_restrict_columns_width(space_outliner); outliner_back(region); @@ -3797,6 +3881,7 @@ void draw_outliner(const bContext *C) space_outliner, restrict_column_width, use_mode_column, + use_warning_column, &te_edit); /* Compute outliner dimensions after it has been drawn. */ @@ -3841,6 +3926,11 @@ void draw_outliner(const bContext *C) outliner_draw_mode_column(C, block, &tvc, space_outliner, &space_outliner->tree); } + /* Draw warning icons */ + if (use_warning_column) { + outliner_draw_warning_column(C, block, space_outliner, use_mode_column, &space_outliner->tree); + } + UI_block_emboss_set(block, UI_EMBOSS); /* Draw edit buttons if necessary. */ diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index e331887319e..24e86e06f68 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -158,6 +158,8 @@ enum { /* Child elements of the same type in the icon-row are drawn merged as one icon. * This flag is set for an element that is part of these merged child icons. */ TE_ICONROW_MERGED = (1 << 7), + /* This element has some warning to be displayed. */ + TE_HAS_WARNING = (1 << 8), }; /* button events */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 3353726de18..e461eb4c69e 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -74,6 +74,7 @@ #include "RNA_access.h" #include "UI_interface.h" +#include "UI_resources.h" #include "outliner_intern.h" #include "tree/tree_display.h" @@ -812,6 +813,41 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } } +bool outliner_element_warnings_get(TreeElement *te, int *r_icon, const char **r_message) +{ + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->type != TSE_SOME_ID) { + return false; + } + if (te->idcode != ID_LI) { + return false; + } + + Library *library = (Library *)tselem->id; + if (library->tag & LIBRARY_TAG_RESYNC_REQUIRED) { + if (r_icon) { + *r_icon = ICON_ERROR; + } + if (r_message) { + *r_message = TIP_( + "Contains linked library overrides that need to be resynced, updating the library is " + "recommended"); + } + return true; + } + if (library->id.tag & LIB_TAG_MISSING) { + if (r_icon) { + *r_icon = ICON_ERROR; + } + if (r_message) { + *r_message = TIP_("Missing library"); + } + return true; + } + return false; +} + TreeElement *outliner_add_element(SpaceOutliner *space_outliner, ListBase *lb, void *idv, @@ -1115,6 +1151,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } + if (outliner_element_warnings_get(te, NULL, NULL)) { + te->flag |= TE_HAS_WARNING; + } + return te; } diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index 003afd5bdec..e192929c7cf 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -66,3 +66,10 @@ ListBase outliner_tree_display_build_tree(TreeDisplay *tree_display, TreeSourceD { return reinterpret_cast<AbstractTreeDisplay *>(tree_display)->buildTree(*source_data); } + +bool outliner_tree_display_warnings_poll(const TreeDisplay *tree_display) +{ + const AbstractTreeDisplay *abstract_tree_display = reinterpret_cast<const AbstractTreeDisplay *>( + tree_display); + return abstract_tree_display->has_warnings; +} diff --git a/source/blender/editors/space_outliner/tree/tree_display.h b/source/blender/editors/space_outliner/tree/tree_display.h index b6dc33ba7b7..7b959576a4b 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.h +++ b/source/blender/editors/space_outliner/tree/tree_display.h @@ -47,6 +47,16 @@ void outliner_tree_display_destroy(TreeDisplay **tree_display); ListBase outliner_tree_display_build_tree(TreeDisplay *tree_display, TreeSourceData *source_data); +/** Accessor to whether given tree has some warnings to display. */ +bool outliner_tree_display_warnings_poll(const struct TreeDisplay *tree_display); + +/** Get actual warning data of a tree element, if any. + * + * \param r_icon The icon to display as warning. + * \param r_message The message to display as warning. + * \return true if there is a warning, false otherwise. */ +bool outliner_element_warnings_get(struct TreeElement *te, int *r_icon, const char **r_message); + /* The following functions are needed to build the tree. They are calls back into C; the way * elements are created should be refactored and ported to C++ with a new design/API too. */ /** diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index 54e64655b18..bf9cf18948c 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -65,6 +65,8 @@ class AbstractTreeDisplay { */ virtual ListBase buildTree(const TreeSourceData &source_data) = 0; + bool has_warnings = false; + protected: /** All derived classes will need a handle to this, so storing it in the base for convenience. */ SpaceOutliner &space_outliner_; @@ -105,7 +107,7 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; private: - TreeElement *add_library_contents(Main &, ListBase &, Library *) const; + TreeElement *add_library_contents(Main &, ListBase &, Library *); bool library_id_filter_poll(const Library *lib, ID *id) const; short id_filter_get() const; }; @@ -123,7 +125,7 @@ class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; private: - TreeElement *add_library_contents(Main &, ListBase &, Library *) const; + TreeElement *add_library_contents(Main &, ListBase &, Library *); bool override_library_id_filter_poll(const Library *lib, ID *id) const; short id_filter_get() const; }; diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc index 836f0937cf4..461104e6bad 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc @@ -104,9 +104,7 @@ ListBase TreeDisplayLibraries::buildTree(const TreeSourceData &source_data) return tree; } -TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, - ListBase &lb, - Library *lib) const +TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, ListBase &lb, Library *lib) { const short filter_id_type = id_filter_get(); @@ -149,6 +147,9 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0); tenlib->name = IFACE_("Current File"); } + if (tenlib->flag & TE_HAS_WARNING) { + has_warnings = true; + } } /* Create data-block list parent element on demand. */ diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc index 943e182277c..bf9fba30c9f 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc @@ -112,7 +112,7 @@ ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, ListBase &lb, - Library *lib) const + Library *lib) { const short filter_id_type = id_filter_get(); @@ -152,6 +152,9 @@ TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0); tenlib->name = IFACE_("Current File"); } + if (tenlib->flag & TE_HAS_WARNING) { + has_warnings = true; + } } /* Create data-block list parent element on demand. */ |