BKE ID remap: Refactor: Remove C API around CPP IDRemapper.
The ID remapper code was already largely defined in a CPP struct (IDRemapper). Make this an actual class, and remove the C API wrapper around. This makes the code cleaner, easier to follow, and easier to extend or modify in the future. Pull Request: https://projects.blender.org/blender/blender/pulls/118146
This commit is contained in:
committed by
Bastien Montagne
parent
d284941e89
commit
5baef63a20
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<AssetRepresentation *> 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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ID *> 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<ID *, ID *> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<id::IDRemapper>(__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<ID *>(discarded_id_iter->next);
|
||||
reused_id_iter = static_cast<ID *>(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<ID *>(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<ID *>(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<ReuseOldBMainData *>(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);
|
||||
|
||||
@@ -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<IDRemapper>(__func__);
|
||||
}
|
||||
if (remapper_id_b == nullptr) {
|
||||
remapper_id_b = BKE_id_remapper_create();
|
||||
remapper_id_b = MEM_new<IDRemapper>(__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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ID *>(lb->first); id; id = id_next) {
|
||||
id_next = static_cast<ID *>(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);
|
||||
|
||||
@@ -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<ID *, ID *> 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<IDRemapper *>(static_cast<void *>(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<blender::bke::id::remapper::IDRemapper *>(static_cast<void *>(remapper));
|
||||
}
|
||||
|
||||
/** \brief wrap C handle to a CPP IDRemapper. */
|
||||
static const blender::bke::id::remapper::IDRemapper *unwrap(const IDRemapper *remapper)
|
||||
{
|
||||
return static_cast<const blender::bke::id::remapper::IDRemapper *>(
|
||||
static_cast<const void *>(remapper));
|
||||
}
|
||||
|
||||
IDRemapper *BKE_id_remapper_create()
|
||||
{
|
||||
blender::bke::id::remapper::IDRemapper *remapper =
|
||||
MEM_new<blender::bke::id::remapper::IDRemapper>(__func__);
|
||||
return wrap(remapper);
|
||||
}
|
||||
|
||||
void BKE_id_remapper_free(IDRemapper *id_remapper)
|
||||
{
|
||||
blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
|
||||
MEM_delete<blender::bke::id::remapper::IDRemapper>(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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ID *> 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<ID *> 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
|
||||
|
||||
@@ -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<ID *>(ob->data), ID_REMAP_APPLY_DEFAULT, nullptr);
|
||||
const IDRemapperApplyResult expected_mapping_result = id_remapper.get_mapping_result(
|
||||
static_cast<ID *>(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<ID *>(old_idv);
|
||||
ID *new_id = static_cast<ID *>(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<ID *> 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<ID *> 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<ID *> 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<RelinkToNewIDData *>(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);
|
||||
}
|
||||
|
||||
@@ -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<std::string, blender::Vector<ID *>> &id_map_dst,
|
||||
ID *id_src,
|
||||
IDRemapper *id_remapper,
|
||||
id::IDRemapper &id_remapper,
|
||||
blender::Vector<ID *> &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<ID *> 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;
|
||||
}
|
||||
|
||||
@@ -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<IDViewerPathElem *>(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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<ButsContextPath *>(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<ButsContextTexture *>(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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<SpaceNla *>(slink);
|
||||
|
||||
if (snla->ads == nullptr) {
|
||||
return;
|
||||
}
|
||||
BKE_id_remapper_apply(
|
||||
mappings, reinterpret_cast<ID **>(&snla->ads->filter_grp), ID_REMAP_APPLY_DEFAULT);
|
||||
BKE_id_remapper_apply(
|
||||
mappings, reinterpret_cast<ID **>(&snla->ads->source), ID_REMAP_APPLY_DEFAULT);
|
||||
|
||||
mappings.apply(reinterpret_cast<ID **>(&snla->ads->filter_grp), ID_REMAP_APPLY_DEFAULT);
|
||||
mappings.apply(reinterpret_cast<ID **>(&snla->ads->source), ID_REMAP_APPLY_DEFAULT);
|
||||
}
|
||||
|
||||
static void nla_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<TreeStoreElem *>(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;
|
||||
|
||||
@@ -66,7 +66,8 @@
|
||||
|
||||
static int gather_strip_data_ids_to_null(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
IDRemapper *id_remapper = static_cast<IDRemapper *>(cb_data->user_data);
|
||||
blender::bke::id::IDRemapper &id_remapper = *static_cast<blender::bke::id::IDRemapper *>(
|
||||
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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
/**
|
||||
|
||||
@@ -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<wmWindowManager *>(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);
|
||||
|
||||
Reference in New Issue
Block a user