diff --git a/source/blender/blenkernel/BKE_idtype.hh b/source/blender/blenkernel/BKE_idtype.hh index 4147204d24c..0eb322f9df9 100644 --- a/source/blender/blenkernel/BKE_idtype.hh +++ b/source/blender/blenkernel/BKE_idtype.hh @@ -48,6 +48,20 @@ enum { * data-blocks. */ IDTYPE_FLAGS_NO_MEMFILE_UNDO = 1 << 5, + /** + * Indicates that the given IDType is considered as unused. + * + * This is used for some 'root' ID types which typically do not have any actual user (WM. + * Scene...). It prevents e.g. their deletion through the 'Purge' operation. + * + * \note This applies to local IDs. Linked data should essentially ignore this flag. In practice, + * currently, only the Scene ID can be linked among the `never unused` types. + * + * \note The implementation of the expected behaviors related to this characteristic is somewhat + * fragile and inconsistent currently. In most case though, code is expected to ensure that such + * IDs have at least an 'extra user' (#LIB_TAG_EXTRAUSER). + */ + IDTYPE_FLAGS_NEVER_UNUSED = 1 << 6, }; struct IDCacheKey { diff --git a/source/blender/blenkernel/intern/lib_query.cc b/source/blender/blenkernel/intern/lib_query.cc index bfb0995c149..f79e231a009 100644 --- a/source/blender/blenkernel/intern/lib_query.cc +++ b/source/blender/blenkernel/intern/lib_query.cc @@ -753,7 +753,8 @@ static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIDsData &data) return false; } - if (ELEM(GS(id->name), ID_WM, ID_WS, ID_SCE, ID_SCR, ID_LI)) { + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); + if (id_type->flags & IDTYPE_FLAGS_NEVER_UNUSED) { /* Some 'root' ID types are never unused (even though they may not have actual users), unless * their actual user-count is set to 0. */ id_relations->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; diff --git a/source/blender/blenkernel/intern/library.cc b/source/blender/blenkernel/intern/library.cc index 5a631c937ba..b1150d91f49 100644 --- a/source/blender/blenkernel/intern/library.cc +++ b/source/blender/blenkernel/intern/library.cc @@ -86,7 +86,8 @@ IDTypeInfo IDType_ID_LI = { /*name*/ "Library", /*name_plural*/ N_("libraries"), /*translation_context*/ BLT_I18NCONTEXT_ID_LIBRARY, - /*flags*/ IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA, + /*flags*/ IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA | + IDTYPE_FLAGS_NEVER_UNUSED, /*asset_type_info*/ nullptr, /*init_data*/ nullptr, diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index d7c383bae56..8323248e7bc 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -1594,7 +1594,7 @@ constexpr IDTypeInfo get_type_info() info.name = "Scene"; info.name_plural = "scenes"; info.translation_context = BLT_I18NCONTEXT_ID_SCENE; - info.flags = 0; + info.flags = IDTYPE_FLAGS_NEVER_UNUSED; info.asset_type_info = nullptr; info.init_data = scene_init_data; diff --git a/source/blender/blenkernel/intern/screen.cc b/source/blender/blenkernel/intern/screen.cc index 7efc51aa979..f192c7a60bb 100644 --- a/source/blender/blenkernel/intern/screen.cc +++ b/source/blender/blenkernel/intern/screen.cc @@ -168,7 +168,7 @@ IDTypeInfo IDType_ID_SCR = { /*name_plural*/ N_("screens"), /*translation_context*/ BLT_I18NCONTEXT_ID_SCREEN, /*flags*/ IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_ONLY_APPEND | IDTYPE_FLAGS_NO_ANIMDATA | - IDTYPE_FLAGS_NO_MEMFILE_UNDO, + IDTYPE_FLAGS_NO_MEMFILE_UNDO | IDTYPE_FLAGS_NEVER_UNUSED, /*asset_type_info*/ nullptr, /*init_data*/ nullptr, diff --git a/source/blender/blenkernel/intern/workspace.cc b/source/blender/blenkernel/intern/workspace.cc index ea4d07825c8..26a154159e8 100644 --- a/source/blender/blenkernel/intern/workspace.cc +++ b/source/blender/blenkernel/intern/workspace.cc @@ -180,7 +180,7 @@ IDTypeInfo IDType_ID_WS = { /*name_plural*/ N_("workspaces"), /*translation_context*/ BLT_I18NCONTEXT_ID_WORKSPACE, /*flags*/ IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_ONLY_APPEND | IDTYPE_FLAGS_NO_ANIMDATA | - IDTYPE_FLAGS_NO_MEMFILE_UNDO, + IDTYPE_FLAGS_NO_MEMFILE_UNDO | IDTYPE_FLAGS_NEVER_UNUSED, /*asset_type_info*/ nullptr, /*init_data*/ workspace_init_data, diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 4d53e2d3553..1bd25a1f56d 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -1311,10 +1311,11 @@ static bool write_file_handle(Main *mainvar, /* We only write unused IDs in undo case. */ if (!wd->use_memfile) { - /* NOTE: All Scenes, WindowManagers and WorkSpaces should always be written to disk, so - * their user-count should never be zero currently. */ + /* NOTE: All 'never unused' local IDs (Scenes, WindowManagers, ...) should always be + * written to disk, so their user-count should never be zero currently. Note that + * libraries have already been skipped above, as they need a specific handling. */ if (id->us == 0) { - BLI_assert(!ELEM(GS(id->name), ID_SCE, ID_WM, ID_WS)); + BLI_assert((id_type->flags & IDTYPE_FLAGS_NEVER_UNUSED) == 0); continue; } diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc index 4715918196b..0f737172d59 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc @@ -13,6 +13,7 @@ #include "BLI_listbase_wrapper.hh" #include "BLI_utildefines.h" +#include "BKE_idtype.hh" #include "BKE_main.hh" #include "../outliner_intern.hh" @@ -75,6 +76,15 @@ ListBase TreeDisplayIDOrphans::build_tree(const TreeSourceData &source_data) bool TreeDisplayIDOrphans::datablock_has_orphans(ListBase &lb) const { + if (BLI_listbase_is_empty(&lb)) { + return false; + } + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(static_cast(lb.first)); + if (id_type->flags & IDTYPE_FLAGS_NEVER_UNUSED) { + /* These ID types are never unused. */ + return false; + } + for (ID *id : List(lb)) { if (ID_REFCOUNTING_USERS(id) <= 0) { return true; diff --git a/source/blender/windowmanager/intern/wm.cc b/source/blender/windowmanager/intern/wm.cc index ca987249351..df3a645a78a 100644 --- a/source/blender/windowmanager/intern/wm.cc +++ b/source/blender/windowmanager/intern/wm.cc @@ -254,7 +254,7 @@ IDTypeInfo IDType_ID_WM = { /*name_plural*/ N_("window_managers"), /*translation_context*/ BLT_I18NCONTEXT_ID_WINDOWMANAGER, /*flags*/ IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA | - IDTYPE_FLAGS_NO_MEMFILE_UNDO, + IDTYPE_FLAGS_NO_MEMFILE_UNDO | IDTYPE_FLAGS_NEVER_UNUSED, /*asset_type_info*/ nullptr, /*init_data*/ nullptr,