diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index 868063fb23d..6879d7b1f47 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -21,9 +21,12 @@ #include "BKE_callbacks.hh" -struct IDRemapper; struct Main; +namespace blender::bke::id { +class IDRemapper; +} + namespace blender::asset_system { class AssetIdentifier; @@ -140,7 +143,7 @@ class AssetLibrary { * mapped to null (typically when an ID gets removed), the asset is removed, because we don't * support such empty/null assets. */ - void remap_ids_and_remove_invalid(const IDRemapper &mappings); + void remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings); /** * Update `catalog_simple_name` by looking up the asset's catalog by its ID. @@ -264,7 +267,7 @@ bool AS_asset_library_has_any_unsaved_catalogs(void); * An asset library can include local IDs (IDs in the current file). Their pointers need to be * remapped on change (or assets removed as IDs gets removed). */ -void AS_asset_library_remap_ids(const IDRemapper *mappings); +void AS_asset_library_remap_ids(const blender::bke::id::IDRemapper &mappings); /** * Attempt to resolve a full path to an asset based on the currently available (not necessary diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index f48c72562f7..6003d5bab9b 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -13,6 +13,7 @@ #include "AS_asset_library.hh" #include "AS_asset_representation.hh" +#include "BKE_lib_remap.hh" #include "BKE_main.hh" #include "BKE_preferences.h" @@ -117,12 +118,11 @@ void AS_asset_library_refresh_catalog_simplename(AssetLibrary *asset_library, asset_library->refresh_catalog_simplename(asset_data); } -void AS_asset_library_remap_ids(const IDRemapper *mappings) +void AS_asset_library_remap_ids(const bke::id::IDRemapper &mappings) { AssetLibraryService *service = AssetLibraryService::get(); service->foreach_loaded_asset_library( - [mappings](AssetLibrary &library) { library.remap_ids_and_remove_invalid(*mappings); }, - true); + [mappings](AssetLibrary &library) { library.remap_ids_and_remove_invalid(mappings); }, true); } void AS_asset_full_path_explode_from_weak_ref(const AssetWeakReference *asset_reference, @@ -239,7 +239,7 @@ bool AssetLibrary::remove_asset(AssetRepresentation &asset) return asset_storage_->remove_asset(asset); } -void AssetLibrary::remap_ids_and_remove_invalid(const IDRemapper &mappings) +void AssetLibrary::remap_ids_and_remove_invalid(const bke::id::IDRemapper &mappings) { asset_storage_->remap_ids_and_remove_invalid(mappings); } diff --git a/source/blender/asset_system/intern/asset_storage.cc b/source/blender/asset_system/intern/asset_storage.cc index ecf33f72c95..02db8550e4c 100644 --- a/source/blender/asset_system/intern/asset_storage.cc +++ b/source/blender/asset_system/intern/asset_storage.cc @@ -43,7 +43,7 @@ bool AssetStorage::remove_asset(AssetRepresentation &asset) return external_assets_.remove_as(&asset); } -void AssetStorage::remap_ids_and_remove_invalid(const IDRemapper &mappings) +void AssetStorage::remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings) { Set removed_assets{}; @@ -51,8 +51,8 @@ void AssetStorage::remap_ids_and_remove_invalid(const IDRemapper &mappings) AssetRepresentation &asset = *asset_ptr; BLI_assert(asset.is_local_id()); - const IDRemapperApplyResult result = BKE_id_remapper_apply( - &mappings, &asset.local_asset_id_, ID_REMAP_APPLY_DEFAULT); + const IDRemapperApplyResult result = mappings.apply(&asset.local_asset_id_, + ID_REMAP_APPLY_DEFAULT); /* Entirely remove assets whose ID is unset. We don't want assets with a null ID pointer. */ if (result == ID_REMAP_RESULT_SOURCE_UNASSIGNED) { diff --git a/source/blender/asset_system/intern/asset_storage.hh b/source/blender/asset_system/intern/asset_storage.hh index 91de06703fe..21553e762bb 100644 --- a/source/blender/asset_system/intern/asset_storage.hh +++ b/source/blender/asset_system/intern/asset_storage.hh @@ -17,7 +17,10 @@ struct AssetMetaData; struct ID; -struct IDRemapper; + +namespace blender::bke::id { +class IDRemapper; +} namespace blender::asset_system { @@ -49,7 +52,7 @@ class AssetStorage { bool remove_asset(AssetRepresentation &asset); /** See #AssetLibrary::remap_ids_and_remove_nulled(). */ - void remap_ids_and_remove_invalid(const IDRemapper &mappings); + void remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings); }; } // namespace blender::asset_system diff --git a/source/blender/blenkernel/BKE_lib_remap.hh b/source/blender/blenkernel/BKE_lib_remap.hh index 968bdb91af1..d95647a46f6 100644 --- a/source/blender/blenkernel/BKE_lib_remap.hh +++ b/source/blender/blenkernel/BKE_lib_remap.hh @@ -21,13 +21,17 @@ */ #include "BLI_compiler_attrs.h" +#include "BLI_map.hh" #include "BLI_span.hh" #include "BLI_utildefines.h" struct ID; -struct IDRemapper; struct Main; +namespace blender::bke::id { +class IDRemapper; +} + /* BKE_libblock_free, delete are declared in BKE_lib_id.hh for convenience. */ /* Also IDRemap->flag. */ @@ -124,9 +128,13 @@ enum eIDRemapType { * * \note Is preferred over BKE_libblock_remap_locked due to performance. */ -void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper *mappings, const int remap_flags); +void BKE_libblock_remap_multiple_locked(Main *bmain, + blender::bke::id::IDRemapper &mappings, + const int remap_flags); -void BKE_libblock_remap_multiple(Main *bmain, IDRemapper *mappings, const int remap_flags); +void BKE_libblock_remap_multiple(Main *bmain, + blender::bke::id::IDRemapper &mappings, + const int remap_flags); /** * Bare raw remapping of IDs, with no other processing than actually updating the ID pointers. @@ -137,7 +145,9 @@ void BKE_libblock_remap_multiple(Main *bmain, IDRemapper *mappings, const int re * case e.g. in read-file process. * * WARNING: This call will likely leave the given BMain in invalid state in many aspects. */ -void BKE_libblock_remap_multiple_raw(Main *bmain, IDRemapper *mappings, const int remap_flags); +void BKE_libblock_remap_multiple_raw(Main *bmain, + blender::bke::id::IDRemapper &mappings, + const int remap_flags); /** * Replace all references in given Main to \a old_id by \a new_id * (if \a new_id is NULL, it unlinks \a old_id). @@ -178,7 +188,7 @@ void BKE_libblock_relink_ex(Main *bmain, void *idv, void *old_idv, void *new_idv void BKE_libblock_relink_multiple(Main *bmain, const blender::Span ids, eIDRemapType remap_type, - IDRemapper *id_remapper, + blender::bke::id::IDRemapper &id_remapper, int remap_flags); /** @@ -193,7 +203,8 @@ void BKE_libblock_relink_multiple(Main *bmain, void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL(); using BKE_library_free_notifier_reference_cb = void (*)(const void *); -using BKE_library_remap_editor_id_reference_cb = void (*)(const IDRemapper *mappings); +using BKE_library_remap_editor_id_reference_cb = + void (*)(const blender::bke::id::IDRemapper &mappings); void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func); void BKE_library_callback_remap_editor_id_reference_set( @@ -220,7 +231,7 @@ enum IDRemapperApplyOptions { * * NOTE: Currently unused by main remapping code, since user-count is handled by * `foreach_libblock_remap_callback_apply` there, depending on whether the remapped pointer does - * use it or not. Need for rare cases in UI handling though (see e.g. `image_id_remap` in + * use it or not. Needed for rare cases in UI handling though (see e.g. `image_id_remap` in * `space_image.cc`). */ ID_REMAP_APPLY_UPDATE_REFCOUNT = (1 << 0), @@ -233,9 +244,9 @@ enum IDRemapperApplyOptions { ID_REMAP_APPLY_ENSURE_REAL = (1 << 1), /** - * Unassign in stead of remap when the new ID data-block would become id_self. + * Unassign instead of remap when the new ID pointer would point to itself. * - * To use this option 'BKE_id_remapper_apply_ex' must be used with a not-null id_self parameter. + * To use this option #IDRemapper::apply must be used with a non-null id_self parameter. */ ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF = (1 << 2), @@ -244,58 +255,66 @@ enum IDRemapperApplyOptions { ENUM_OPERATORS(IDRemapperApplyOptions, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) using IDRemapperIterFunction = void (*)(ID *old_id, ID *new_id, void *user_data); +using IDTypeFilter = uint64_t; -/** - * Create a new ID Remapper. - * - * An ID remapper stores multiple remapping rules. - */ -IDRemapper *BKE_id_remapper_create(); +namespace blender::bke::id { -void BKE_id_remapper_clear(IDRemapper *id_remapper); -bool BKE_id_remapper_is_empty(const IDRemapper *id_remapper); -/** Free the given ID Remapper. */ -void BKE_id_remapper_free(IDRemapper *id_remapper); -/** Add a new remapping. Does not replace an existing mapping for `old_id`, if any. */ -void BKE_id_remapper_add(IDRemapper *id_remapper, ID *old_id, ID *new_id); -/** Add a new remapping, replacing a potential already existing mapping of `old_id`. */ -void BKE_id_remapper_add_overwrite(IDRemapper *id_remapper, ID *old_id, ID *new_id); +class IDRemapper { + blender::Map mappings_; + IDTypeFilter source_types_ = 0; -/** - * Apply a remapping. - * - * Update the id pointer stored in the given r_id_ptr if a remapping rule exists. - */ -IDRemapperApplyResult BKE_id_remapper_apply(const IDRemapper *id_remapper, - ID **r_id_ptr, - IDRemapperApplyOptions options); -/** - * Apply a remapping. - * - * Use this function when `ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF`. In this case - * the #id_self parameter is required. Otherwise the #BKE_id_remapper_apply can be used. - * - * \param id_self: required for ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF. - * When remapping to id_self it will then be remapped to NULL. - */ -IDRemapperApplyResult BKE_id_remapper_apply_ex(const IDRemapper *id_remapper, - ID **r_id_ptr, - IDRemapperApplyOptions options, - ID *id_self); -bool BKE_id_remapper_has_mapping_for(const IDRemapper *id_remapper, uint64_t type_filter); + public: + void clear(void) + { + mappings_.clear(); + source_types_ = 0; + } -/** - * Determine the mapping result, without applying the mapping. - */ -IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const IDRemapper *id_remapper, - ID *id, - IDRemapperApplyOptions options, - const ID *id_self); -void BKE_id_remapper_iter(const IDRemapper *id_remapper, - IDRemapperIterFunction func, - void *user_data); + bool is_empty(void) const + { + return mappings_.is_empty(); + } -/** Returns a readable string for the given result. Can be used for debugging purposes. */ -const char *BKE_id_remapper_result_string(const IDRemapperApplyResult result); -/** Prints out the rules inside the given id_remapper. Can be used for debugging purposes. */ -void BKE_id_remapper_print(const IDRemapper *id_remapper); + bool contains_mappings_for_any(IDTypeFilter filter) const + { + return (source_types_ & filter) != 0; + } + + /** Add a new remapping. Does not replace an existing mapping for `old_id`, if any. */ + void add(ID *old_id, ID *new_id); + /** Add a new remapping, replacing a potential already existing mapping of `old_id`. */ + void add_overwrite(ID *old_id, ID *new_id); + + /** Determine the mapping result, without applying the mapping. */ + IDRemapperApplyResult get_mapping_result(ID *id, + IDRemapperApplyOptions options, + const ID *id_self) const; + + /** + * Apply a remapping. + * + * Update the id pointer stored in the given r_id_ptr if a remapping rule exists. + * + * \param id_self: Only for ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF. + * When remapping to `id_self` it will then be remapped to `nullptr` instead. + */ + IDRemapperApplyResult apply(ID **r_id_ptr, + IDRemapperApplyOptions options, + ID *id_self = nullptr) const; + + /** Iterate over all remapping pairs in the remapper, and call the callback function on them. */ + void iter(IDRemapperIterFunction func, void *user_data) const + { + for (auto item : mappings_.items()) { + func(item.key, item.value, user_data); + } + } + + /** Return a readable string for the given result. Can be used for debugging purposes. */ + static const blender::StringRefNull result_to_string(const IDRemapperApplyResult result); + + /** Print out the rules inside the given id_remapper. Can be used for debugging purposes. */ + void print(void) const; +}; + +} // namespace blender::bke::id diff --git a/source/blender/blenkernel/BKE_screen.hh b/source/blender/blenkernel/BKE_screen.hh index 2b4ef5a5e01..8053eaa36ab 100644 --- a/source/blender/blenkernel/BKE_screen.hh +++ b/source/blender/blenkernel/BKE_screen.hh @@ -17,6 +17,10 @@ #include "BKE_context.hh" +namespace blender::bke::id { +class IDRemapper; +} + namespace blender::asset_system { class AssetRepresentation; } @@ -28,7 +32,6 @@ struct BlendLibReader; struct BlendWriter; struct Header; struct ID; -struct IDRemapper; struct LayoutPanelState; struct LibraryForeachIDData; struct ListBase; @@ -109,7 +112,7 @@ struct SpaceType { bContextDataCallback context; /* Used when we want to replace an ID by another (or NULL). */ - void (*id_remap)(ScrArea *area, SpaceLink *sl, const IDRemapper *mappings); + void (*id_remap)(ScrArea *area, SpaceLink *sl, const blender::bke::id::IDRemapper &mappings); /** * foreach_id callback to process all ID pointers of the editor. Used indirectly by lib_query's diff --git a/source/blender/blenkernel/BKE_viewer_path.hh b/source/blender/blenkernel/BKE_viewer_path.hh index da485e1cdb9..c4dd2fee0ad 100644 --- a/source/blender/blenkernel/BKE_viewer_path.hh +++ b/source/blender/blenkernel/BKE_viewer_path.hh @@ -29,7 +29,10 @@ struct BlendDataReader; struct BlendLibReader; struct LibraryForeachIDData; struct Library; -struct IDRemapper; + +namespace blender::bke::id { +class IDRemapper; +} enum ViewerPathEqualFlag { VIEWER_PATH_EQUAL_FLAG_IGNORE_REPEAT_ITERATION = (1 << 0), @@ -44,7 +47,8 @@ bool BKE_viewer_path_equal(const ViewerPath *a, void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_path); void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer_path); void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_path); -void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mappings); +void BKE_viewer_path_id_remap(ViewerPath *viewer_path, + const blender::bke::id::IDRemapper &mappings); ViewerPathElem *BKE_viewer_path_elem_new(ViewerPathElemType type); IDViewerPathElem *BKE_viewer_path_elem_new_id(); diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index fc88d6042bf..dc4756598a7 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -64,6 +64,8 @@ # include "BPY_extern.h" #endif +using namespace blender::bke; + /* -------------------------------------------------------------------- */ /** \name Blend/Library Paths * \{ */ @@ -228,7 +230,7 @@ struct ReuseOldBMainData { /** Storage for all remapping rules (old_id -> new_id) required by the preservation of old IDs * into the new Main. */ - IDRemapper *remapper; + id::IDRemapper *remapper; bool is_libraries_remapped; /** Used to find matching IDs by name/lib in new main, to remap ID usages of data ported over @@ -246,25 +248,25 @@ struct ReuseOldBMainData { * double of a linked data as a local one, without any known relationships between them. In * practice, this latter case is not expected to commonly happen. */ -static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data) +static id::IDRemapper &reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data) { if (reuse_data->is_libraries_remapped) { - return reuse_data->remapper; + return *reuse_data->remapper; } if (reuse_data->remapper == nullptr) { - reuse_data->remapper = BKE_id_remapper_create(); + reuse_data->remapper = MEM_new(__func__); } Main *new_bmain = reuse_data->new_bmain; Main *old_bmain = reuse_data->old_bmain; - IDRemapper *remapper = reuse_data->remapper; + id::IDRemapper &remapper = *reuse_data->remapper; LISTBASE_FOREACH (Library *, old_lib_iter, &old_bmain->libraries) { /* In case newly opened `new_bmain` is a library of the `old_bmain`, remap it to null, since a * file should never ever have linked data from itself. */ if (STREQ(old_lib_iter->filepath_abs, new_bmain->filepath)) { - BKE_id_remapper_add(remapper, &old_lib_iter->id, nullptr); + remapper.add(&old_lib_iter->id, nullptr); continue; } @@ -277,19 +279,18 @@ static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_dat continue; } - BKE_id_remapper_add(remapper, &old_lib_iter->id, &new_lib_iter->id); + remapper.add(&old_lib_iter->id, &new_lib_iter->id); break; } } reuse_data->is_libraries_remapped = true; - return reuse_data->remapper; + return *reuse_data->remapper; } -static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *id) +static bool reuse_bmain_data_remapper_is_id_remapped(id::IDRemapper &remapper, ID *id) { - IDRemapperApplyResult result = BKE_id_remapper_get_mapping_result( - remapper, id, ID_REMAP_APPLY_DEFAULT, nullptr); + IDRemapperApplyResult result = remapper.get_mapping_result(id, ID_REMAP_APPLY_DEFAULT, nullptr); if (ELEM(result, ID_REMAP_RESULT_SOURCE_REMAPPED, ID_REMAP_RESULT_SOURCE_UNASSIGNED)) { /* ID is already remapped to its matching ID in the new main, or explicitly remapped to null, * nothing else to do here. */ @@ -319,7 +320,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con ListBase *new_lb = which_libbase(new_bmain, id_code); ListBase *old_lb = which_libbase(old_bmain, id_code); - IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data); + id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data); /* NOTE: Full swapping is only supported for ID types that are assumed to be only local * data-blocks (like UI-like ones). Otherwise, the swapping could fail in many funny ways. */ @@ -346,14 +347,14 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con const int strcmp_result = strcmp(discarded_id_iter->name + 2, reused_id_iter->name + 2); if (strcmp_result == 0) { /* Matching IDs, we can remap the discarded 'new' one to the re-used 'old' one. */ - BKE_id_remapper_add(remapper, discarded_id_iter, reused_id_iter); + remapper.add(discarded_id_iter, reused_id_iter); discarded_id_iter = static_cast(discarded_id_iter->next); reused_id_iter = static_cast(reused_id_iter->next); } else if (strcmp_result < 0) { /* No matching reused 'old' ID for this discarded 'new' one. */ - BKE_id_remapper_add(remapper, discarded_id_iter, nullptr); + remapper.add(discarded_id_iter, nullptr); discarded_id_iter = static_cast(discarded_id_iter->next); } @@ -365,7 +366,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con for (; discarded_id_iter != nullptr; discarded_id_iter = static_cast(discarded_id_iter->next)) { - BKE_id_remapper_add(remapper, discarded_id_iter, nullptr); + remapper.add(discarded_id_iter, nullptr); } FOREACH_MAIN_LISTBASE_ID_BEGIN (new_lb, reused_id_iter) { @@ -374,7 +375,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con /* Ensure that the reused ID is remapped to itself, since it is known to be in the `new_bmain`. */ - BKE_id_remapper_add_overwrite(remapper, reused_id_iter, reused_id_iter); + remapper.add_overwrite(reused_id_iter, reused_id_iter); } FOREACH_MAIN_LISTBASE_ID_END; } @@ -428,8 +429,8 @@ static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool * new WM, and is responsible to free it properly. */ reuse_data->wm_setup_data->old_wm = old_wm; - IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data); - BKE_id_remapper_add(remapper, &old_wm->id, &new_wm->id); + id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data); + remapper.add(&old_wm->id, &new_wm->id); } /* Current (old) WM, but no (new) one in file (should only happen when reading pre 2.5 files, no * WM back then), or not loading UI: Keep current WM. */ @@ -452,7 +453,7 @@ static int swap_old_bmain_data_for_blendfile_dependencies_process_cb( ReuseOldBMainData *reuse_data = static_cast(cb_data->user_data); /* First check if it has already been remapped. */ - IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data); + id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data); if (reuse_bmain_data_remapper_is_id_remapped(remapper, id)) { return IDWALK_RET_NOP; } @@ -461,7 +462,7 @@ static int swap_old_bmain_data_for_blendfile_dependencies_process_cb( BLI_assert(id_map != nullptr); ID *id_new = BKE_main_idmap_lookup_id(id_map, id); - BKE_id_remapper_add(remapper, id, id_new); + remapper.add(id, id_new); return IDWALK_RET_NOP; } @@ -784,7 +785,7 @@ static void setup_app_data(bContext *C, /* Handle all pending remapping from swapping old and new IDs around. */ BKE_libblock_remap_multiple_raw(bfd->main, - reuse_data.remapper, + *reuse_data.remapper, (ID_REMAP_FORCE_UI_POINTERS | ID_REMAP_SKIP_USER_REFCOUNT | ID_REMAP_SKIP_UPDATE_TAGGING | ID_REMAP_SKIP_USER_CLEAR)); @@ -793,7 +794,7 @@ static void setup_app_data(bContext *C, * library of the previous opened blendfile'. */ reuse_bmain_data_invalid_local_usages_fix(&reuse_data); - BKE_id_remapper_free(reuse_data.remapper); + MEM_delete(reuse_data.remapper); reuse_data.remapper = nullptr; wm_data_consistency_ensure(CTX_wm_manager(C), curscene, cur_view_layer); diff --git a/source/blender/blenkernel/intern/lib_id.cc b/source/blender/blenkernel/intern/lib_id.cc index 4c9474e0b1b..171c5ed70e0 100644 --- a/source/blender/blenkernel/intern/lib_id.cc +++ b/source/blender/blenkernel/intern/lib_id.cc @@ -77,6 +77,8 @@ # include "BLI_time_utildefines.h" #endif +using namespace blender::bke::id; + static CLG_LogRef LOG = {"bke.lib_id"}; IDTypeInfo IDType_ID_LINK_PLACEHOLDER = { @@ -803,10 +805,10 @@ static void id_swap(Main *bmain, IDRemapper *remapper_id_b = input_remapper_id_b; if (do_self_remap) { if (remapper_id_a == nullptr) { - remapper_id_a = BKE_id_remapper_create(); + remapper_id_a = MEM_new(__func__); } if (remapper_id_b == nullptr) { - remapper_id_b = BKE_id_remapper_create(); + remapper_id_b = MEM_new(__func__); } } @@ -852,25 +854,25 @@ static void id_swap(Main *bmain, } if (remapper_id_a != nullptr) { - BKE_id_remapper_add(remapper_id_a, id_b, id_a); + remapper_id_a->add(id_b, id_a); } if (remapper_id_b != nullptr) { - BKE_id_remapper_add(remapper_id_b, id_a, id_b); + remapper_id_b->add(id_a, id_b); } /* Finalize remapping of internal references to self broken by swapping, if requested. */ if (do_self_remap) { BKE_libblock_relink_multiple( - bmain, {id_a}, ID_REMAP_TYPE_REMAP, remapper_id_a, self_remap_flags); + bmain, {id_a}, ID_REMAP_TYPE_REMAP, *remapper_id_a, self_remap_flags); BKE_libblock_relink_multiple( - bmain, {id_b}, ID_REMAP_TYPE_REMAP, remapper_id_b, self_remap_flags); + bmain, {id_b}, ID_REMAP_TYPE_REMAP, *remapper_id_b, self_remap_flags); } if (input_remapper_id_a == nullptr && remapper_id_a != nullptr) { - BKE_id_remapper_free(remapper_id_a); + MEM_delete(remapper_id_a); } if (input_remapper_id_b == nullptr && remapper_id_b != nullptr) { - BKE_id_remapper_free(remapper_id_b); + MEM_delete(remapper_id_b); } } @@ -908,10 +910,10 @@ static void id_embedded_swap(ID **embedded_id_a, /* Restore internal pointers to the swapped embedded IDs in their owners' data. This also * includes the potential self-references inside the embedded IDs themselves. */ if (remapper_id_a != nullptr) { - BKE_id_remapper_add(remapper_id_a, *embedded_id_b, *embedded_id_a); + remapper_id_a->add(*embedded_id_b, *embedded_id_a); } if (remapper_id_b != nullptr) { - BKE_id_remapper_add(remapper_id_b, *embedded_id_a, *embedded_id_b); + remapper_id_b->add(*embedded_id_a, *embedded_id_b); } } } diff --git a/source/blender/blenkernel/intern/lib_id_delete.cc b/source/blender/blenkernel/intern/lib_id_delete.cc index f9ff7f325df..428f8a1239a 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.cc +++ b/source/blender/blenkernel/intern/lib_id_delete.cc @@ -42,6 +42,8 @@ # include "BPY_extern.h" #endif +using namespace blender::bke::id; + static CLG_LogRef LOG = {"bke.lib_id_delete"}; void BKE_libblock_free_data(ID *id, const bool do_id_user) @@ -146,10 +148,9 @@ static int id_free(Main *bmain, void *idv, int flag, const bool use_flag_from_id } if (remap_editor_id_reference_cb) { - IDRemapper *remapper = BKE_id_remapper_create(); - BKE_id_remapper_add(remapper, id, nullptr); + IDRemapper remapper; + remapper.add(id, nullptr); remap_editor_id_reference_cb(remapper); - BKE_id_remapper_free(remapper); } } @@ -241,7 +242,7 @@ static size_t id_delete(Main *bmain, BKE_main_lock(bmain); if (do_tagged_deletion) { - IDRemapper *id_remapper = BKE_id_remapper_create(); + IDRemapper id_remapper; BKE_layer_collection_resync_forbid(); /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. @@ -269,7 +270,7 @@ static size_t id_delete(Main *bmain, BLI_remlink(lb, id); BKE_main_namemap_remove_name(bmain, id, id->name + 2); BLI_addtail(&tagged_deleted_ids, id); - BKE_id_remapper_add(id_remapper, id, nullptr); + id_remapper.add(id, nullptr); /* Do not tag as no_main now, we want to unlink it first (lower-level ID management * code has some specific handling of 'no main' IDs that would be a problem in that * case). */ @@ -283,7 +284,7 @@ static size_t id_delete(Main *bmain, BLI_remlink(&bmain->shapekeys, &shape_key->id); BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2); BLI_addtail(&tagged_deleted_ids, &shape_key->id); - BKE_id_remapper_add(id_remapper, &shape_key->id, nullptr); + id_remapper.add(&shape_key->id, nullptr); shape_key->id.tag |= tag; } @@ -299,7 +300,7 @@ static size_t id_delete(Main *bmain, * Also, this will also flag users of deleted data that cannot be unlinked * (object using deleted obdata, etc.), so that they also get deleted. */ BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags); - BKE_id_remapper_clear(id_remapper); + id_remapper.clear(); } /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */ @@ -316,7 +317,6 @@ static size_t id_delete(Main *bmain, ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR); cleanup_ids.clear(); - BKE_id_remapper_free(id_remapper); BKE_layer_collection_resync_allow(); BKE_main_collection_sync_remap(bmain); @@ -340,22 +340,22 @@ static size_t id_delete(Main *bmain, * Note that we go forward here, since we want to check dependencies before users * (e.g. meshes before objects). * Avoids to have to loop twice. */ - IDRemapper *remapper = BKE_id_remapper_create(); + IDRemapper remapper; for (i = 0; i < base_count; i++) { ListBase *lb = lbarray[i]; ID *id, *id_next; - BKE_id_remapper_clear(remapper); + remapper.clear(); for (id = static_cast(lb->first); id; id = id_next) { id_next = static_cast(id->next); /* NOTE: in case we delete a library, we also delete all its datablocks! */ if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) { id->tag |= tag; - BKE_id_remapper_add(remapper, id, nullptr); + remapper.add(id, nullptr); } } - if (BKE_id_remapper_is_empty(remapper)) { + if (remapper.is_empty()) { continue; } @@ -367,7 +367,6 @@ static size_t id_delete(Main *bmain, * (object using deleted obdata, etc.), so that they also get deleted. */ BKE_libblock_remap_multiple_locked(bmain, remapper, remapping_flags); } - BKE_id_remapper_free(remapper); } BKE_main_unlock(bmain); diff --git a/source/blender/blenkernel/intern/lib_id_remapper.cc b/source/blender/blenkernel/intern/lib_id_remapper.cc index 0a8135fd7c3..7027c4d175d 100644 --- a/source/blender/blenkernel/intern/lib_id_remapper.cc +++ b/source/blender/blenkernel/intern/lib_id_remapper.cc @@ -10,215 +10,87 @@ #include "MEM_guardedalloc.h" -#include "BLI_map.hh" +namespace blender::bke::id { -using IDTypeFilter = uint64_t; +void IDRemapper::add(ID *old_id, ID *new_id) +{ + BLI_assert(old_id != nullptr); + BLI_assert(new_id == nullptr || (GS(old_id->name) == GS(new_id->name))); + BLI_assert(BKE_idtype_idcode_to_idfilter(GS(old_id->name)) != 0); -namespace blender::bke::id::remapper { -struct IDRemapper { - private: - Map mappings; - IDTypeFilter source_types = 0; + mappings_.add(old_id, new_id); + source_types_ |= BKE_idtype_idcode_to_idfilter(GS(old_id->name)); +} - public: - void clear() - { - mappings.clear(); - source_types = 0; +void IDRemapper::add_overwrite(ID *old_id, ID *new_id) +{ + BLI_assert(old_id != nullptr); + BLI_assert(new_id == nullptr || (GS(old_id->name) == GS(new_id->name))); + BLI_assert(BKE_idtype_idcode_to_idfilter(GS(old_id->name)) != 0); + + mappings_.add_overwrite(old_id, new_id); + source_types_ |= BKE_idtype_idcode_to_idfilter(GS(old_id->name)); +} + +IDRemapperApplyResult IDRemapper::get_mapping_result(ID *id, + IDRemapperApplyOptions options, + const ID *id_self) const +{ + if (!mappings_.contains(id)) { + return ID_REMAP_RESULT_SOURCE_UNAVAILABLE; + } + const ID *new_id = mappings_.lookup(id); + if ((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) != 0 && id_self == new_id) { + new_id = nullptr; + } + if (new_id == nullptr) { + return ID_REMAP_RESULT_SOURCE_UNASSIGNED; } - bool is_empty() const - { - return mappings.is_empty(); + return ID_REMAP_RESULT_SOURCE_REMAPPED; +} + +IDRemapperApplyResult IDRemapper::apply(ID **r_id_ptr, + IDRemapperApplyOptions options, + ID *id_self) const +{ + BLI_assert(r_id_ptr != nullptr); + BLI_assert_msg( + ((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) == 0 || id_self != nullptr), + "ID_REMAP_APPLY_WHEN_REMAPPING_TO_SELF requires a non-null `id_self` parameter."); + + if (*r_id_ptr == nullptr) { + return ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE; } - void add(ID *old_id, ID *new_id) - { - BLI_assert(old_id != nullptr); - BLI_assert(new_id == nullptr || (GS(old_id->name) == GS(new_id->name))); - mappings.add(old_id, new_id); - BLI_assert(BKE_idtype_idcode_to_idfilter(GS(old_id->name)) != 0); - source_types |= BKE_idtype_idcode_to_idfilter(GS(old_id->name)); + if (!mappings_.contains(*r_id_ptr)) { + return ID_REMAP_RESULT_SOURCE_UNAVAILABLE; } - void add_overwrite(ID *old_id, ID *new_id) - { - BLI_assert(old_id != nullptr); - BLI_assert(new_id == nullptr || (GS(old_id->name) == GS(new_id->name))); - mappings.add_overwrite(old_id, new_id); - BLI_assert(BKE_idtype_idcode_to_idfilter(GS(old_id->name)) != 0); - source_types |= BKE_idtype_idcode_to_idfilter(GS(old_id->name)); + if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) { + id_us_min(*r_id_ptr); } - bool contains_mappings_for_any(IDTypeFilter filter) const - { - return (source_types & filter) != 0; + *r_id_ptr = mappings_.lookup(*r_id_ptr); + if (options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF && *r_id_ptr == id_self) { + *r_id_ptr = nullptr; + } + if (*r_id_ptr == nullptr) { + return ID_REMAP_RESULT_SOURCE_UNASSIGNED; } - IDRemapperApplyResult get_mapping_result(ID *id, - IDRemapperApplyOptions options, - const ID *id_self) const - { - if (!mappings.contains(id)) { - return ID_REMAP_RESULT_SOURCE_UNAVAILABLE; - } - const ID *new_id = mappings.lookup(id); - if ((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) != 0 && id_self == new_id) { - new_id = nullptr; - } - if (new_id == nullptr) { - return ID_REMAP_RESULT_SOURCE_UNASSIGNED; - } - - return ID_REMAP_RESULT_SOURCE_REMAPPED; + if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) { + /* Do not handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */ + id_us_plus_no_lib(*r_id_ptr); } - IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options, ID *id_self) const - { - BLI_assert(r_id_ptr != nullptr); - if (*r_id_ptr == nullptr) { - return ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE; - } - - if (!mappings.contains(*r_id_ptr)) { - return ID_REMAP_RESULT_SOURCE_UNAVAILABLE; - } - - if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) { - id_us_min(*r_id_ptr); - } - - *r_id_ptr = mappings.lookup(*r_id_ptr); - if (options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF && *r_id_ptr == id_self) { - *r_id_ptr = nullptr; - } - if (*r_id_ptr == nullptr) { - return ID_REMAP_RESULT_SOURCE_UNASSIGNED; - } - - if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) { - /* Do not handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */ - id_us_plus_no_lib(*r_id_ptr); - } - - if (options & ID_REMAP_APPLY_ENSURE_REAL) { - id_us_ensure_real(*r_id_ptr); - } - return ID_REMAP_RESULT_SOURCE_REMAPPED; + if (options & ID_REMAP_APPLY_ENSURE_REAL) { + id_us_ensure_real(*r_id_ptr); } - - void iter(IDRemapperIterFunction func, void *user_data) const - { - for (auto item : mappings.items()) { - func(item.key, item.value, user_data); - } - } -}; - -} // namespace blender::bke::id::remapper - -/** \brief wrap CPP IDRemapper to a C handle. */ -static IDRemapper *wrap(blender::bke::id::remapper::IDRemapper *remapper) -{ - return static_cast(static_cast(remapper)); + return ID_REMAP_RESULT_SOURCE_REMAPPED; } -/** \brief wrap C handle to a CPP IDRemapper. */ -static blender::bke::id::remapper::IDRemapper *unwrap(IDRemapper *remapper) -{ - return static_cast(static_cast(remapper)); -} - -/** \brief wrap C handle to a CPP IDRemapper. */ -static const blender::bke::id::remapper::IDRemapper *unwrap(const IDRemapper *remapper) -{ - return static_cast( - static_cast(remapper)); -} - -IDRemapper *BKE_id_remapper_create() -{ - blender::bke::id::remapper::IDRemapper *remapper = - MEM_new(__func__); - return wrap(remapper); -} - -void BKE_id_remapper_free(IDRemapper *id_remapper) -{ - blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - MEM_delete(remapper); -} - -void BKE_id_remapper_clear(IDRemapper *id_remapper) -{ - blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - remapper->clear(); -} - -bool BKE_id_remapper_is_empty(const IDRemapper *id_remapper) -{ - const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - return remapper->is_empty(); -} - -void BKE_id_remapper_add(IDRemapper *id_remapper, ID *old_id, ID *new_id) -{ - blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - remapper->add(old_id, new_id); -} - -void BKE_id_remapper_add_overwrite(IDRemapper *id_remapper, ID *old_id, ID *new_id) -{ - blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - remapper->add_overwrite(old_id, new_id); -} - -bool BKE_id_remapper_has_mapping_for(const IDRemapper *id_remapper, uint64_t type_filter) -{ - const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - return remapper->contains_mappings_for_any(type_filter); -} - -IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const IDRemapper *id_remapper, - ID *id, - IDRemapperApplyOptions options, - const ID *id_self) -{ - const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - return remapper->get_mapping_result(id, options, id_self); -} - -IDRemapperApplyResult BKE_id_remapper_apply_ex(const IDRemapper *id_remapper, - ID **r_id_ptr, - const IDRemapperApplyOptions options, - ID *id_self) -{ - BLI_assert_msg((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) == 0 || - id_self != nullptr, - "ID_REMAP_APPLY_WHEN_REMAPPING_TO_SELF requires id_self parameter."); - const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - return remapper->apply(r_id_ptr, options, id_self); -} - -IDRemapperApplyResult BKE_id_remapper_apply(const IDRemapper *id_remapper, - ID **r_id_ptr, - const IDRemapperApplyOptions options) -{ - BLI_assert_msg((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) == 0, - "ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF requires id_self parameter. Use " - "`BKE_id_remapper_apply_ex`."); - return BKE_id_remapper_apply_ex(id_remapper, r_id_ptr, options, nullptr); -} - -void BKE_id_remapper_iter(const IDRemapper *id_remapper, - IDRemapperIterFunction func, - void *user_data) -{ - const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper); - remapper->iter(func, user_data); -} - -const char *BKE_id_remapper_result_string(const IDRemapperApplyResult result) +const blender::StringRefNull IDRemapper::result_to_string(const IDRemapperApplyResult result) { switch (result) { case ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE: @@ -229,23 +101,22 @@ const char *BKE_id_remapper_result_string(const IDRemapperApplyResult result) return "unassigned"; case ID_REMAP_RESULT_SOURCE_REMAPPED: return "remapped"; - default: - BLI_assert_unreachable(); } + BLI_assert_unreachable(); return ""; } -static void id_remapper_print_item_cb(ID *old_id, ID *new_id, void * /*user_data*/) +void IDRemapper::print(void) const { - if (old_id != nullptr && new_id != nullptr) { - printf("Remap %s(%p) to %s(%p)\n", old_id->name, old_id, new_id->name, new_id); - } - if (old_id != nullptr && new_id == nullptr) { - printf("Unassign %s(%p)\n", old_id->name, old_id); - } + auto print_cb = [](ID *old_id, ID *new_id, void * /*user_data*/) { + if (old_id != nullptr && new_id != nullptr) { + printf("Remap %s(%p) to %s(%p)\n", old_id->name, old_id, new_id->name, new_id); + } + if (old_id != nullptr && new_id == nullptr) { + printf("Unassign %s(%p)\n", old_id->name, old_id); + } + }; + this->iter(print_cb, nullptr); } -void BKE_id_remapper_print(const IDRemapper *id_remapper) -{ - BKE_id_remapper_iter(id_remapper, id_remapper_print_item_cb, nullptr); -} +} // namespace blender::bke::id diff --git a/source/blender/blenkernel/intern/lib_id_remapper_test.cc b/source/blender/blenkernel/intern/lib_id_remapper_test.cc index b4928fafd6b..6c7eefa129c 100644 --- a/source/blender/blenkernel/intern/lib_id_remapper_test.cc +++ b/source/blender/blenkernel/intern/lib_id_remapper_test.cc @@ -10,29 +10,27 @@ #include "DNA_ID.h" -namespace blender::bke::id::remapper::tests { +using namespace blender::bke::id; + +namespace blender::bke::id::tests { TEST(lib_id_remapper, unavailable) { ID id1; ID *idp = &id1; - IDRemapper *remapper = BKE_id_remapper_create(); - IDRemapperApplyResult result = BKE_id_remapper_apply(remapper, &idp, ID_REMAP_APPLY_DEFAULT); + IDRemapper remapper; + IDRemapperApplyResult result = remapper.apply(&idp, ID_REMAP_APPLY_DEFAULT); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNAVAILABLE); - - BKE_id_remapper_free(remapper); } TEST(lib_id_remapper, not_mappable) { ID *idp = nullptr; - IDRemapper *remapper = BKE_id_remapper_create(); - IDRemapperApplyResult result = BKE_id_remapper_apply(remapper, &idp, ID_REMAP_APPLY_DEFAULT); + IDRemapper remapper; + IDRemapperApplyResult result = remapper.apply(&idp, ID_REMAP_APPLY_DEFAULT); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE); - - BKE_id_remapper_free(remapper); } TEST(lib_id_remapper, mapped) @@ -43,13 +41,11 @@ TEST(lib_id_remapper, mapped) STRNCPY(id1.name, "OB1"); STRNCPY(id2.name, "OB2"); - IDRemapper *remapper = BKE_id_remapper_create(); - BKE_id_remapper_add(remapper, &id1, &id2); - IDRemapperApplyResult result = BKE_id_remapper_apply(remapper, &idp, ID_REMAP_APPLY_DEFAULT); + IDRemapper remapper; + remapper.add(&id1, &id2); + IDRemapperApplyResult result = remapper.apply(&idp, ID_REMAP_APPLY_DEFAULT); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_REMAPPED); EXPECT_EQ(idp, &id2); - - BKE_id_remapper_free(remapper); } TEST(lib_id_remapper, unassigned) @@ -58,13 +54,11 @@ TEST(lib_id_remapper, unassigned) ID *idp = &id1; STRNCPY(id1.name, "OB2"); - IDRemapper *remapper = BKE_id_remapper_create(); - BKE_id_remapper_add(remapper, &id1, nullptr); - IDRemapperApplyResult result = BKE_id_remapper_apply(remapper, &idp, ID_REMAP_APPLY_DEFAULT); + IDRemapper remapper; + remapper.add(&id1, nullptr); + IDRemapperApplyResult result = remapper.apply(&idp, ID_REMAP_APPLY_DEFAULT); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED); EXPECT_EQ(idp, nullptr); - - BKE_id_remapper_free(remapper); } TEST(lib_id_remapper, unassign_when_mapped_to_self) @@ -80,31 +74,28 @@ TEST(lib_id_remapper, unassign_when_mapped_to_self) /* Default mapping behavior. Should just remap to id2. */ idp = &id1; - IDRemapper *remapper = BKE_id_remapper_create(); - BKE_id_remapper_add(remapper, &id1, &id2); - IDRemapperApplyResult result = BKE_id_remapper_apply_ex( - remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); + IDRemapper remapper; + remapper.add(&id1, &id2); + IDRemapperApplyResult result = remapper.apply( + &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_REMAPPED); EXPECT_EQ(idp, &id2); /* Default mapping behavior. Should unassign. */ idp = &id1; - BKE_id_remapper_clear(remapper); - BKE_id_remapper_add(remapper, &id1, nullptr); - result = BKE_id_remapper_apply_ex( - remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); + remapper.clear(); + remapper.add(&id1, nullptr); + result = remapper.apply(&idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED); EXPECT_EQ(idp, nullptr); /* Unmap when remapping to self behavior. Should unassign. */ idp = &id1; - BKE_id_remapper_clear(remapper); - BKE_id_remapper_add(remapper, &id1, &id_self); - result = BKE_id_remapper_apply_ex( - remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); + remapper.clear(); + remapper.add(&id1, &id_self); + result = remapper.apply(&idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self); EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED); EXPECT_EQ(idp, nullptr); - BKE_id_remapper_free(remapper); } -} // namespace blender::bke::id::remapper::tests +} // namespace blender::bke::id::tests diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index cc74cabfde1..15c183ca61c 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -72,6 +72,8 @@ # include "BLI_time_utildefines.h" #endif +using namespace blender::bke; + static CLG_LogRef LOG = {"bke.liboverride"}; static CLG_LogRef LOG_RESYNC = {"bke.liboverride_resync"}; @@ -487,11 +489,11 @@ static void lib_override_prefill_newid_from_existing_overrides(Main *bmain, ID * FOREACH_MAIN_ID_END; } -static void lib_override_remapper_overrides_add(IDRemapper *id_remapper, +static void lib_override_remapper_overrides_add(id::IDRemapper &id_remapper, ID *reference_id, ID *local_id) { - BKE_id_remapper_add(id_remapper, reference_id, local_id); + id_remapper.add(reference_id, local_id); Key *reference_key, *local_key = nullptr; if ((reference_key = BKE_key_from_id(reference_id)) != nullptr) { @@ -500,7 +502,7 @@ static void lib_override_remapper_overrides_add(IDRemapper *id_remapper, BLI_assert(local_key != nullptr); } - BKE_id_remapper_add(id_remapper, &reference_key->id, &local_key->id); + id_remapper.add(&reference_key->id, &local_key->id); } } @@ -620,7 +622,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, BLI_assert(id_hierarchy_root != nullptr); blender::Vector relinked_ids; - IDRemapper *id_remapper = BKE_id_remapper_create(); + id::IDRemapper id_remapper; /* Still checking the whole Main, that way we can tag other local IDs as needing to be * remapped to use newly created overriding IDs, if needed. */ ID *id; @@ -693,7 +695,6 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain, id_remapper, ID_REMAP_SKIP_OVERRIDE_LIBRARY | ID_REMAP_FORCE_USER_REFCOUNT); - BKE_id_remapper_free(id_remapper); relinked_ids.clear(); } else { @@ -1934,7 +1935,7 @@ static void lib_override_library_remap(Main *bmain, GHash *linkedref_to_old_override) { ID *id; - IDRemapper *remapper = BKE_id_remapper_create(); + id::IDRemapper remapper; blender::Vector nomain_ids; FOREACH_MAIN_ID_BEGIN (bmain, id) { @@ -1944,7 +1945,7 @@ static void lib_override_library_remap(Main *bmain, if (id_override_old == nullptr) { continue; } - BKE_id_remapper_add(remapper, id_override_old, id_override_new); + remapper.add(id_override_old, id_override_new); } } FOREACH_MAIN_ID_END; @@ -1968,7 +1969,6 @@ static void lib_override_library_remap(Main *bmain, ID_REMAP_TYPE_REMAP, remapper, ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE); - BKE_id_remapper_free(remapper); } /** @@ -2515,7 +2515,7 @@ static bool lib_override_library_resync(Main *bmain, /* Once overrides have been properly 'transferred' from old to new ID, we can clear ID usages * of the old one. * This is necessary in case said old ID is not in Main anymore. */ - IDRemapper *id_remapper = BKE_id_remapper_create(); + id::IDRemapper id_remapper; BKE_libblock_relink_multiple(bmain, id_override_old_vector, ID_REMAP_TYPE_CLEANUP, @@ -2525,7 +2525,6 @@ static bool lib_override_library_resync(Main *bmain, id_override_old->tag |= LIB_TAG_NO_USER_REFCOUNT; } id_override_old_vector.clear(); - BKE_id_remapper_free(id_remapper); /* Delete old override IDs. * Note that we have to use tagged group deletion here, since ID deletion also uses diff --git a/source/blender/blenkernel/intern/lib_remap.cc b/source/blender/blenkernel/intern/lib_remap.cc index ca028dea0e0..ad04b2a3801 100644 --- a/source/blender/blenkernel/intern/lib_remap.cc +++ b/source/blender/blenkernel/intern/lib_remap.cc @@ -38,6 +38,8 @@ #include "lib_intern.hh" /* own include */ +using namespace blender::bke::id; + static CLG_LogRef LOG = {"bke.lib_remap"}; BKE_library_free_notifier_reference_cb free_notifier_reference_cb = nullptr; @@ -59,7 +61,7 @@ struct IDRemap { eIDRemapType type; Main *bmain; /* Only used to trigger depsgraph updates in the right bmain. */ - IDRemapper *id_remapper; + IDRemapper &id_remapper; /** The ID in which we are replacing old_id by new_id usages. */ ID *id_owner; @@ -103,7 +105,7 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner, ID *id_self, ID **id_ptr, IDRemap *id_remap_data, - const IDRemapper *mappings, + const IDRemapper &mappings, const IDRemapperApplyOptions id_remapper_options, const int cb_flag, const bool is_indirect, @@ -116,7 +118,7 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner, ID *old_id = *id_ptr; if (!violates_never_null) { - BKE_id_remapper_apply_ex(mappings, id_ptr, id_remapper_options, id_self); + mappings.apply(id_ptr, id_remapper_options, id_self); if (!skip_update_tagging) { if (id_remap_data->bmain != nullptr) { DEG_id_tag_update_ex(id_remap_data->bmain, @@ -195,15 +197,15 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) return IDWALK_RET_NOP; } - IDRemapper *id_remapper = id_remap_data->id_remapper; + IDRemapper &id_remapper = id_remap_data->id_remapper; IDRemapperApplyOptions id_remapper_options = ID_REMAP_APPLY_DEFAULT; /* Used to cleanup all IDs used by a specific one. */ if (id_remap_data->type == ID_REMAP_TYPE_CLEANUP) { /* Clearing existing instance to reduce potential lookup times for IDs referencing many other * IDs. This makes sure that there will only be a single rule in the id_remapper. */ - BKE_id_remapper_clear(id_remapper); - BKE_id_remapper_add(id_remapper, *id_p, nullptr); + id_remapper.clear(); + id_remapper.add(*id_p, nullptr); } /* Better remap to nullptr than not remapping at all, @@ -212,8 +214,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) id_remapper_options |= ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF; } - const IDRemapperApplyResult expected_mapping_result = BKE_id_remapper_get_mapping_result( - id_remapper, *id_p, id_remapper_options, id_self); + const IDRemapperApplyResult expected_mapping_result = id_remapper.get_mapping_result( + *id_p, id_remapper_options, id_self); /* Exit, when no modifications will be done; ensuring id->runtime counters won't changed. */ if (ELEM(expected_mapping_result, ID_REMAP_RESULT_SOURCE_UNAVAILABLE, @@ -247,7 +249,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) id_owner->lib, (*id_p)->name, *id_p, - BKE_id_remapper_result_string(expected_mapping_result), + id_remapper.result_to_string(expected_mapping_result).c_str(), is_indirect, skip_indirect, is_reference, @@ -292,7 +294,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data) static void libblock_remap_data_preprocess_ob(Object *ob, eIDRemapType remap_type, - const IDRemapper *id_remapper) + const IDRemapper &id_remapper) { if (ob->type != OB_ARMATURE) { return; @@ -303,7 +305,7 @@ static void libblock_remap_data_preprocess_ob(Object *ob, const bool is_cleanup_type = remap_type == ID_REMAP_TYPE_CLEANUP; /* Early exit when mapping, but no armature mappings present. */ - if (!is_cleanup_type && !BKE_id_remapper_has_mapping_for(id_remapper, FILTER_ID_AR)) { + if (!is_cleanup_type && !id_remapper.contains_mappings_for_any(FILTER_ID_AR)) { return; } @@ -313,8 +315,8 @@ static void libblock_remap_data_preprocess_ob(Object *ob, * Fortunately, this is just a tag, so we can accept to 'over-tag' a bit for pose recalc, * and avoid another complex and risky condition nightmare like the one we have in * foreach_libblock_remap_callback(). */ - const IDRemapperApplyResult expected_mapping_result = BKE_id_remapper_get_mapping_result( - id_remapper, static_cast(ob->data), ID_REMAP_APPLY_DEFAULT, nullptr); + const IDRemapperApplyResult expected_mapping_result = id_remapper.get_mapping_result( + static_cast(ob->data), ID_REMAP_APPLY_DEFAULT, nullptr); if (is_cleanup_type || expected_mapping_result == ID_REMAP_RESULT_SOURCE_REMAPPED) { ob->pose->flag |= POSE_RECALC; /* We need to clear pose bone pointers immediately, some code may access those before @@ -325,7 +327,7 @@ static void libblock_remap_data_preprocess_ob(Object *ob, static void libblock_remap_data_preprocess(ID *id_owner, eIDRemapType remap_type, - const IDRemapper *id_remapper) + const IDRemapper &id_remapper) { switch (GS(id_owner->name)) { case ID_OB: { @@ -483,9 +485,16 @@ static void libblock_remap_reset_remapping_status_callback(ID *old_id, * (useful to retrieve info about remapping process). */ static void libblock_remap_data( - Main *bmain, ID *id, eIDRemapType remap_type, IDRemapper *id_remapper, const int remap_flags) + Main *bmain, ID *id, eIDRemapType remap_type, IDRemapper &id_remapper, const int remap_flags) { - IDRemap id_remap_data = {eIDRemapType(0)}; + IDRemap id_remap_data = { + /*.type=*/remap_type, + /*.bmain=*/bmain, + /*.id_remapper=*/id_remapper, + /*.id_owner=*/nullptr, + /*.flag=*/remap_flags, + }; + const bool include_ui = (remap_flags & ID_REMAP_FORCE_UI_POINTERS) != 0; const int foreach_id_flags = (((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ? IDWALK_DO_INTERNAL_RUNTIME_POINTERS : @@ -499,13 +508,7 @@ static void libblock_remap_data( IDWALK_DO_LIBRARY_POINTER : IDWALK_NOP)); - id_remap_data.id_remapper = id_remapper; - id_remap_data.type = remap_type; - id_remap_data.bmain = bmain; - id_remap_data.id_owner = nullptr; - id_remap_data.flag = remap_flags; - - BKE_id_remapper_iter(id_remapper, libblock_remap_reset_remapping_status_callback, nullptr); + id_remapper.iter(libblock_remap_reset_remapping_status_callback, nullptr); if (id) { #ifdef DEBUG_PRINT @@ -524,7 +527,7 @@ static void libblock_remap_data( FOREACH_MAIN_ID_BEGIN (bmain, id_curr) { const uint64_t can_use_filter_id = BKE_library_id_can_use_filter_id(id_curr, include_ui); - const bool has_mapping = BKE_id_remapper_has_mapping_for(id_remapper, can_use_filter_id); + const bool has_mapping = id_remapper.contains_mappings_for_any(can_use_filter_id); /* Continue when id_remapper doesn't have any mappings that can be used by id_curr. */ if (!has_mapping) { @@ -544,7 +547,7 @@ static void libblock_remap_data( FOREACH_MAIN_ID_END; } - BKE_id_remapper_iter(id_remapper, libblock_remap_data_update_tags, &id_remap_data); + id_remapper.iter(libblock_remap_data_update_tags, &id_remap_data); } struct LibBlockRemapMultipleUserData { @@ -645,9 +648,9 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_ BKE_libblock_runtime_reset_remapping_status(old_id); } -void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper *mappings, const int remap_flags) +void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper &mappings, const int remap_flags) { - if (BKE_id_remapper_is_empty(mappings)) { + if (mappings.is_empty()) { /* Early exit nothing to do. */ return; } @@ -658,7 +661,7 @@ void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper *mappings, const user_data.bmain = bmain; user_data.remap_flags = remap_flags; - BKE_id_remapper_iter(mappings, libblock_remap_foreach_idpair_cb, &user_data); + mappings.iter(libblock_remap_foreach_idpair_cb, &user_data); /* We assume editors do not hold references to their IDs... This is false in some cases * (Image is especially tricky here), @@ -671,9 +674,9 @@ void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper *mappings, const DEG_relations_tag_update(bmain); } -void BKE_libblock_remap_multiple_raw(Main *bmain, IDRemapper *mappings, const int remap_flags) +void BKE_libblock_remap_multiple_raw(Main *bmain, IDRemapper &mappings, const int remap_flags) { - if (BKE_id_remapper_is_empty(mappings)) { + if (mappings.is_empty()) { /* Early exit nothing to do. */ return; } @@ -687,12 +690,11 @@ void BKE_libblock_remap_multiple_raw(Main *bmain, IDRemapper *mappings, const in void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const int remap_flags) { - IDRemapper *remapper = BKE_id_remapper_create(); + IDRemapper remapper; ID *old_id = static_cast(old_idv); ID *new_id = static_cast(new_idv); - BKE_id_remapper_add(remapper, old_id, new_id); + remapper.add(old_id, new_id); BKE_libblock_remap_multiple_locked(bmain, remapper, remap_flags); - BKE_id_remapper_free(remapper); } void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const int remap_flags) @@ -704,7 +706,7 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const int rem BKE_main_unlock(bmain); } -void BKE_libblock_remap_multiple(Main *bmain, IDRemapper *mappings, const int remap_flags) +void BKE_libblock_remap_multiple(Main *bmain, IDRemapper &mappings, const int remap_flags) { BKE_main_lock(bmain); @@ -798,10 +800,10 @@ static void libblock_relink_foreach_idpair_cb(ID *old_id, ID *new_id, void *user void BKE_libblock_relink_multiple(Main *bmain, const blender::Span ids, const eIDRemapType remap_type, - IDRemapper *id_remapper, + IDRemapper &id_remapper, const int remap_flags) { - BLI_assert(remap_type == ID_REMAP_TYPE_REMAP || BKE_id_remapper_is_empty(id_remapper)); + BLI_assert(remap_type == ID_REMAP_TYPE_REMAP || id_remapper.is_empty()); for (ID *id_iter : ids) { libblock_remap_data(bmain, id_iter, remap_type, id_remapper, remap_flags); @@ -815,7 +817,7 @@ void BKE_libblock_relink_multiple(Main *bmain, case ID_REMAP_TYPE_REMAP: { LibBlockRelinkMultipleUserData user_data = {bmain, ids}; - BKE_id_remapper_iter(id_remapper, libblock_relink_foreach_idpair_cb, &user_data); + id_remapper.iter(libblock_relink_foreach_idpair_cb, &user_data); break; } case ID_REMAP_TYPE_CLEANUP: { @@ -869,7 +871,7 @@ void BKE_libblock_relink_ex( blender::Array ids = {id}; /* No need to lock here, we are only affecting given ID, not bmain database. */ - IDRemapper *id_remapper = BKE_id_remapper_create(); + IDRemapper id_remapper; eIDRemapType remap_type = ID_REMAP_TYPE_REMAP; BLI_assert(id != nullptr); @@ -877,7 +879,7 @@ void BKE_libblock_relink_ex( if (old_id != nullptr) { BLI_assert((new_id == nullptr) || GS(old_id->name) == GS(new_id->name)); BLI_assert(old_id != new_id); - BKE_id_remapper_add(id_remapper, old_id, new_id); + id_remapper.add(old_id, new_id); } else { BLI_assert(new_id == nullptr); @@ -885,13 +887,11 @@ void BKE_libblock_relink_ex( } BKE_libblock_relink_multiple(bmain, ids, remap_type, id_remapper, remap_flags); - - BKE_id_remapper_free(id_remapper); } struct RelinkToNewIDData { blender::Vector ids; - IDRemapper *id_remapper; + IDRemapper id_remapper; }; static void libblock_relink_to_newid_prepare_data(Main *bmain, @@ -908,12 +908,12 @@ static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data) Main *bmain = cb_data->bmain; ID **id_pointer = cb_data->id_pointer; ID *id = *id_pointer; - RelinkToNewIDData *relink_data = (RelinkToNewIDData *)cb_data->user_data; + RelinkToNewIDData *relink_data = static_cast(cb_data->user_data); if (id) { /* See: NEW_ID macro */ if (id->newid != nullptr) { - BKE_id_remapper_add(relink_data->id_remapper, id, id->newid); + relink_data->id_remapper.add(id, id->newid); id = id->newid; } if (id->tag & LIB_TAG_NEW) { @@ -945,7 +945,6 @@ void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag) BLI_assert(bmain->relations == nullptr); RelinkToNewIDData relink_data{}; - relink_data.id_remapper = BKE_id_remapper_create(); libblock_relink_to_newid_prepare_data(bmain, id, &relink_data); @@ -953,6 +952,4 @@ void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag) ID_REMAP_SKIP_OVERRIDE_LIBRARY; BKE_libblock_relink_multiple( bmain, relink_data.ids, ID_REMAP_TYPE_REMAP, relink_data.id_remapper, remap_flag_final); - - BKE_id_remapper_free(relink_data.id_remapper); } diff --git a/source/blender/blenkernel/intern/main.cc b/source/blender/blenkernel/intern/main.cc index 75343243540..29c379aea31 100644 --- a/source/blender/blenkernel/intern/main.cc +++ b/source/blender/blenkernel/intern/main.cc @@ -38,6 +38,8 @@ #include "IMB_imbuf.hh" #include "IMB_imbuf_types.hh" +using namespace blender::bke; + static CLG_LogRef LOG = {"bke.main"}; Main *BKE_main_new() @@ -258,7 +260,7 @@ static bool are_ids_from_different_mains_matching(Main *bmain_1, ID *id_1, Main static void main_merge_add_id_to_move(Main *bmain_dst, blender::Map> &id_map_dst, ID *id_src, - IDRemapper *id_remapper, + id::IDRemapper &id_remapper, blender::Vector &ids_to_move, const bool is_library, MainMergeReport &reports) @@ -287,7 +289,7 @@ static void main_merge_add_id_to_move(Main *bmain_dst, "found in given destination Main", id_src->name, bmain_dst->filepath); - BKE_id_remapper_add(id_remapper, id_src, nullptr); + id_remapper.add(id_src, nullptr); reports.num_unknown_ids++; } else { @@ -321,8 +323,8 @@ void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &report /* A dedicated remapper for libraries is needed because these need to be remapped _before_ IDs * are moved from `bmain_src` to `bmain_dst`, to avoid having to fix naming and ordering of IDs * afterwards (especially in case some source linked IDs become local in `bmain_dst`). */ - IDRemapper *id_remapper = BKE_id_remapper_create(); - IDRemapper *id_remapper_libraries = BKE_id_remapper_create(); + id::IDRemapper id_remapper; + id::IDRemapper id_remapper_libraries; blender::Vector ids_to_move; FOREACH_MAIN_ID_BEGIN (bmain_src, id_iter_src) { @@ -347,11 +349,11 @@ void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &report BLI_assert(!src_has_match_in_dst); if (!src_has_match_in_dst) { if (is_library) { - BKE_id_remapper_add(id_remapper_libraries, id_iter_src, id_iter_dst); + id_remapper_libraries.add(id_iter_src, id_iter_dst); reports.num_remapped_libraries++; } else { - BKE_id_remapper_add(id_remapper, id_iter_src, id_iter_dst); + id_remapper.add(id_iter_src, id_iter_dst); reports.num_remapped_ids++; } src_has_match_in_dst = true; @@ -426,8 +428,6 @@ void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &report BLI_assert(BKE_main_namemap_validate(bmain_dst)); - BKE_id_remapper_free(id_remapper); - BKE_id_remapper_free(id_remapper_libraries); BKE_main_free(bmain_src); *r_bmain_src = nullptr; } diff --git a/source/blender/blenkernel/intern/viewer_path.cc b/source/blender/blenkernel/intern/viewer_path.cc index b94c15063e9..01f9b268ca7 100644 --- a/source/blender/blenkernel/intern/viewer_path.cc +++ b/source/blender/blenkernel/intern/viewer_path.cc @@ -142,13 +142,14 @@ void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_p } } -void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mappings) +void BKE_viewer_path_id_remap(ViewerPath *viewer_path, + const blender::bke::id::IDRemapper &mappings) { LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { switch (ViewerPathElemType(elem->type)) { case VIEWER_PATH_ELEM_TYPE_ID: { auto *typed_elem = reinterpret_cast(elem); - BKE_id_remapper_apply(mappings, &typed_elem->id, ID_REMAP_APPLY_DEFAULT); + mappings.apply(&typed_elem->id, ID_REMAP_APPLY_DEFAULT); break; } case VIEWER_PATH_ELEM_TYPE_MODIFIER: diff --git a/source/blender/editors/include/ED_util.hh b/source/blender/editors/include/ED_util.hh index 8450cc3d72e..087bc87766f 100644 --- a/source/blender/editors/include/ED_util.hh +++ b/source/blender/editors/include/ED_util.hh @@ -11,10 +11,13 @@ #include "BLI_compiler_attrs.h" #include "WM_types.hh" -struct IDRemapper; struct Main; struct bContext; +namespace blender::bke::id { +class IDRemapper; +} + /* ed_util.cc */ void ED_editors_init_for_undo(Main *bmain); @@ -42,7 +45,9 @@ bool ED_editors_flush_edits(Main *bmain); * \param new_id: may be NULL to unlink \a old_id. */ void ED_spacedata_id_remap_single(ScrArea *area, SpaceLink *sl, ID *old_id, ID *new_id); -void ED_spacedata_id_remap(ScrArea *area, SpaceLink *sl, const IDRemapper *mappings); +void ED_spacedata_id_remap(ScrArea *area, + SpaceLink *sl, + const blender::bke::id::IDRemapper &mappings); void ED_operatortypes_edutils(); diff --git a/source/blender/editors/space_action/space_action.cc b/source/blender/editors/space_action/space_action.cc index ce671335645..829cdf0aa40 100644 --- a/source/blender/editors/space_action/space_action.cc +++ b/source/blender/editors/space_action/space_action.cc @@ -783,13 +783,15 @@ static void action_refresh(const bContext *C, ScrArea *area) /* XXX re-sizing y-extents of tot should go here? */ } -static void action_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void action_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceAction *sact = (SpaceAction *)slink; - BKE_id_remapper_apply(mappings, (ID **)&sact->action, ID_REMAP_APPLY_DEFAULT); - BKE_id_remapper_apply(mappings, (ID **)&sact->ads.filter_grp, ID_REMAP_APPLY_DEFAULT); - BKE_id_remapper_apply(mappings, &sact->ads.source, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&sact->action, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&sact->ads.filter_grp, ID_REMAP_APPLY_DEFAULT); + mappings.apply(&sact->ads.source, ID_REMAP_APPLY_DEFAULT); } static void action_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_buttons/space_buttons.cc b/source/blender/editors/space_buttons/space_buttons.cc index fff575c2cef..5ba94eca019 100644 --- a/source/blender/editors/space_buttons/space_buttons.cc +++ b/source/blender/editors/space_buttons/space_buttons.cc @@ -854,20 +854,20 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params) } } -static void buttons_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void buttons_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceProperties *sbuts = (SpaceProperties *)slink; - if (BKE_id_remapper_apply(mappings, &sbuts->pinid, ID_REMAP_APPLY_DEFAULT) == - ID_REMAP_RESULT_SOURCE_UNASSIGNED) - { + if (mappings.apply(&sbuts->pinid, ID_REMAP_APPLY_DEFAULT) == ID_REMAP_RESULT_SOURCE_UNASSIGNED) { sbuts->flag &= ~SB_PIN_CONTEXT; } if (sbuts->path) { ButsContextPath *path = static_cast(sbuts->path); for (int i = 0; i < path->len; i++) { - switch (BKE_id_remapper_apply(mappings, &path->ptr[i].owner_id, ID_REMAP_APPLY_DEFAULT)) { + switch (mappings.apply(&path->ptr[i].owner_id, ID_REMAP_APPLY_DEFAULT)) { case ID_REMAP_RESULT_SOURCE_UNASSIGNED: { path->len = i; if (i != 0) { @@ -901,7 +901,7 @@ static void buttons_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemap if (sbuts->texuser) { ButsContextTexture *ct = static_cast(sbuts->texuser); - BKE_id_remapper_apply(mappings, (ID **)&ct->texture, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&ct->texture, ID_REMAP_APPLY_DEFAULT); BLI_freelistN(&ct->users); ct->user = nullptr; } diff --git a/source/blender/editors/space_clip/space_clip.cc b/source/blender/editors/space_clip/space_clip.cc index ce97120f9b9..8e0529ae45d 100644 --- a/source/blender/editors/space_clip/space_clip.cc +++ b/source/blender/editors/space_clip/space_clip.cc @@ -1151,16 +1151,18 @@ static void clip_properties_region_listener(const wmRegionListenerParams *params /** \name IO Callbacks * \{ */ -static void clip_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void clip_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceClip *sclip = (SpaceClip *)slink; - if (!BKE_id_remapper_has_mapping_for(mappings, FILTER_ID_MC | FILTER_ID_MSK)) { + if (!mappings.contains_mappings_for_any(FILTER_ID_MC | FILTER_ID_MSK)) { return; } - BKE_id_remapper_apply(mappings, (ID **)&sclip->clip, ID_REMAP_APPLY_ENSURE_REAL); - BKE_id_remapper_apply(mappings, (ID **)&sclip->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); + mappings.apply((ID **)&sclip->clip, ID_REMAP_APPLY_ENSURE_REAL); + mappings.apply((ID **)&sclip->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); } static void clip_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_file/space_file.cc b/source/blender/editors/space_file/space_file.cc index 35c5955c766..6c0d65a2c97 100644 --- a/source/blender/editors/space_file/space_file.cc +++ b/source/blender/editors/space_file/space_file.cc @@ -827,7 +827,9 @@ static void file_space_subtype_item_extend(bContext * /*C*/, EnumPropertyItem ** RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items); } -static void file_id_remap(ScrArea *area, SpaceLink *sl, const IDRemapper * /*mappings*/) +static void file_id_remap(ScrArea *area, + SpaceLink *sl, + const blender::bke::id::IDRemapper & /*mappings*/) { SpaceFile *sfile = (SpaceFile *)sl; diff --git a/source/blender/editors/space_graph/space_graph.cc b/source/blender/editors/space_graph/space_graph.cc index b999b12fb18..844704d6c83 100644 --- a/source/blender/editors/space_graph/space_graph.cc +++ b/source/blender/editors/space_graph/space_graph.cc @@ -796,15 +796,17 @@ static void graph_refresh(const bContext *C, ScrArea *area) graph_refresh_fcurve_colors(C); } -static void graph_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void graph_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceGraph *sgraph = (SpaceGraph *)slink; if (!sgraph->ads) { return; } - BKE_id_remapper_apply(mappings, (ID **)&sgraph->ads->filter_grp, ID_REMAP_APPLY_DEFAULT); - BKE_id_remapper_apply(mappings, (ID **)&sgraph->ads->source, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&sgraph->ads->filter_grp, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&sgraph->ads->source, ID_REMAP_APPLY_DEFAULT); } static void graph_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_image/space_image.cc b/source/blender/editors/space_image/space_image.cc index b3b3bb24fa3..7c5beaafd27 100644 --- a/source/blender/editors/space_image/space_image.cc +++ b/source/blender/editors/space_image/space_image.cc @@ -1006,19 +1006,19 @@ static void image_header_region_listener(const wmRegionListenerParams *params) } } -static void image_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void image_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceImage *simg = (SpaceImage *)slink; - if (!BKE_id_remapper_has_mapping_for(mappings, - FILTER_ID_IM | FILTER_ID_GD_LEGACY | FILTER_ID_MSK)) - { + if (!mappings.contains_mappings_for_any(FILTER_ID_IM | FILTER_ID_GD_LEGACY | FILTER_ID_MSK)) { return; } - BKE_id_remapper_apply(mappings, (ID **)&simg->image, ID_REMAP_APPLY_ENSURE_REAL); - BKE_id_remapper_apply(mappings, (ID **)&simg->gpd, ID_REMAP_APPLY_UPDATE_REFCOUNT); - BKE_id_remapper_apply(mappings, (ID **)&simg->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); + mappings.apply((ID **)&simg->image, ID_REMAP_APPLY_ENSURE_REAL); + mappings.apply((ID **)&simg->gpd, ID_REMAP_APPLY_UPDATE_REFCOUNT); + mappings.apply((ID **)&simg->mask_info.mask, ID_REMAP_APPLY_ENSURE_REAL); } static void image_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_nla/space_nla.cc b/source/blender/editors/space_nla/space_nla.cc index b41d5b7271f..aa6d1a22b52 100644 --- a/source/blender/editors/space_nla/space_nla.cc +++ b/source/blender/editors/space_nla/space_nla.cc @@ -554,17 +554,18 @@ static void nla_listener(const wmSpaceTypeListenerParams *params) } } -static void nla_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void nla_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceNla *snla = reinterpret_cast(slink); if (snla->ads == nullptr) { return; } - BKE_id_remapper_apply( - mappings, reinterpret_cast(&snla->ads->filter_grp), ID_REMAP_APPLY_DEFAULT); - BKE_id_remapper_apply( - mappings, reinterpret_cast(&snla->ads->source), ID_REMAP_APPLY_DEFAULT); + + mappings.apply(reinterpret_cast(&snla->ads->filter_grp), ID_REMAP_APPLY_DEFAULT); + mappings.apply(reinterpret_cast(&snla->ads->source), ID_REMAP_APPLY_DEFAULT); } static void nla_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 65e3353799f..169a323b086 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -1223,7 +1223,9 @@ static void node_id_remap_cb(ID *old_id, ID *new_id, void *user_data) } } -static void node_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void node_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { /* Although we should be able to perform all the mappings in a single go this lead to issues when * running the python test cases. Somehow the nodetree/edittree weren't updated to the new @@ -1236,7 +1238,7 @@ static void node_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper * We could also move a remap address at a time to use the IDRemapper as that should get closer * to cleaner code. See {D13615} for more information about this topic. */ - BKE_id_remapper_iter(mappings, node_id_remap_cb, slink); + mappings.iter(node_id_remap_cb, slink); } static void node_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index d3ca02955cc..521b386df24 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -410,7 +410,9 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl) return (SpaceLink *)space_outliner_new; } -static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const IDRemapper *mappings) +static void outliner_id_remap(ScrArea *area, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceOutliner *space_outliner = (SpaceOutliner *)slink; @@ -425,7 +427,7 @@ static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const IDRemapper BLI_mempool_iternew(space_outliner->treestore, &iter); while ((tselem = static_cast(BLI_mempool_iterstep(&iter)))) { - switch (BKE_id_remapper_apply(mappings, &tselem->id, ID_REMAP_APPLY_DEFAULT)) { + switch (mappings.apply(&tselem->id, ID_REMAP_APPLY_DEFAULT)) { case ID_REMAP_RESULT_SOURCE_REMAPPED: changed = true; break; diff --git a/source/blender/editors/space_sequencer/sequencer_clipboard.cc b/source/blender/editors/space_sequencer/sequencer_clipboard.cc index d23435c841f..e3a39ffbbd2 100644 --- a/source/blender/editors/space_sequencer/sequencer_clipboard.cc +++ b/source/blender/editors/space_sequencer/sequencer_clipboard.cc @@ -66,7 +66,8 @@ static int gather_strip_data_ids_to_null(LibraryIDLinkCallbackData *cb_data) { - IDRemapper *id_remapper = static_cast(cb_data->user_data); + blender::bke::id::IDRemapper &id_remapper = *static_cast( + cb_data->user_data); ID *id = *cb_data->id_pointer; /* We don't care about embedded, loop-back, or internal IDs. */ @@ -82,7 +83,7 @@ static int gather_strip_data_ids_to_null(LibraryIDLinkCallbackData *cb_data) /* Nullify everything that is not: * #bSound, #MovieClip, #Image, #Text, #VFont, #bAction, or #Collection IDs. */ if (!ELEM(id_type, ID_SO, ID_MC, ID_IM, ID_TXT, ID_VF, ID_AC)) { - BKE_id_remapper_add(id_remapper, id, nullptr); + id_remapper.add(id, nullptr); return IDWALK_RET_STOP_RECURSION; } } @@ -183,12 +184,11 @@ static bool sequencer_write_copy_paste_file(Main *bmain_src, * to copy whole scenes. We have to come up with a proper idea of how to copy and * paste scene strips. */ - IDRemapper *id_remapper = BKE_id_remapper_create(); + blender::bke::id::IDRemapper id_remapper; BKE_library_foreach_ID_link( - bmain_src, &scene_dst->id, gather_strip_data_ids_to_null, id_remapper, IDWALK_RECURSE); + bmain_src, &scene_dst->id, gather_strip_data_ids_to_null, &id_remapper, IDWALK_RECURSE); BKE_libblock_remap_multiple(bmain_src, id_remapper, 0); - BKE_id_remapper_free(id_remapper); /* Ensure that there are no old copy tags around */ BKE_blendfile_write_partial_begin(bmain_src); diff --git a/source/blender/editors/space_sequencer/space_sequencer.cc b/source/blender/editors/space_sequencer/space_sequencer.cc index 72a4ea649aa..1da1a731a72 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.cc +++ b/source/blender/editors/space_sequencer/space_sequencer.cc @@ -906,10 +906,12 @@ static void sequencer_buttons_region_listener(const wmRegionListenerParams *para } } -static void sequencer_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void sequencer_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceSeq *sseq = (SpaceSeq *)slink; - BKE_id_remapper_apply(mappings, (ID **)&sseq->gpd, ID_REMAP_APPLY_DEFAULT); + mappings.apply((ID **)&sseq->gpd, ID_REMAP_APPLY_DEFAULT); } static void sequencer_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 786527af96e..a88a5ea5d0b 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -152,7 +152,9 @@ static void spreadsheet_keymap(wmKeyConfig *keyconf) WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW); } -static void spreadsheet_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void spreadsheet_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink; BKE_viewer_path_id_remap(&sspreadsheet->viewer_path, mappings); diff --git a/source/blender/editors/space_text/space_text.cc b/source/blender/editors/space_text/space_text.cc index 14dc911ab14..14ab0b8231a 100644 --- a/source/blender/editors/space_text/space_text.cc +++ b/source/blender/editors/space_text/space_text.cc @@ -376,10 +376,12 @@ static void text_properties_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void text_id_remap(ScrArea * /*area*/, SpaceLink *slink, const IDRemapper *mappings) +static void text_id_remap(ScrArea * /*area*/, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { SpaceText *stext = (SpaceText *)slink; - BKE_id_remapper_apply(mappings, (ID **)&stext->text, ID_REMAP_APPLY_ENSURE_REAL); + mappings.apply((ID **)&stext->text, ID_REMAP_APPLY_ENSURE_REAL); } static void text_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 0c2b5a32b1d..b331c3dfe07 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -1991,9 +1991,10 @@ static void space_view3d_refresh(const bContext *C, ScrArea *area) MEM_SAFE_FREE(v3d->runtime.local_stats); } -static void view3d_id_remap_v3d_ob_centers(View3D *v3d, const IDRemapper *mappings) +static void view3d_id_remap_v3d_ob_centers(View3D *v3d, + const blender::bke::id::IDRemapper &mappings) { - if (BKE_id_remapper_apply(mappings, (ID **)&v3d->ob_center, ID_REMAP_APPLY_DEFAULT) == + if (mappings.apply((ID **)&v3d->ob_center, ID_REMAP_APPLY_DEFAULT) == ID_REMAP_RESULT_SOURCE_UNASSIGNED) { /* Otherwise, bone-name may remain valid... @@ -2002,10 +2003,13 @@ static void view3d_id_remap_v3d_ob_centers(View3D *v3d, const IDRemapper *mappin } } -static void view3d_id_remap_v3d( - ScrArea *area, SpaceLink *slink, View3D *v3d, const IDRemapper *mappings, const bool is_local) +static void view3d_id_remap_v3d(ScrArea *area, + SpaceLink *slink, + View3D *v3d, + const blender::bke::id::IDRemapper &mappings, + const bool is_local) { - if (BKE_id_remapper_apply(mappings, (ID **)&v3d->camera, ID_REMAP_APPLY_DEFAULT) == + if (mappings.apply((ID **)&v3d->camera, ID_REMAP_APPLY_DEFAULT) == ID_REMAP_RESULT_SOURCE_UNASSIGNED) { /* 3D view might be inactive, in that case needs to use slink->regionbase */ @@ -2023,11 +2027,13 @@ static void view3d_id_remap_v3d( } } -static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const IDRemapper *mappings) +static void view3d_id_remap(ScrArea *area, + SpaceLink *slink, + const blender::bke::id::IDRemapper &mappings) { - if (!BKE_id_remapper_has_mapping_for(mappings, - FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_IM | FILTER_ID_MC)) + if (!mappings.contains_mappings_for_any(FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_IM | + FILTER_ID_MC)) { return; } diff --git a/source/blender/editors/util/ed_util.cc b/source/blender/editors/util/ed_util.cc index 337deb1928f..fda7b179db7 100644 --- a/source/blender/editors/util/ed_util.cc +++ b/source/blender/editors/util/ed_util.cc @@ -464,7 +464,9 @@ void unpack_menu(bContext *C, UI_popup_menu_end(C, pup); } -void ED_spacedata_id_remap(ScrArea *area, SpaceLink *sl, const IDRemapper *mappings) +void ED_spacedata_id_remap(ScrArea *area, + SpaceLink *sl, + const blender::bke::id::IDRemapper &mappings) { SpaceType *st = BKE_spacetype_from_id(sl->spacetype); if (st && st->id_remap) { @@ -477,9 +479,8 @@ void ED_spacedata_id_remap_single(ScrArea *area, SpaceLink *sl, ID *old_id, ID * SpaceType *st = BKE_spacetype_from_id(sl->spacetype); if (st && st->id_remap) { - IDRemapper *mappings = BKE_id_remapper_create(); - BKE_id_remapper_add(mappings, old_id, new_id); + blender::bke::id::IDRemapper mappings; + mappings.add(old_id, new_id); st->id_remap(area, sl, mappings); - BKE_id_remapper_free(mappings); } } diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index f5d0754a44f..f6348f40cce 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -28,7 +28,6 @@ struct GHashIterator; struct GPUViewport; struct ID; struct IDProperty; -struct IDRemapper; struct ImBuf; struct ImageFormatData; struct Main; @@ -71,6 +70,10 @@ struct wmXrRuntimeData; struct wmXrSessionState; #endif +namespace blender::bke::id { +class IDRemapper; +} + namespace blender::asset_system { class AssetRepresentation; } @@ -585,7 +588,7 @@ void WM_main_add_notifier(unsigned int type, void *reference); * Clear notifiers by reference, Used so listeners don't act on freed data. */ void WM_main_remove_notifier_reference(const void *reference); -void WM_main_remap_editor_id_reference(const IDRemapper *mappings); +void WM_main_remap_editor_id_reference(const blender::bke::id::IDRemapper &mappings); /* reports */ /** diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 20860675143..945ea95f2a3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -412,7 +412,7 @@ static void wm_main_remap_msgbus_notify(ID *old_id, ID *new_id, void *user_data) } } -void WM_main_remap_editor_id_reference(const IDRemapper *mappings) +void WM_main_remap_editor_id_reference(const blender::bke::id::IDRemapper &mappings) { Main *bmain = G_MAIN; @@ -424,11 +424,11 @@ void WM_main_remap_editor_id_reference(const IDRemapper *mappings) } } - BKE_id_remapper_iter(mappings, wm_main_remap_assetlist, nullptr); + mappings.iter(wm_main_remap_assetlist, nullptr); wmWindowManager *wm = static_cast(bmain->wm.first); if (wm && wm->message_bus) { - BKE_id_remapper_iter(mappings, wm_main_remap_msgbus_notify, wm->message_bus); + mappings.iter(wm_main_remap_msgbus_notify, wm->message_bus); } AS_asset_library_remap_ids(mappings);