123 lines
3.5 KiB
C++
123 lines
3.5 KiB
C++
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "DNA_ID.h"
|
|
|
|
#include "BKE_idtype.hh"
|
|
#include "BKE_lib_id.hh"
|
|
#include "BKE_lib_remap.hh"
|
|
|
|
namespace blender::bke::id {
|
|
|
|
void IDRemapper::add(ID *old_id, ID *new_id)
|
|
{
|
|
BLI_assert(old_id != nullptr);
|
|
BLI_assert(new_id == nullptr || this->allow_idtype_mismatch ||
|
|
(GS(old_id->name) == GS(new_id->name)));
|
|
BLI_assert(BKE_idtype_idcode_to_idfilter(GS(old_id->name)) != 0);
|
|
|
|
mappings_.add(old_id, new_id);
|
|
source_types_ |= BKE_idtype_idcode_to_idfilter(GS(old_id->name));
|
|
}
|
|
|
|
void IDRemapper::add_overwrite(ID *old_id, ID *new_id)
|
|
{
|
|
BLI_assert(old_id != nullptr);
|
|
BLI_assert(new_id == nullptr || this->allow_idtype_mismatch ||
|
|
(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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
ID *const *new_id = mappings_.lookup_ptr(*r_id_ptr);
|
|
if (new_id == nullptr) {
|
|
return ID_REMAP_RESULT_SOURCE_UNAVAILABLE;
|
|
}
|
|
|
|
if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) {
|
|
id_us_min(*r_id_ptr);
|
|
}
|
|
|
|
*r_id_ptr = *new_id;
|
|
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 ID_TAG_INDIRECT/ID_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;
|
|
}
|
|
|
|
StringRefNull IDRemapper::result_to_string(const IDRemapperApplyResult result)
|
|
{
|
|
switch (result) {
|
|
case ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE:
|
|
return "not_mappable";
|
|
case ID_REMAP_RESULT_SOURCE_UNAVAILABLE:
|
|
return "unavailable";
|
|
case ID_REMAP_RESULT_SOURCE_UNASSIGNED:
|
|
return "unassigned";
|
|
case ID_REMAP_RESULT_SOURCE_REMAPPED:
|
|
return "remapped";
|
|
}
|
|
BLI_assert_unreachable();
|
|
return "";
|
|
}
|
|
|
|
void IDRemapper::print() const
|
|
{
|
|
this->iter([](ID *old_id, ID *new_id) {
|
|
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);
|
|
}
|
|
});
|
|
}
|
|
|
|
} // namespace blender::bke::id
|