Revert "Performance: Remap multiple items in UI"
This reverts commit 948211679f
.
This commit introduced some regressions in the test suite.
As this change is a core part of blender Bastien and I decided to revert
it as the solution isn't clear and needs more investigation.
The following tests FAILED:
62 - blendfile_liblink (SEGFAULT)
63 - blendfile_library_overrides (SEGFAULT)
It fails in (id_us_ensure_real)
This commit is contained in:
parent
33ba298b5d
commit
460e0a1347
|
@ -38,9 +38,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID;
|
||||
struct IDRemapper;
|
||||
|
||||
/* BKE_libblock_free, delete are declared in BKE_lib_id.h for convenience. */
|
||||
|
||||
/* Also IDRemap->flag. */
|
||||
|
@ -100,19 +97,6 @@ enum {
|
|||
ID_REMAP_FORCE_OBDATA_IN_EDITMODE = 1 << 9,
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace all references in given Main using the given \a mappings
|
||||
*
|
||||
* \note Is preferred over BKE_libblock_remap_locked due to performance.
|
||||
*/
|
||||
void BKE_libblock_remap_multiple_locked(struct Main *bmain,
|
||||
const struct IDRemapper *mappings,
|
||||
const short remap_flags);
|
||||
|
||||
void BKE_libblock_remap_multiple(struct Main *bmain,
|
||||
const struct IDRemapper *mappings,
|
||||
const short 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).
|
||||
|
@ -162,61 +146,12 @@ void BKE_libblock_relink_to_newid(struct Main *bmain, struct ID *id, int remap_f
|
|||
ATTR_NONNULL();
|
||||
|
||||
typedef void (*BKE_library_free_notifier_reference_cb)(const void *);
|
||||
typedef void (*BKE_library_remap_editor_id_reference_cb)(const struct IDRemapper *mappings);
|
||||
typedef void (*BKE_library_remap_editor_id_reference_cb)(struct ID *, struct ID *);
|
||||
|
||||
void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func);
|
||||
void BKE_library_callback_remap_editor_id_reference_set(
|
||||
BKE_library_remap_editor_id_reference_cb func);
|
||||
|
||||
/* IDRemapper */
|
||||
struct IDRemapper;
|
||||
typedef enum IDRemapperApplyResult {
|
||||
/** No remapping rules available for the source. */
|
||||
ID_REMAP_RESULT_SOURCE_UNAVAILABLE,
|
||||
/** Source isn't mappable (e.g. NULL). */
|
||||
ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE,
|
||||
/** Source has been remapped to a new pointer. */
|
||||
ID_REMAP_RESULT_SOURCE_REMAPPED,
|
||||
/** Source has been set to NULL. */
|
||||
ID_REMAP_RESULT_SOURCE_UNASSIGNED,
|
||||
} IDRemapperApplyResult;
|
||||
|
||||
typedef enum IDRemapperApplyOptions {
|
||||
ID_REMAP_APPLY_UPDATE_REFCOUNT = (1 << 0),
|
||||
ID_REMAP_APPLY_ENSURE_REAL = (1 << 1),
|
||||
|
||||
ID_REMAP_APPLY_DEFAULT = 0,
|
||||
} IDRemapperApplyOptions;
|
||||
|
||||
typedef void (*IDRemapperIterFunction)(struct ID *old_id, struct ID *new_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Create a new ID Remapper.
|
||||
*
|
||||
* An ID remapper stores multiple remapping rules.
|
||||
*/
|
||||
struct IDRemapper *BKE_id_remapper_create(void);
|
||||
|
||||
void BKE_id_remapper_clear(struct IDRemapper *id_remapper);
|
||||
bool BKE_id_remapper_is_empty(const struct IDRemapper *id_remapper);
|
||||
/** Free the given ID Remapper. */
|
||||
void BKE_id_remapper_free(struct IDRemapper *id_remapper);
|
||||
/** Add a new remapping. */
|
||||
void BKE_id_remapper_add(struct IDRemapper *id_remapper, struct ID *old_id, struct ID *new_id);
|
||||
|
||||
/**
|
||||
* 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 struct IDRemapper *id_remapper,
|
||||
struct ID **r_id_ptr,
|
||||
IDRemapperApplyOptions options);
|
||||
bool BKE_id_remapper_has_mapping_for(const struct IDRemapper *id_remapper, uint64_t type_filter);
|
||||
void BKE_id_remapper_iter(const struct IDRemapper *id_remapper,
|
||||
IDRemapperIterFunction func,
|
||||
void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,6 @@ struct BlendLibReader;
|
|||
struct BlendWriter;
|
||||
struct Header;
|
||||
struct ID;
|
||||
struct IDRemapper;
|
||||
struct LibraryForeachIDData;
|
||||
struct ListBase;
|
||||
struct Menu;
|
||||
|
@ -118,7 +117,10 @@ typedef struct SpaceType {
|
|||
bContextDataCallback context;
|
||||
|
||||
/* Used when we want to replace an ID by another (or NULL). */
|
||||
void (*id_remap)(struct ScrArea *area, struct SpaceLink *sl, const struct IDRemapper *mappings);
|
||||
void (*id_remap)(struct ScrArea *area,
|
||||
struct SpaceLink *sl,
|
||||
struct ID *old_id,
|
||||
struct ID *new_id);
|
||||
|
||||
int (*space_subtype_get)(struct ScrArea *area);
|
||||
void (*space_subtype_set)(struct ScrArea *area, int value);
|
||||
|
|
|
@ -179,7 +179,6 @@ set(SRC
|
|||
intern/lib_id.c
|
||||
intern/lib_id_delete.c
|
||||
intern/lib_id_eval.c
|
||||
intern/lib_id_remapper.cc
|
||||
intern/lib_override.c
|
||||
intern/lib_query.c
|
||||
intern/lib_remap.c
|
||||
|
@ -824,7 +823,6 @@ if(WITH_GTESTS)
|
|||
intern/idprop_serialize_test.cc
|
||||
intern/lattice_deform_test.cc
|
||||
intern/layer_test.cc
|
||||
intern/lib_id_remapper_test.cc
|
||||
intern/lib_id_test.cc
|
||||
intern/lib_remap_test.cc
|
||||
intern/tracking_test.cc
|
||||
|
|
|
@ -154,10 +154,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
|
|||
}
|
||||
|
||||
if (remap_editor_id_reference_cb) {
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
BKE_id_remapper_add(remapper, id, NULL);
|
||||
remap_editor_id_reference_cb(remapper);
|
||||
BKE_id_remapper_free(remapper);
|
||||
remap_editor_id_reference_cb(id, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,40 +292,32 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
* 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. */
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
for (i = 0; i < base_count; i++) {
|
||||
ListBase *lb = lbarray[i];
|
||||
ID *id, *id_next;
|
||||
BKE_id_remapper_clear(remapper);
|
||||
|
||||
for (id = lb->first; id; id = id_next) {
|
||||
id_next = id->next;
|
||||
/* NOTE: in case we delete a library, we also delete all its datablocks! */
|
||||
if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
|
||||
id->tag |= tag;
|
||||
BKE_id_remapper_add(remapper, id, NULL);
|
||||
|
||||
/* Will tag 'never NULL' users of this ID too.
|
||||
* Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
|
||||
* (and proxy!) links, this can lead to nasty crashing here in second,
|
||||
* actual deleting loop.
|
||||
* 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_locked(bmain,
|
||||
id,
|
||||
NULL,
|
||||
(ID_REMAP_FLAG_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS));
|
||||
}
|
||||
}
|
||||
|
||||
if (BKE_id_remapper_is_empty(remapper)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Will tag 'never NULL' users of this ID too.
|
||||
* Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
|
||||
* (and proxy!) links, this can lead to nasty crashing here in second,
|
||||
* actual deleting loop.
|
||||
* 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,
|
||||
remapper,
|
||||
(ID_REMAP_FLAG_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS));
|
||||
}
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
||||
BKE_main_unlock(bmain);
|
||||
|
||||
/* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones,
|
||||
|
|
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2022 by Blender Foundation.
|
||||
*/
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
|
||||
using IDTypeFilter = uint64_t;
|
||||
|
||||
namespace blender::bke::id::remapper {
|
||||
struct IDRemapper {
|
||||
private:
|
||||
Map<ID *, ID *> mappings;
|
||||
IDTypeFilter source_types = 0;
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
mappings.clear();
|
||||
source_types = 0;
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return mappings.is_empty();
|
||||
}
|
||||
|
||||
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);
|
||||
source_types |= BKE_idtype_idcode_to_idfilter(GS(old_id->name));
|
||||
}
|
||||
|
||||
bool contains_mappings_for_any(IDTypeFilter filter) const
|
||||
{
|
||||
return (source_types & filter) != 0;
|
||||
}
|
||||
|
||||
IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options) 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 (*r_id_ptr == nullptr) {
|
||||
return ID_REMAP_RESULT_SOURCE_UNASSIGNED;
|
||||
}
|
||||
|
||||
if (options & ID_REMAP_APPLY_UPDATE_REFCOUNT) {
|
||||
id_us_plus(*r_id_ptr);
|
||||
}
|
||||
|
||||
if (options & ID_REMAP_APPLY_ENSURE_REAL) {
|
||||
id_us_ensure_real(*r_id_ptr);
|
||||
}
|
||||
return ID_REMAP_RESULT_SOURCE_REMAPPED;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/** \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));
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
IDRemapper *BKE_id_remapper_create(void)
|
||||
{
|
||||
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(struct IDRemapper *id_remapper)
|
||||
{
|
||||
blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
|
||||
remapper->clear();
|
||||
}
|
||||
|
||||
bool BKE_id_remapper_is_empty(const struct 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);
|
||||
}
|
||||
|
||||
bool BKE_id_remapper_has_mapping_for(const struct 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_apply(const IDRemapper *id_remapper,
|
||||
ID **r_id_ptr,
|
||||
const IDRemapperApplyOptions options)
|
||||
{
|
||||
const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
|
||||
return remapper->apply(r_id_ptr, options);
|
||||
}
|
||||
|
||||
void BKE_id_remapper_iter(const struct IDRemapper *id_remapper,
|
||||
IDRemapperIterFunction func,
|
||||
void *user_data)
|
||||
{
|
||||
const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
|
||||
remapper->iter(func, user_data);
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2022 by Blender Foundation.
|
||||
*/
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include "BKE_lib_remap.h"
|
||||
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
namespace blender::bke::id::remapper::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);
|
||||
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);
|
||||
EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE);
|
||||
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
||||
TEST(lib_id_remapper, mapped)
|
||||
{
|
||||
ID id1;
|
||||
ID id2;
|
||||
ID *idp = &id1;
|
||||
BLI_strncpy(id1.name, "OB1", sizeof(id1.name));
|
||||
BLI_strncpy(id2.name, "OB2", sizeof(id2.name));
|
||||
|
||||
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);
|
||||
EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_REMAPPED);
|
||||
EXPECT_EQ(idp, &id2);
|
||||
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
||||
TEST(lib_id_remapper, unassigned)
|
||||
{
|
||||
ID id1;
|
||||
ID *idp = &id1;
|
||||
|
||||
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);
|
||||
EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED);
|
||||
EXPECT_EQ(idp, nullptr);
|
||||
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
||||
} // namespace blender::bke::id::remapper::tests
|
|
@ -1121,45 +1121,6 @@ void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadRepor
|
|||
}
|
||||
}
|
||||
|
||||
static void lib_override_library_remap(Main *bmain,
|
||||
const ID *id_root_reference,
|
||||
GHash *linkedref_to_old_override)
|
||||
{
|
||||
ID *id;
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
|
||||
if (id->tag & LIB_TAG_DOIT && id->newid != NULL && id->lib == id_root_reference->lib) {
|
||||
ID *id_override_new = id->newid;
|
||||
ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id);
|
||||
if (id_override_old == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_id_remapper_add(remapper, id_override_old, id_override_new);
|
||||
/* Remap no-main override IDs we just created too. */
|
||||
GHashIterator linkedref_to_old_override_iter;
|
||||
GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
|
||||
ID *id_override_old_iter = BLI_ghashIterator_getValue(&linkedref_to_old_override_iter);
|
||||
if ((id_override_old_iter->tag & LIB_TAG_NO_MAIN) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_libblock_relink_ex(bmain,
|
||||
id_override_old_iter,
|
||||
id_override_old,
|
||||
id_override_new,
|
||||
ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
/* Remap all IDs to use the new override. */
|
||||
BKE_libblock_remap_multiple(bmain, remapper, 0);
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
||||
static bool lib_override_library_resync(Main *bmain,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
|
@ -1351,9 +1312,32 @@ static bool lib_override_library_resync(Main *bmain,
|
|||
}
|
||||
FOREACH_MAIN_LISTBASE_END;
|
||||
|
||||
/* We remap old to new override usages in a separate loop, after all new overrides have
|
||||
/* We need to remap old to new override usages in a separate loop, after all new overrides have
|
||||
* been added to Main. */
|
||||
lib_override_library_remap(bmain, id_root_reference, linkedref_to_old_override);
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (id->tag & LIB_TAG_DOIT && id->newid != NULL && id->lib == id_root_reference->lib) {
|
||||
ID *id_override_new = id->newid;
|
||||
ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id);
|
||||
|
||||
if (id_override_old != NULL) {
|
||||
/* Remap all IDs to use the new override. */
|
||||
BKE_libblock_remap(bmain, id_override_old, id_override_new, 0);
|
||||
/* Remap no-main override IDs we just created too. */
|
||||
GHashIterator linkedref_to_old_override_iter;
|
||||
GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
|
||||
ID *id_override_old_iter = BLI_ghashIterator_getValue(&linkedref_to_old_override_iter);
|
||||
if (id_override_old_iter->tag & LIB_TAG_NO_MAIN) {
|
||||
BKE_libblock_relink_ex(bmain,
|
||||
id_override_old_iter,
|
||||
id_override_old,
|
||||
id_override_new,
|
||||
ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
BKE_main_collection_sync(bmain);
|
||||
|
||||
|
|
|
@ -510,18 +510,11 @@ static void libblock_remap_data(
|
|||
#endif
|
||||
}
|
||||
|
||||
typedef struct LibblockRemapMultipleUserData {
|
||||
Main *bmain;
|
||||
short remap_flags;
|
||||
} LibBlockRemapMultipleUserData;
|
||||
|
||||
static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_data)
|
||||
void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
|
||||
{
|
||||
LibBlockRemapMultipleUserData *data = user_data;
|
||||
Main *bmain = data->bmain;
|
||||
const short remap_flags = data->remap_flags;
|
||||
|
||||
IDRemap id_remap_data;
|
||||
ID *old_id = old_idv;
|
||||
ID *new_id = new_idv;
|
||||
int skipped_direct, skipped_refcounted;
|
||||
|
||||
BLI_assert(old_id != NULL);
|
||||
|
@ -534,6 +527,13 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_
|
|||
free_notifier_reference_cb(old_id);
|
||||
}
|
||||
|
||||
/* We assume editors do not hold references to their IDs... This is false in some cases
|
||||
* (Image is especially tricky here),
|
||||
* editors' code is to handle refcount (id->us) itself then. */
|
||||
if (remap_editor_id_reference_cb) {
|
||||
remap_editor_id_reference_cb(old_id, new_id);
|
||||
}
|
||||
|
||||
skipped_direct = id_remap_data.skipped_direct;
|
||||
skipped_refcounted = id_remap_data.skipped_refcounted;
|
||||
|
||||
|
@ -606,41 +606,6 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_
|
|||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
||||
void BKE_libblock_remap_multiple_locked(Main *bmain,
|
||||
const struct IDRemapper *mappings,
|
||||
const short remap_flags)
|
||||
{
|
||||
if (BKE_id_remapper_is_empty(mappings)) {
|
||||
/* Early exit nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
LibBlockRemapMultipleUserData user_data;
|
||||
user_data.bmain = bmain;
|
||||
user_data.remap_flags = remap_flags;
|
||||
BKE_id_remapper_iter(mappings, 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),
|
||||
* editors' code is to handle refcount (id->us) itself then. */
|
||||
if (remap_editor_id_reference_cb) {
|
||||
remap_editor_id_reference_cb(mappings);
|
||||
}
|
||||
|
||||
/* Full rebuild of DEG! */
|
||||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
||||
void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
|
||||
{
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
ID *old_id = old_idv;
|
||||
ID *new_id = new_idv;
|
||||
BKE_id_remapper_add(remapper, 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 short remap_flags)
|
||||
{
|
||||
BKE_main_lock(bmain);
|
||||
|
@ -650,17 +615,6 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short r
|
|||
BKE_main_unlock(bmain);
|
||||
}
|
||||
|
||||
void BKE_libblock_remap_multiple(Main *bmain,
|
||||
const struct IDRemapper *mappings,
|
||||
const short remap_flags)
|
||||
{
|
||||
BKE_main_lock(bmain);
|
||||
|
||||
BKE_libblock_remap_multiple_locked(bmain, mappings, remap_flags);
|
||||
|
||||
BKE_main_unlock(bmain);
|
||||
}
|
||||
|
||||
void BKE_libblock_unlink(Main *bmain,
|
||||
void *idv,
|
||||
const bool do_flag_never_null,
|
||||
|
|
|
@ -33,7 +33,6 @@ extern "C" {
|
|||
struct GPUBatch;
|
||||
struct Main;
|
||||
struct bContext;
|
||||
struct IDRemapper;
|
||||
|
||||
/* ed_util.c */
|
||||
|
||||
|
@ -61,13 +60,10 @@ bool ED_editors_flush_edits(struct Main *bmain);
|
|||
*
|
||||
* \param new_id: may be NULL to unlink \a old_id.
|
||||
*/
|
||||
void ED_spacedata_id_remap_single(struct ScrArea *area,
|
||||
struct SpaceLink *sl,
|
||||
struct ID *old_id,
|
||||
struct ID *new_id);
|
||||
void ED_spacedata_id_remap(struct ScrArea *area,
|
||||
struct SpaceLink *sl,
|
||||
const struct IDRemapper *mappings);
|
||||
struct ID *old_id,
|
||||
struct ID *new_id);
|
||||
|
||||
void ED_operatortypes_edutils(void);
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
|
@ -815,15 +814,20 @@ 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 *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void action_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
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);
|
||||
if ((ID *)sact->action == old_id) {
|
||||
sact->action = (bAction *)new_id;
|
||||
}
|
||||
|
||||
if ((ID *)sact->ads.filter_grp == old_id) {
|
||||
sact->ads.filter_grp = (Collection *)new_id;
|
||||
}
|
||||
if ((ID *)sact->ads.source == old_id) {
|
||||
sact->ads.source = new_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_gpencil_modifier.h" /* Types for registering panels. */
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_shader_fx.h"
|
||||
|
@ -861,53 +860,54 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params)
|
|||
}
|
||||
}
|
||||
|
||||
static void buttons_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void buttons_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceProperties *sbuts = (SpaceProperties *)slink;
|
||||
|
||||
if (BKE_id_remapper_apply(mappings, &sbuts->pinid, ID_REMAP_APPLY_DEFAULT) ==
|
||||
ID_REMAP_RESULT_SOURCE_UNASSIGNED) {
|
||||
sbuts->flag &= ~SB_PIN_CONTEXT;
|
||||
if (sbuts->pinid == old_id) {
|
||||
sbuts->pinid = new_id;
|
||||
if (new_id == NULL) {
|
||||
sbuts->flag &= ~SB_PIN_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
if (sbuts->path) {
|
||||
ButsContextPath *path = 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)) {
|
||||
case ID_REMAP_RESULT_SOURCE_UNASSIGNED: {
|
||||
if (i == 0) {
|
||||
MEM_SAFE_FREE(sbuts->path);
|
||||
}
|
||||
else {
|
||||
memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
|
||||
path->len = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_REMAP_RESULT_SOURCE_REMAPPED: {
|
||||
RNA_id_pointer_create(path->ptr[i].owner_id, &path->ptr[i]);
|
||||
/* There is no easy way to check/make path downwards valid, just nullify it.
|
||||
* Next redraw will rebuild this anyway. */
|
||||
i++;
|
||||
memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
|
||||
path->len = i;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE:
|
||||
case ID_REMAP_RESULT_SOURCE_UNAVAILABLE: {
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < path->len; i++) {
|
||||
if (path->ptr[i].owner_id == old_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == path->len) {
|
||||
/* pass */
|
||||
}
|
||||
else if (new_id == NULL) {
|
||||
if (i == 0) {
|
||||
MEM_SAFE_FREE(sbuts->path);
|
||||
}
|
||||
else {
|
||||
memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
|
||||
path->len = i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RNA_id_pointer_create(new_id, &path->ptr[i]);
|
||||
/* There is no easy way to check/make path downwards valid, just nullify it.
|
||||
* Next redraw will rebuild this anyway. */
|
||||
i++;
|
||||
memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
|
||||
path->len = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (sbuts->texuser) {
|
||||
ButsContextTexture *ct = sbuts->texuser;
|
||||
BKE_id_remapper_apply(mappings, (ID **)&ct->texture, ID_REMAP_APPLY_DEFAULT);
|
||||
if ((ID *)ct->texture == old_id) {
|
||||
ct->texture = (Tex *)new_id;
|
||||
}
|
||||
BLI_freelistN(&ct->users);
|
||||
ct->user = NULL;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
@ -1318,18 +1317,23 @@ static void clip_properties_region_listener(const wmRegionListenerParams *params
|
|||
|
||||
/********************* registration ********************/
|
||||
|
||||
static void clip_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void clip_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceClip *sclip = (SpaceClip *)slink;
|
||||
|
||||
if (!BKE_id_remapper_has_mapping_for(mappings, FILTER_ID_MC | FILTER_ID_MSK)) {
|
||||
if (!ELEM(GS(old_id->name), ID_MC, 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);
|
||||
if ((ID *)sclip->clip == old_id) {
|
||||
sclip->clip = (MovieClip *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
|
||||
if ((ID *)sclip->mask_info.mask == old_id) {
|
||||
sclip->mask_info.mask = (Mask *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
}
|
||||
|
||||
void ED_spacetype_clip(void)
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "BKE_appdir.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
|
@ -990,7 +989,7 @@ static int /*eContextResult*/ file_context(const bContext *C,
|
|||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
}
|
||||
|
||||
static void file_id_remap(ScrArea *area, SpaceLink *sl, const struct IDRemapper *UNUSED(mappings))
|
||||
static void file_id_remap(ScrArea *area, SpaceLink *sl, ID *UNUSED(old_id), ID *UNUSED(new_id))
|
||||
{
|
||||
SpaceFile *sfile = (SpaceFile *)sl;
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
|
@ -797,17 +796,18 @@ static void graph_refresh(const bContext *C, ScrArea *area)
|
|||
graph_refresh_fcurve_colors(C);
|
||||
}
|
||||
|
||||
static void graph_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void graph_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
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);
|
||||
if (sgraph->ads) {
|
||||
if ((ID *)sgraph->ads->filter_grp == old_id) {
|
||||
sgraph->ads->filter_grp = (Collection *)new_id;
|
||||
}
|
||||
if ((ID *)sgraph->ads->source == old_id) {
|
||||
sgraph->ads->source = new_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int graph_space_subtype_get(ScrArea *area)
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
@ -984,19 +983,29 @@ static void image_header_region_listener(const wmRegionListenerParams *params)
|
|||
}
|
||||
}
|
||||
|
||||
static void image_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void image_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceImage *simg = (SpaceImage *)slink;
|
||||
|
||||
if (!BKE_id_remapper_has_mapping_for(mappings, FILTER_ID_IM | FILTER_ID_GD | FILTER_ID_MSK)) {
|
||||
if (!ELEM(GS(old_id->name), ID_IM, ID_GD, 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);
|
||||
if ((ID *)simg->image == old_id) {
|
||||
simg->image = (Image *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
|
||||
if ((ID *)simg->gpd == old_id) {
|
||||
simg->gpd = (bGPdata *)new_id;
|
||||
id_us_min(old_id);
|
||||
id_us_plus(new_id);
|
||||
}
|
||||
|
||||
if ((ID *)simg->mask_info.mask == old_id) {
|
||||
simg->mask_info.mask = (Mask *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
|
@ -578,17 +577,18 @@ static void nla_listener(const wmSpaceTypeListenerParams *params)
|
|||
}
|
||||
}
|
||||
|
||||
static void nla_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void nla_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceNla *snla = (SpaceNla *)slink;
|
||||
|
||||
if (snla->ads == NULL) {
|
||||
return;
|
||||
if (snla->ads) {
|
||||
if ((ID *)snla->ads->filter_grp == old_id) {
|
||||
snla->ads->filter_grp = (Collection *)new_id;
|
||||
}
|
||||
if ((ID *)snla->ads->source == old_id) {
|
||||
snla->ads->source = new_id;
|
||||
}
|
||||
}
|
||||
BKE_id_remapper_apply(mappings, (ID **)&snla->ads->filter_grp, ID_REMAP_APPLY_DEFAULT);
|
||||
BKE_id_remapper_apply(mappings, (ID **)&snla->ads->source, ID_REMAP_APPLY_DEFAULT);
|
||||
}
|
||||
|
||||
void ED_spacetype_nla(void)
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
|
@ -897,63 +896,71 @@ static void node_widgets()
|
|||
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
|
||||
}
|
||||
|
||||
static void node_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceNode *snode = (SpaceNode *)slink;
|
||||
|
||||
if (ELEM(BKE_id_remapper_apply(mappings, &snode->id, ID_REMAP_APPLY_DEFAULT),
|
||||
ID_REMAP_RESULT_SOURCE_REMAPPED,
|
||||
ID_REMAP_RESULT_SOURCE_UNASSIGNED)) {
|
||||
if (snode->id == old_id) {
|
||||
/* nasty DNA logic for SpaceNode:
|
||||
* ideally should be handled by editor code, but would be bad level call
|
||||
*/
|
||||
BLI_freelistN(&snode->treepath);
|
||||
|
||||
/* XXX Untested in case new_id != nullptr... */
|
||||
snode->id = new_id;
|
||||
snode->from = nullptr;
|
||||
snode->nodetree = nullptr;
|
||||
snode->edittree = nullptr;
|
||||
}
|
||||
if (BKE_id_remapper_apply(mappings, &snode->from, ID_REMAP_APPLY_DEFAULT) ==
|
||||
ID_REMAP_RESULT_SOURCE_UNASSIGNED) {
|
||||
snode->flag &= ~SNODE_PIN;
|
||||
}
|
||||
BKE_id_remapper_apply(mappings, (ID **)&snode->gpd, ID_REMAP_APPLY_UPDATE_REFCOUNT);
|
||||
|
||||
if (!BKE_id_remapper_has_mapping_for(mappings, FILTER_ID_NT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bNodeTreePath *path, *path_next;
|
||||
for (path = (bNodeTreePath *)snode->treepath.first; path; path = path->next) {
|
||||
BKE_id_remapper_apply(mappings, (ID **)&path->nodetree, ID_REMAP_APPLY_ENSURE_REAL);
|
||||
if (path == snode->treepath.first) {
|
||||
/* first nodetree in path is same as snode->nodetree */
|
||||
snode->nodetree = path->nodetree;
|
||||
}
|
||||
if (path->nodetree == nullptr) {
|
||||
break;
|
||||
else if (GS(old_id->name) == ID_OB) {
|
||||
if (snode->from == old_id) {
|
||||
if (new_id == nullptr) {
|
||||
snode->flag &= ~SNODE_PIN;
|
||||
}
|
||||
snode->from = new_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* remaining path entries are invalid, remove */
|
||||
for (; path; path = path_next) {
|
||||
path_next = path->next;
|
||||
|
||||
BLI_remlink(&snode->treepath, path);
|
||||
MEM_freeN(path);
|
||||
else if (GS(old_id->name) == ID_GD) {
|
||||
if ((ID *)snode->gpd == old_id) {
|
||||
snode->gpd = (bGPdata *)new_id;
|
||||
id_us_min(old_id);
|
||||
id_us_plus(new_id);
|
||||
}
|
||||
}
|
||||
else if (GS(old_id->name) == ID_NT) {
|
||||
bNodeTreePath *path, *path_next;
|
||||
|
||||
/* edittree is just the last in the path,
|
||||
* set this directly since the path may have been shortened above */
|
||||
if (snode->treepath.last) {
|
||||
path = (bNodeTreePath *)snode->treepath.last;
|
||||
snode->edittree = path->nodetree;
|
||||
}
|
||||
else {
|
||||
snode->edittree = nullptr;
|
||||
for (path = (bNodeTreePath *)snode->treepath.first; path; path = path->next) {
|
||||
if ((ID *)path->nodetree == old_id) {
|
||||
path->nodetree = (bNodeTree *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
if (path == snode->treepath.first) {
|
||||
/* first nodetree in path is same as snode->nodetree */
|
||||
snode->nodetree = path->nodetree;
|
||||
}
|
||||
if (path->nodetree == nullptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* remaining path entries are invalid, remove */
|
||||
for (; path; path = path_next) {
|
||||
path_next = path->next;
|
||||
|
||||
BLI_remlink(&snode->treepath, path);
|
||||
MEM_freeN(path);
|
||||
}
|
||||
|
||||
/* edittree is just the last in the path,
|
||||
* set this directly since the path may have been shortened above */
|
||||
if (snode->treepath.last) {
|
||||
path = (bNodeTreePath *)snode->treepath.last;
|
||||
snode->edittree = path->nodetree;
|
||||
}
|
||||
else {
|
||||
snode->edittree = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_outliner_treehash.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
|
@ -406,49 +405,45 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
|
|||
return (SpaceLink *)space_outliner_new;
|
||||
}
|
||||
|
||||
static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRemapper *mappings)
|
||||
static void outliner_id_remap(ScrArea *area, SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceOutliner *space_outliner = (SpaceOutliner *)slink;
|
||||
|
||||
BKE_id_remapper_apply(mappings, (ID **)&space_outliner->search_tse.id, ID_REMAP_APPLY_DEFAULT);
|
||||
|
||||
if (!space_outliner->treestore) {
|
||||
return;
|
||||
/* Some early out checks. */
|
||||
if (!TREESTORE_ID_TYPE(old_id)) {
|
||||
return; /* ID type is not used by outliner. */
|
||||
}
|
||||
|
||||
TreeStoreElem *tselem;
|
||||
BLI_mempool_iter iter;
|
||||
bool changed = false;
|
||||
bool unassigned = false;
|
||||
if (space_outliner->search_tse.id == old_id) {
|
||||
space_outliner->search_tse.id = new_id;
|
||||
}
|
||||
|
||||
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)) {
|
||||
case ID_REMAP_RESULT_SOURCE_REMAPPED:
|
||||
if (space_outliner->treestore) {
|
||||
TreeStoreElem *tselem;
|
||||
BLI_mempool_iter iter;
|
||||
bool changed = false;
|
||||
|
||||
BLI_mempool_iternew(space_outliner->treestore, &iter);
|
||||
while ((tselem = static_cast<TreeStoreElem *>(BLI_mempool_iterstep(&iter)))) {
|
||||
if (tselem->id == old_id) {
|
||||
tselem->id = new_id;
|
||||
changed = true;
|
||||
break;
|
||||
case ID_REMAP_RESULT_SOURCE_UNASSIGNED:
|
||||
changed = true;
|
||||
unassigned = true;
|
||||
break;
|
||||
case ID_REMAP_RESULT_SOURCE_UNAVAILABLE:
|
||||
case ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that the Outliner may not be the active editor of the area, and hence not initialized.
|
||||
* So runtime data might not have been created yet. */
|
||||
if (space_outliner->runtime && space_outliner->runtime->treehash && changed) {
|
||||
/* rebuild hash table, because it depends on ids too */
|
||||
/* postpone a full rebuild because this can be called many times on-free */
|
||||
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
|
||||
/* Note that the Outliner may not be the active editor of the area, and hence not initialized.
|
||||
* So runtime data might not have been created yet. */
|
||||
if (space_outliner->runtime && space_outliner->runtime->treehash && changed) {
|
||||
/* rebuild hash table, because it depends on ids too */
|
||||
/* postpone a full rebuild because this can be called many times on-free */
|
||||
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
|
||||
|
||||
if (unassigned) {
|
||||
/* Redraw is needed when removing data for multiple outlines show the same data.
|
||||
* without this, the stale data won't get fully flushed when this outliner
|
||||
* is not the active outliner the user is interacting with. See T85976. */
|
||||
ED_area_tag_redraw(area);
|
||||
if (new_id == nullptr) {
|
||||
/* Redraw is needed when removing data for multiple outlines show the same data.
|
||||
* without this, the stale data won't get fully flushed when this outliner
|
||||
* is not the active outliner the user is interacting with. See T85976. */
|
||||
ED_area_tag_redraw(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_sequencer_offscreen.h"
|
||||
|
||||
|
@ -989,12 +988,19 @@ static void sequencer_buttons_region_listener(const wmRegionListenerParams *para
|
|||
}
|
||||
}
|
||||
|
||||
static void sequencer_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void sequencer_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceSeq *sseq = (SpaceSeq *)slink;
|
||||
BKE_id_remapper_apply(mappings, (ID **)&sseq->gpd, ID_REMAP_APPLY_DEFAULT);
|
||||
|
||||
if (!ELEM(GS(old_id->name), ID_GD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ID *)sseq->gpd == old_id) {
|
||||
sseq->gpd = (bGPdata *)new_id;
|
||||
id_us_min(old_id);
|
||||
id_us_plus(new_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************* */
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
@ -172,23 +171,21 @@ static void spreadsheet_keymap(wmKeyConfig *keyconf)
|
|||
WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
|
||||
}
|
||||
|
||||
static void spreadsheet_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const IDRemapper *mappings)
|
||||
static void spreadsheet_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink;
|
||||
LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
|
||||
if (context->type != SPREADSHEET_CONTEXT_OBJECT) {
|
||||
continue;
|
||||
if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
|
||||
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context;
|
||||
if ((ID *)object_context->object == old_id) {
|
||||
if (new_id && GS(new_id->name) == ID_OB) {
|
||||
object_context->object = (Object *)new_id;
|
||||
}
|
||||
else {
|
||||
object_context->object = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context;
|
||||
|
||||
if (object_context->object != nullptr && GS(object_context->object->id.name) != ID_OB) {
|
||||
object_context->object = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_id_remapper_apply(mappings, ((ID **)&object_context->object), ID_REMAP_APPLY_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
@ -402,12 +401,18 @@ static void text_properties_region_draw(const bContext *C, ARegion *region)
|
|||
}
|
||||
}
|
||||
|
||||
static void text_id_remap(ScrArea *UNUSED(area),
|
||||
SpaceLink *slink,
|
||||
const struct IDRemapper *mappings)
|
||||
static void text_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceText *stext = (SpaceText *)slink;
|
||||
BKE_id_remapper_apply(mappings, (ID **)&stext->text, ID_REMAP_APPLY_ENSURE_REAL);
|
||||
|
||||
if (!ELEM(GS(old_id->name), ID_TXT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ID *)stext->text == old_id) {
|
||||
stext->text = (Text *)new_id;
|
||||
id_us_ensure_real(new_id);
|
||||
}
|
||||
}
|
||||
|
||||
/********************* registration ********************/
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "BKE_idprop.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
@ -1814,54 +1813,50 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
|
|||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
}
|
||||
|
||||
static void view3d_id_remap_v3d_ob_centers(View3D *v3d, const struct IDRemapper *mappings)
|
||||
{
|
||||
if (BKE_id_remapper_apply(mappings, (ID **)&v3d->ob_center, ID_REMAP_APPLY_DEFAULT) ==
|
||||
ID_REMAP_RESULT_SOURCE_UNASSIGNED) {
|
||||
/* Otherwise, bonename may remain valid...
|
||||
* We could be smart and check this, too? */
|
||||
v3d->ob_center_bone[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void view3d_id_remap_v3d(ScrArea *area,
|
||||
SpaceLink *slink,
|
||||
View3D *v3d,
|
||||
const struct IDRemapper *mappings,
|
||||
const bool is_local)
|
||||
static void view3d_id_remap(ScrArea *area, SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
{
|
||||
View3D *v3d;
|
||||
ARegion *region;
|
||||
if (BKE_id_remapper_apply(mappings, (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 */
|
||||
ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
|
||||
&slink->regionbase;
|
||||
for (region = regionbase->first; region; region = region->next) {
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd :
|
||||
region->regiondata;
|
||||
if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
|
||||
rv3d->persp = RV3D_PERSP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool is_local = false;
|
||||
|
||||
static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRemapper *mappings)
|
||||
{
|
||||
|
||||
if (!BKE_id_remapper_has_mapping_for(
|
||||
mappings, FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_IM | FILTER_ID_MC)) {
|
||||
if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
|
||||
return;
|
||||
}
|
||||
|
||||
View3D *view3d = (View3D *)slink;
|
||||
view3d_id_remap_v3d(area, slink, view3d, mappings, false);
|
||||
view3d_id_remap_v3d_ob_centers(view3d, mappings);
|
||||
if (view3d->localvd != NULL) {
|
||||
/* Object centers in local-view aren't used, see: T52663 */
|
||||
view3d_id_remap_v3d(area, slink, view3d->localvd, mappings, true);
|
||||
for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
|
||||
if ((ID *)v3d->camera == old_id) {
|
||||
v3d->camera = (Object *)new_id;
|
||||
if (!new_id) {
|
||||
/* 3D view might be inactive, in that case needs to use slink->regionbase */
|
||||
ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
|
||||
&slink->regionbase;
|
||||
for (region = regionbase->first; region; region = region->next) {
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd :
|
||||
region->regiondata;
|
||||
if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
|
||||
rv3d->persp = RV3D_PERSP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Values in local-view aren't used, see: T52663 */
|
||||
if (is_local == false) {
|
||||
if ((ID *)v3d->ob_center == old_id) {
|
||||
v3d->ob_center = (Object *)new_id;
|
||||
/* Otherwise, bonename may remain valid...
|
||||
* We could be smart and check this, too? */
|
||||
if (new_id == NULL) {
|
||||
v3d->ob_center_bone[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_local) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_multires.h"
|
||||
|
@ -435,27 +434,11 @@ void unpack_menu(bContext *C,
|
|||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
|
||||
void ED_spacedata_id_remap(struct ScrArea *area,
|
||||
struct SpaceLink *sl,
|
||||
const struct IDRemapper *mappings)
|
||||
{
|
||||
SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
|
||||
if (st && st->id_remap) {
|
||||
st->id_remap(area, sl, mappings);
|
||||
}
|
||||
}
|
||||
|
||||
void ED_spacedata_id_remap_single(struct ScrArea *area,
|
||||
struct SpaceLink *sl,
|
||||
ID *old_id,
|
||||
ID *new_id)
|
||||
void ED_spacedata_id_remap(struct ScrArea *area, struct SpaceLink *sl, ID *old_id, ID *new_id)
|
||||
{
|
||||
SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
|
||||
|
||||
if (st && st->id_remap) {
|
||||
struct IDRemapper *mappings = BKE_id_remapper_create();
|
||||
BKE_id_remapper_add(mappings, old_id, new_id);
|
||||
st->id_remap(area, sl, mappings);
|
||||
BKE_id_remapper_free(mappings);
|
||||
st->id_remap(area, sl, old_id, new_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ struct GHashIterator;
|
|||
struct GPUViewport;
|
||||
struct ID;
|
||||
struct IDProperty;
|
||||
struct IDRemapper;
|
||||
struct ImBuf;
|
||||
struct ImageFormatData;
|
||||
struct Main;
|
||||
|
@ -472,7 +471,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 struct IDRemapper *mappings);
|
||||
void WM_main_remap_editor_id_reference(struct ID *old_id, struct ID *new_id);
|
||||
|
||||
/* reports */
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
|
@ -313,39 +312,28 @@ void WM_main_remove_notifier_reference(const void *reference)
|
|||
}
|
||||
}
|
||||
|
||||
static void wm_main_remap_assetlist(ID *old_id, ID *new_id, void *UNUSED(user_data))
|
||||
{
|
||||
ED_assetlist_storage_id_remap(old_id, new_id);
|
||||
}
|
||||
|
||||
static void wm_main_remap_msgbus_notify(ID *old_id, ID *new_id, void *user_data)
|
||||
{
|
||||
struct wmMsgBus *mbus = user_data;
|
||||
if (new_id != NULL) {
|
||||
WM_msg_id_update(mbus, old_id, new_id);
|
||||
}
|
||||
else {
|
||||
WM_msg_id_remove(mbus, old_id);
|
||||
}
|
||||
}
|
||||
|
||||
void WM_main_remap_editor_id_reference(const struct IDRemapper *mappings)
|
||||
void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id)
|
||||
{
|
||||
Main *bmain = G_MAIN;
|
||||
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
ED_spacedata_id_remap(area, sl, mappings);
|
||||
ED_spacedata_id_remap(area, sl, old_id, new_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BKE_id_remapper_iter(mappings, wm_main_remap_assetlist, NULL);
|
||||
ED_assetlist_storage_id_remap(old_id, new_id);
|
||||
|
||||
wmWindowManager *wm = bmain->wm.first;
|
||||
if (wm && wm->message_bus) {
|
||||
BKE_id_remapper_iter(mappings, wm_main_remap_msgbus_notify, wm->message_bus);
|
||||
struct wmMsgBus *mbus = wm->message_bus;
|
||||
if (new_id != NULL) {
|
||||
WM_msg_id_update(mbus, old_id, new_id);
|
||||
}
|
||||
else {
|
||||
WM_msg_id_remove(mbus, old_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ void WM_init(bContext *C, int argc, const char **argv)
|
|||
BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove);
|
||||
BKE_region_callback_refresh_tag_gizmomap_set(WM_gizmomap_tag_refresh);
|
||||
BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference);
|
||||
BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap_single);
|
||||
BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap);
|
||||
DEG_editors_set_update_cb(ED_render_id_flush_update, ED_render_scene_update);
|
||||
|
||||
ED_spacetypes_init();
|
||||
|
|
Loading…
Reference in New Issue