From d7d487e13a503ebd6b366e6e3b74714fe8610b1a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 17 Aug 2023 14:42:04 +0200 Subject: [PATCH] Refactor: Move Editors' 'foreach_id' code into a new SpaceType callback. Was a known pending TODO for quite some time already. This commit should have no behavior change at all. --- source/blender/blenkernel/BKE_screen.h | 7 + source/blender/blenkernel/intern/screen.cc | 234 +----------------- .../editors/space_action/space_action.cc | 21 ++ .../editors/space_buttons/space_buttons.cc | 19 ++ .../blender/editors/space_clip/space_clip.cc | 16 ++ .../blender/editors/space_file/space_file.cc | 16 ++ .../editors/space_graph/space_graph.cc | 23 ++ .../editors/space_image/space_image.cc | 17 ++ source/blender/editors/space_nla/space_nla.cc | 15 ++ .../blender/editors/space_node/space_node.cc | 92 +++++++ .../editors/space_outliner/space_outliner.cc | 34 +++ .../editors/space_script/space_script.cc | 8 + .../space_sequencer/space_sequencer.cc | 9 + .../space_spreadsheet/space_spreadsheet.cc | 7 + .../blender/editors/space_text/space_text.cc | 8 + .../editors/space_view3d/space_view3d.cc | 14 ++ 16 files changed, 309 insertions(+), 231 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index ceac55ad82b..4782bf3c9d3 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -105,6 +105,13 @@ typedef struct SpaceType { /* Used when we want to replace an ID by another (or NULL). */ void (*id_remap)(struct ScrArea *area, struct SpaceLink *sl, const struct IDRemapper *mappings); + /** + * foreach_id callback to process all ID pointers of the editor. Used indirectly by lib_query's + * #BKE_library_foreach_ID_link when #IDWALK_INCLUDE_UI bitflag is set (through WM's foreach_id + * usage of #BKE_screen_foreach_id_screen_area). + */ + void (*foreach_id)(struct SpaceLink *space_link, struct LibraryForeachIDData *data); + int (*space_subtype_get)(struct ScrArea *area); void (*space_subtype_set)(struct ScrArea *area, int value); void (*space_subtype_item_extend)(struct bContext *C, EnumPropertyItem **item, int *totitem); diff --git a/source/blender/blenkernel/intern/screen.cc b/source/blender/blenkernel/intern/screen.cc index 460b7551cb9..b769a34b5fe 100644 --- a/source/blender/blenkernel/intern/screen.cc +++ b/source/blender/blenkernel/intern/screen.cc @@ -81,243 +81,15 @@ static void screen_free_data(ID *id) MEM_SAFE_FREE(screen->tool_tip); } -static void screen_foreach_id_dopesheet(LibraryForeachIDData *data, bDopeSheet *ads) -{ - if (ads != nullptr) { - BKE_LIB_FOREACHID_PROCESS_ID(data, ads->source, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, ads->filter_grp, IDWALK_CB_NOP); - } -} - void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area) { - const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); - const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; - const bool allow_pointer_access = (data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, area->full, IDWALK_CB_NOP); - /* TODO: this should be moved to a callback in `SpaceType`, defined in each editor's own code. - * Will be for a later round of cleanup though... */ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - switch (sl->spacetype) { - case SPACE_VIEW3D: { - View3D *v3d = (View3D *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->camera, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->ob_center, IDWALK_CB_NOP); - if (v3d->localvd) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->localvd->camera, IDWALK_CB_NOP); - } - BKE_viewer_path_foreach_id(data, &v3d->viewer_path); - break; - } - case SPACE_GRAPH: { - SpaceGraph *sipo = (SpaceGraph *)sl; - BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, - screen_foreach_id_dopesheet(data, sipo->ads)); + SpaceType *space_type = BKE_spacetype_from_id(sl->spacetype); - if (!is_readonly) { - /* Force recalc of list of channels (i.e. including calculating F-Curve colors) to - * prevent the "black curves" problem post-undo. */ - sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR; - } - break; - } - case SPACE_PROPERTIES: { - SpaceProperties *sbuts = (SpaceProperties *)sl; - BKE_LIB_FOREACHID_PROCESS_ID(data, sbuts->pinid, IDWALK_CB_NOP); - if (!is_readonly) { - if (sbuts->pinid == nullptr) { - sbuts->flag &= ~SB_PIN_CONTEXT; - } - /* NOTE: Restoring path pointers is complicated, if not impossible, because this contains - * data pointers too, not just ID ones. See #40046. */ - MEM_SAFE_FREE(sbuts->path); - } - break; - } - case SPACE_FILE: { - if (!is_readonly) { - SpaceFile *sfile = (SpaceFile *)sl; - sfile->op = nullptr; - sfile->tags = FILE_TAG_REBUILD_MAIN_FILES; - } - break; - } - case SPACE_ACTION: { - SpaceAction *saction = (SpaceAction *)sl; - screen_foreach_id_dopesheet(data, &saction->ads); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, saction->action, IDWALK_CB_NOP); - if (!is_readonly) { - /* Force recalc of list of channels, potentially updating the active action while we're - * at it (as it can only be updated that way) #28962. */ - saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; - } - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = (SpaceImage *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->image, IDWALK_CB_USER_ONE); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->iuser.scene, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->mask_info.mask, IDWALK_CB_USER_ONE); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->gpd, IDWALK_CB_USER); - if (!is_readonly) { - sima->scopes.ok = 0; - } - break; - } - case SPACE_SEQ: { - SpaceSeq *sseq = (SpaceSeq *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sseq->gpd, IDWALK_CB_USER); - break; - } - case SPACE_NLA: { - SpaceNla *snla = (SpaceNla *)sl; - BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, - screen_foreach_id_dopesheet(data, snla->ads)); - break; - } - case SPACE_TEXT: { - SpaceText *st = (SpaceText *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, st->text, IDWALK_CB_USER_ONE); - break; - } - case SPACE_SCRIPT: { - SpaceScript *scpt = (SpaceScript *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scpt->script, IDWALK_CB_NOP); - break; - } - case SPACE_OUTLINER: { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - if (space_outliner->treestore != nullptr) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - - BLI_mempool_iternew(space_outliner->treestore, &iter); - while ((tselem = static_cast(BLI_mempool_iterstep(&iter)))) { - /* Do not try to restore non-ID pointers (drivers/sequence/etc.). */ - if (TSE_IS_REAL_ID(tselem)) { - const int cb_flag = (tselem->id != nullptr && allow_pointer_access && - (tselem->id->flag & LIB_EMBEDDED_DATA) != 0) ? - IDWALK_CB_EMBEDDED_NOT_OWNING : - IDWALK_CB_NOP; - BKE_LIB_FOREACHID_PROCESS_ID(data, tselem->id, cb_flag); - } - else if (!is_readonly) { - tselem->id = nullptr; - } - } - if (!is_readonly) { - /* rebuild hash table, because it depends on ids too */ - space_outliner->storeflag |= SO_TREESTORE_REBUILD; - } - } - break; - } - case SPACE_NODE: { - SpaceNode *snode = (SpaceNode *)sl; - const bool is_embedded_nodetree = snode->id != nullptr && allow_pointer_access && - ntreeFromID(snode->id) == snode->nodetree; - - BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP); - - bNodeTreePath *path = static_cast(snode->treepath.first); - BLI_assert(path == nullptr || path->nodetree == snode->nodetree); - - if (is_embedded_nodetree) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING); - if (path != nullptr) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING); - } - - /* Embedded ID pointers are not remapped (besides exceptions), ensure it still matches - * actual data. Note that `snode->id` was already processed (and therefore potentially - * remapped) above. */ - if (!is_readonly) { - snode->nodetree = (snode->id == nullptr) ? nullptr : ntreeFromID(snode->id); - if (path != nullptr) { - path->nodetree = snode->nodetree; - } - } - } - else { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_USER_ONE); - if (path != nullptr) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE); - } - } - - /* Both `snode->id` and `snode->nodetree` have been remapped now, so their data can be - * accessed. */ - BLI_assert(snode->id == nullptr || snode->nodetree == nullptr || - (snode->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0 || - snode->nodetree == ntreeFromID(snode->id)); - - if (path != nullptr) { - for (path = path->next; path != nullptr; path = path->next) { - BLI_assert(path->nodetree != nullptr); - if ((data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0) { - BLI_assert((path->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0); - } - - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE); - - if (path->nodetree == nullptr) { - BLI_assert(!is_readonly); - /* Remaining path entries are invalid, remove them. */ - for (bNodeTreePath *path_next; path; path = path_next) { - path_next = path->next; - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); - } - break; - } - } - } - BLI_assert(path == nullptr); - - if (!is_readonly) { - /* `edittree` is just the last in the path, set this directly since the path may have - * been shortened above. */ - if (snode->treepath.last != nullptr) { - path = static_cast(snode->treepath.last); - snode->edittree = path->nodetree; - } - else { - snode->edittree = nullptr; - } - } - else { - /* Only process this pointer in readonly case, otherwise could lead to a bad - * double-remapping e.g. */ - if (is_embedded_nodetree && snode->edittree == snode->nodetree) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER( - data, snode->edittree, IDWALK_CB_EMBEDDED_NOT_OWNING); - } - else { - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->edittree, IDWALK_CB_NOP); - } - } - break; - } - case SPACE_CLIP: { - SpaceClip *sclip = (SpaceClip *)sl; - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->clip, IDWALK_CB_USER_ONE); - BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE); - - if (!is_readonly) { - sclip->scopes.ok = 0; - } - break; - } - case SPACE_SPREADSHEET: { - SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - BKE_viewer_path_foreach_id(data, &sspreadsheet->viewer_path); - break; - } - default: - break; + if (space_type && space_type->foreach_id) { + space_type->foreach_id(sl, data); } } } diff --git a/source/blender/editors/space_action/space_action.cc b/source/blender/editors/space_action/space_action.cc index 08a4e154c59..305d61c3479 100644 --- a/source/blender/editors/space_action/space_action.cc +++ b/source/blender/editors/space_action/space_action.cc @@ -21,6 +21,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_nla.h" #include "BKE_screen.h" @@ -805,6 +806,25 @@ static void action_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapp BKE_id_remapper_apply(mappings, &sact->ads.source, ID_REMAP_APPLY_DEFAULT); } +static void action_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceAction *sact = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sact->action, IDWALK_CB_NOP); + + /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceNla and #SpaceGraph. */ + BKE_LIB_FOREACHID_PROCESS_ID(data, sact->ads.source, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sact->ads.filter_grp, IDWALK_CB_NOP); + + if (!is_readonly) { + /* Force recalc of list of channels, potentially updating the active action while we're + * at it (as it can only be updated that way) #28962. */ + sact->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; + } +} + /** * \note Used for splitting out a subset of modes is more involved, * The previous non-timeline mode is stored so switching back to the @@ -884,6 +904,7 @@ void ED_spacetype_action() st->listener = action_listener; st->refresh = action_refresh; st->id_remap = action_id_remap; + st->foreach_id = action_foreach_id; st->space_subtype_item_extend = action_space_subtype_item_extend; st->space_subtype_get = action_space_subtype_get; st->space_subtype_set = action_space_subtype_set; diff --git a/source/blender/editors/space_buttons/space_buttons.cc b/source/blender/editors/space_buttons/space_buttons.cc index bb955e744dc..a33cf4afa6f 100644 --- a/source/blender/editors/space_buttons/space_buttons.cc +++ b/source/blender/editors/space_buttons/space_buttons.cc @@ -17,6 +17,7 @@ #include "BKE_context.h" #include "BKE_gpencil_modifier_legacy.h" /* Types for registering panels. */ +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_modifier.h" #include "BKE_screen.h" @@ -906,6 +907,23 @@ static void buttons_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemap } } +static void buttons_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceProperties *sbuts = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + BKE_LIB_FOREACHID_PROCESS_ID(data, sbuts->pinid, IDWALK_CB_NOP); + if (!is_readonly) { + if (sbuts->pinid == nullptr) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } + /* NOTE: Restoring path pointers is complicated, if not impossible, because this contains + * data pointers too, not just ID ones. See #40046. */ + MEM_SAFE_FREE(sbuts->path); + } +} + static void buttons_space_blend_read_data(BlendDataReader * /*reader*/, SpaceLink *sl) { SpaceProperties *sbuts = (SpaceProperties *)sl; @@ -954,6 +972,7 @@ void ED_spacetype_buttons() st->listener = buttons_area_listener; st->context = buttons_context; st->id_remap = buttons_id_remap; + st->foreach_id = buttons_foreach_id; st->blend_read_data = buttons_space_blend_read_data; st->blend_read_lib = buttons_space_blend_read_lib; st->blend_write = buttons_space_blend_write; diff --git a/source/blender/editors/space_clip/space_clip.cc b/source/blender/editors/space_clip/space_clip.cc index 456f647cff9..417566eb075 100644 --- a/source/blender/editors/space_clip/space_clip.cc +++ b/source/blender/editors/space_clip/space_clip.cc @@ -23,6 +23,7 @@ #include "BKE_context.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_movieclip.h" #include "BKE_screen.h" @@ -1162,6 +1163,20 @@ static void clip_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper BKE_id_remapper_apply(mappings, (ID **)&sclip->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); } +static void clip_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceClip *sclip = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->clip, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE); + + if (!is_readonly) { + sclip->scopes.ok = 0; + } +} + static void clip_space_blend_read_data(BlendDataReader * /*reader*/, SpaceLink *sl) { SpaceClip *sclip = (SpaceClip *)sl; @@ -1209,6 +1224,7 @@ void ED_spacetype_clip() st->dropboxes = clip_dropboxes; st->refresh = clip_refresh; st->id_remap = clip_id_remap; + st->foreach_id = clip_foreach_id; st->blend_read_data = clip_space_blend_read_data; st->blend_read_lib = clip_space_blend_read_lib; st->blend_write = clip_space_blend_write; diff --git a/source/blender/editors/space_file/space_file.cc b/source/blender/editors/space_file/space_file.cc index 35325d50836..92c77d85774 100644 --- a/source/blender/editors/space_file/space_file.cc +++ b/source/blender/editors/space_file/space_file.cc @@ -18,6 +18,7 @@ #include "BKE_appdir.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_report.h" @@ -843,6 +844,20 @@ static void file_id_remap(ScrArea *area, SpaceLink *sl, const IDRemapper * /*map file_reset_filelist_showing_main_data(area, sfile); } +static void file_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceFile *sfile = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + /* TODO: investigate whether differences between this code and the one in #file_id_remap are + * meaningful and make sense or not. */ + if (!is_readonly) { + sfile->op = nullptr; + sfile->tags = FILE_TAG_REBUILD_MAIN_FILES; + } +} + static void file_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl) { SpaceFile *sfile = (SpaceFile *)sl; @@ -912,6 +927,7 @@ void ED_spacetype_file() st->space_subtype_set = file_space_subtype_set; st->context = file_context; st->id_remap = file_id_remap; + st->foreach_id = file_foreach_id; st->blend_read_data = file_space_blend_read_data; st->blend_read_lib = file_space_blend_read_lib; st->blend_write = file_space_blend_write; diff --git a/source/blender/editors/space_graph/space_graph.cc b/source/blender/editors/space_graph/space_graph.cc index 547cb6f2697..40c1111be01 100644 --- a/source/blender/editors/space_graph/space_graph.cc +++ b/source/blender/editors/space_graph/space_graph.cc @@ -21,6 +21,7 @@ #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" @@ -814,6 +815,27 @@ static void graph_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemappe BKE_id_remapper_apply(mappings, (ID **)&sgraph->ads->source, ID_REMAP_APPLY_DEFAULT); } +static void graph_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceGraph *sgraph = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceAction and #SpaceNla. */ + if (sgraph->ads == nullptr) { + return; + } + + BKE_LIB_FOREACHID_PROCESS_ID(data, sgraph->ads->source, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sgraph->ads->filter_grp, IDWALK_CB_NOP); + + if (!is_readonly) { + /* Force recalc of list of channels (i.e. including calculating F-Curve colors) to + * prevent the "black curves" problem post-undo. */ + sgraph->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR; + } +} + static int graph_space_subtype_get(ScrArea *area) { SpaceGraph *sgraph = static_cast(area->spacedata.first); @@ -886,6 +908,7 @@ void ED_spacetype_ipo() st->listener = graph_listener; st->refresh = graph_refresh; st->id_remap = graph_id_remap; + st->foreach_id = graph_foreach_id; st->space_subtype_item_extend = graph_space_subtype_item_extend; st->space_subtype_get = graph_space_subtype_get; st->space_subtype_set = graph_space_subtype_set; diff --git a/source/blender/editors/space_image/space_image.cc b/source/blender/editors/space_image/space_image.cc index 91ee6e67d6c..52389ddc8ff 100644 --- a/source/blender/editors/space_image/space_image.cc +++ b/source/blender/editors/space_image/space_image.cc @@ -23,6 +23,7 @@ #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" @@ -1003,6 +1004,21 @@ static void image_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemappe BKE_id_remapper_apply(mappings, (ID **)&simg->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); } +static void image_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceImage *simg = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, simg->image, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, simg->iuser.scene, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, simg->mask_info.mask, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, simg->gpd, IDWALK_CB_USER); + if (!is_readonly) { + simg->scopes.ok = 0; + } +} + /** * \note Used for splitting out a subset of modes is more involved, * The previous non-uv-edit mode is stored so switching back to the @@ -1097,6 +1113,7 @@ void ED_spacetype_image() st->context = image_context; st->gizmos = image_widgets; st->id_remap = image_id_remap; + st->foreach_id = image_foreach_id; st->space_subtype_item_extend = image_space_subtype_item_extend; st->space_subtype_get = image_space_subtype_get; st->space_subtype_set = image_space_subtype_set; diff --git a/source/blender/editors/space_nla/space_nla.cc b/source/blender/editors/space_nla/space_nla.cc index 61b09592dbc..2ee69f093d0 100644 --- a/source/blender/editors/space_nla/space_nla.cc +++ b/source/blender/editors/space_nla/space_nla.cc @@ -18,6 +18,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" @@ -570,6 +571,19 @@ static void nla_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper mappings, reinterpret_cast(&snla->ads->source), ID_REMAP_APPLY_DEFAULT); } +static void nla_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceNla *snla = reinterpret_cast(space_link); + + /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceAction and #SpaceGraph. */ + if (snla->ads == nullptr) { + return; + } + + BKE_LIB_FOREACHID_PROCESS_ID(data, snla->ads->source, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snla->ads->filter_grp, IDWALK_CB_NOP); +} + static void nla_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl) { SpaceNla *snla = reinterpret_cast(sl); @@ -613,6 +627,7 @@ void ED_spacetype_nla() st->listener = nla_listener; st->keymap = nla_keymap; st->id_remap = nla_id_remap; + st->foreach_id = nla_foreach_id; st->blend_read_data = nla_space_blend_read_data; st->blend_read_lib = nla_space_blend_read_lib; st->blend_write = nla_space_blend_write; diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 481df5229d9..7d128cc0c65 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -18,6 +18,7 @@ #include "BKE_context.h" #include "BKE_gpencil_legacy.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_node.hh" #include "BKE_node_runtime.hh" @@ -1029,6 +1030,96 @@ static void node_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper BKE_id_remapper_iter(mappings, node_id_remap_cb, slink); } +static void node_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceNode *snode = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + const bool allow_pointer_access = (data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0; + const bool is_embedded_nodetree = snode->id != nullptr && allow_pointer_access && + ntreeFromID(snode->id) == snode->nodetree; + + BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP); + + bNodeTreePath *path = static_cast(snode->treepath.first); + BLI_assert(path == nullptr || path->nodetree == snode->nodetree); + + if (is_embedded_nodetree) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING); + if (path != nullptr) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_EMBEDDED_NOT_OWNING); + } + + /* Embedded ID pointers are not remapped (besides exceptions), ensure it still matches + * actual data. Note that `snode->id` was already processed (and therefore potentially + * remapped) above. */ + if (!is_readonly) { + snode->nodetree = (snode->id == nullptr) ? nullptr : ntreeFromID(snode->id); + if (path != nullptr) { + path->nodetree = snode->nodetree; + } + } + } + else { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->nodetree, IDWALK_CB_USER_ONE); + if (path != nullptr) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE); + } + } + + /* Both `snode->id` and `snode->nodetree` have been remapped now, so their data can be + * accessed. */ + BLI_assert(snode->id == nullptr || snode->nodetree == nullptr || + (snode->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0 || + snode->nodetree == ntreeFromID(snode->id)); + + if (path != nullptr) { + for (path = path->next; path != nullptr; path = path->next) { + BLI_assert(path->nodetree != nullptr); + if ((data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0) { + BLI_assert((path->nodetree->id.flag & LIB_EMBEDDED_DATA) == 0); + } + + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, path->nodetree, IDWALK_CB_USER_ONE); + + if (path->nodetree == nullptr) { + BLI_assert(!is_readonly); + /* Remaining path entries are invalid, remove them. */ + for (bNodeTreePath *path_next; path; path = path_next) { + path_next = path->next; + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + } + break; + } + } + } + BLI_assert(path == nullptr); + + if (!is_readonly) { + /* `edittree` is just the last in the path, set this directly since the path may have + * been shortened above. */ + if (snode->treepath.last != nullptr) { + path = static_cast(snode->treepath.last); + snode->edittree = path->nodetree; + } + else { + snode->edittree = nullptr; + } + } + else { + /* Only process this pointer in readonly case, otherwise could lead to a bad + * double-remapping e.g. */ + if (is_embedded_nodetree && snode->edittree == snode->nodetree) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->edittree, IDWALK_CB_EMBEDDED_NOT_OWNING); + } + else { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, snode->edittree, IDWALK_CB_NOP); + } + } +} + static int node_space_subtype_get(ScrArea *area) { SpaceNode *snode = (SpaceNode *)area->spacedata.first; @@ -1151,6 +1242,7 @@ void ED_spacetype_node() st->dropboxes = node_dropboxes; st->gizmos = node_widgets; st->id_remap = node_id_remap; + st->foreach_id = node_foreach_id; st->space_subtype_item_extend = node_space_subtype_item_extend; st->space_subtype_get = node_space_subtype_get; st->space_subtype_set = node_space_subtype_set; diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index cd7ce11f4b7..552bcb2d6c4 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -19,6 +19,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_outliner_treehash.hh" #include "BKE_screen.h" @@ -441,6 +442,38 @@ static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const IDRemapper } } +static void outliner_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceOutliner *space_outliner = reinterpret_cast(space_link); + const int data_flags = BKE_lib_query_foreachid_process_flags_get(data); + const bool is_readonly = (data_flags & IDWALK_READONLY) != 0; + const bool allow_pointer_access = (data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0; + + if (space_outliner->treestore != nullptr) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(space_outliner->treestore, &iter); + while ((tselem = static_cast(BLI_mempool_iterstep(&iter)))) { + /* Do not try to restore non-ID pointers (drivers/sequence/etc.). */ + if (TSE_IS_REAL_ID(tselem)) { + const int cb_flag = (tselem->id != nullptr && allow_pointer_access && + (tselem->id->flag & LIB_EMBEDDED_DATA) != 0) ? + IDWALK_CB_EMBEDDED_NOT_OWNING : + IDWALK_CB_NOP; + BKE_LIB_FOREACHID_PROCESS_ID(data, tselem->id, cb_flag); + } + else if (!is_readonly) { + tselem->id = nullptr; + } + } + if (!is_readonly) { + /* rebuild hash table, because it depends on ids too */ + space_outliner->storeflag |= SO_TREESTORE_REBUILD; + } + } +} + static void outliner_deactivate(ScrArea *area) { /* Remove hover highlights */ @@ -583,6 +616,7 @@ void ED_spacetype_outliner() st->keymap = outliner_keymap; st->dropboxes = outliner_dropboxes; st->id_remap = outliner_id_remap; + st->foreach_id = outliner_foreach_id; st->deactivate = outliner_deactivate; st->context = outliner_context; st->blend_read_data = outliner_space_blend_read_data; diff --git a/source/blender/editors/space_script/space_script.cc b/source/blender/editors/space_script/space_script.cc index a0257b69f97..8aa1cf53424 100644 --- a/source/blender/editors/space_script/space_script.cc +++ b/source/blender/editors/space_script/space_script.cc @@ -15,6 +15,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_lib_query.h" #include "BKE_screen.h" #include "ED_screen.hh" @@ -147,6 +148,12 @@ static void script_main_region_listener(const wmRegionListenerParams * /*params* #endif } +static void script_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceScript *scpt = reinterpret_cast(space_link); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scpt->script, IDWALK_CB_NOP); +} + static void script_space_blend_read_lib(BlendLibReader *reader, ID *parent_id, SpaceLink *sl) { SpaceScript *scpt = (SpaceScript *)sl; @@ -180,6 +187,7 @@ void ED_spacetype_script() st->duplicate = script_duplicate; st->operatortypes = script_operatortypes; st->keymap = script_keymap; + st->foreach_id = script_foreach_id; st->blend_read_lib = script_space_blend_read_lib; st->blend_write = script_space_blend_write; diff --git a/source/blender/editors/space_sequencer/space_sequencer.cc b/source/blender/editors/space_sequencer/space_sequencer.cc index fc9c32faf92..9c5cd53395e 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.cc +++ b/source/blender/editors/space_sequencer/space_sequencer.cc @@ -10,6 +10,7 @@ #include #include +#include "DNA_gpencil_legacy_types.h" #include "DNA_mask_types.h" #include "DNA_scene_types.h" @@ -20,6 +21,7 @@ #include "BLI_math_base.h" #include "BKE_global.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" #include "BKE_sequencer_offscreen.h" @@ -925,6 +927,12 @@ static void sequencer_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRem BKE_id_remapper_apply(mappings, (ID **)&sseq->gpd, ID_REMAP_APPLY_DEFAULT); } +static void sequencer_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceSeq *sseq = reinterpret_cast(space_link); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sseq->gpd, IDWALK_CB_USER); +} + /* ************************************* */ static bool sequencer_channel_region_poll(const RegionPollParams *params) @@ -1012,6 +1020,7 @@ void ED_spacetype_sequencer() st->refresh = sequencer_refresh; st->listener = sequencer_listener; st->id_remap = sequencer_id_remap; + st->foreach_id = sequencer_foreach_id; st->blend_read_data = sequencer_space_blend_read_data; st->blend_read_lib = sequencer_space_blend_read_lib; st->blend_write = sequencer_space_blend_write; diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 4563e0960a5..2fcb816fab5 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -163,6 +163,12 @@ static void spreadsheet_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDR BKE_viewer_path_id_remap(&sspreadsheet->viewer_path, mappings); } +static void spreadsheet_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceSpreadsheet *sspreadsheet = reinterpret_cast(space_link); + BKE_viewer_path_foreach_id(data, &sspreadsheet->viewer_path); +} + static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region) { region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM | V2D_SCROLL_VERTICAL_HIDE | @@ -721,6 +727,7 @@ void ED_spacetype_spreadsheet() st->operatortypes = spreadsheet_operatortypes; st->keymap = spreadsheet_keymap; st->id_remap = spreadsheet_id_remap; + st->foreach_id = spreadsheet_foreach_id; st->blend_read_data = spreadsheet_blend_read_data; st->blend_read_lib = spreadsheet_blend_read_lib; st->blend_write = spreadsheet_blend_write; diff --git a/source/blender/editors/space_text/space_text.cc b/source/blender/editors/space_text/space_text.cc index fae3324dce2..b41e6476396 100644 --- a/source/blender/editors/space_text/space_text.cc +++ b/source/blender/editors/space_text/space_text.cc @@ -17,6 +17,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" @@ -396,6 +397,12 @@ static void text_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper BKE_id_remapper_apply(mappings, (ID **)&stext->text, ID_REMAP_APPLY_ENSURE_REAL); } +static void text_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + SpaceText *st = reinterpret_cast(space_link); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, st->text, IDWALK_CB_USER_ONE); +} + static void text_space_blend_read_data(BlendDataReader * /*reader*/, SpaceLink *sl) { SpaceText *st = (SpaceText *)sl; @@ -433,6 +440,7 @@ void ED_spacetype_text() st->context = text_context; st->dropboxes = text_dropboxes; st->id_remap = text_id_remap; + st->foreach_id = text_foreach_id; st->blend_read_data = text_space_blend_read_data; st->blend_read_lib = text_space_blend_read_lib; st->blend_write = text_space_blend_write; diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index a86b4b5bf19..16ba426faf7 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -42,6 +42,7 @@ #include "BKE_lattice.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_mball.h" @@ -2092,6 +2093,18 @@ static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const IDRemapper *m BKE_viewer_path_id_remap(&view3d->viewer_path, mappings); } +static void view3d_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) +{ + View3D *v3d = reinterpret_cast(space_link); + + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->ob_center, IDWALK_CB_NOP); + if (v3d->localvd) { + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->localvd->camera, IDWALK_CB_NOP); + } + BKE_viewer_path_foreach_id(data, &v3d->viewer_path); +} + static void view3d_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl) { View3D *v3d = (View3D *)sl; @@ -2166,6 +2179,7 @@ void ED_spacetype_view3d() st->gizmos = view3d_widgets; st->context = view3d_context; st->id_remap = view3d_id_remap; + st->foreach_id = view3d_foreach_id; st->blend_read_data = view3d_space_blend_read_data; st->blend_read_lib = view3d_space_blend_read_lib; st->blend_write = view3d_space_blend_write;