forked from bartvdbraak/blender
readfile: optimization for undo
Was using O(n^2) lookup on ID's with undo. This caused undo to hang with 1000's of data-blocks (especially with heavy scenes & outliner-space, which doesn't even need to be visible to cause a slow-down). Internally this uses a ghash per id-type, which is lazy-initialized. Each key uses the name and library since there may be name collisions between libraries. Developer Notes: - Adds small `BKE_main_idmap_*` API. - Needed to change linking order for this to build.
This commit is contained in:
parent
3054e33d67
commit
441a440cbb
@ -552,11 +552,11 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_modifiers
|
||||
bf_bmesh
|
||||
bf_gpu
|
||||
bf_blenloader
|
||||
bf_blenkernel
|
||||
bf_physics
|
||||
bf_nodes
|
||||
bf_rna
|
||||
bf_blenloader
|
||||
bf_imbuf
|
||||
bf_blenlib
|
||||
bf_depsgraph
|
||||
|
50
source/blender/blenkernel/BKE_library_idmap.h
Normal file
50
source/blender/blenkernel/BKE_library_idmap.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef __BKE_LIBRARY_IDMAP_H__
|
||||
#define __BKE_LIBRARY_IDMAP_H__
|
||||
|
||||
/** \file BKE_library_idmap.h
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
struct ID;
|
||||
struct Main;
|
||||
struct IDNameLib_Map;
|
||||
|
||||
struct IDNameLib_Map *BKE_main_idmap_create(
|
||||
struct Main *bmain)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void BKE_main_idmap_destroy(
|
||||
struct IDNameLib_Map *id_typemap)
|
||||
ATTR_NONNULL();
|
||||
struct Main *BKE_main_idmap_main_get(
|
||||
struct IDNameLib_Map *id_typemap)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
struct ID *BKE_main_idmap_lookup(
|
||||
struct IDNameLib_Map *id_typemap,
|
||||
short id_type, const char *name, const struct Library *lib)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 3);
|
||||
struct ID *BKE_main_idmap_lookup_id(
|
||||
struct IDNameLib_Map *id_typemap, const struct ID *id)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
|
||||
|
||||
#endif /* __BKE_LIBRARY_IDMAP_H__ */
|
@ -121,6 +121,7 @@ set(SRC
|
||||
intern/lamp.c
|
||||
intern/lattice.c
|
||||
intern/library.c
|
||||
intern/library_idmap.c
|
||||
intern/library_query.c
|
||||
intern/linestyle.c
|
||||
intern/mask.c
|
||||
@ -244,6 +245,7 @@ set(SRC
|
||||
BKE_lamp.h
|
||||
BKE_lattice.h
|
||||
BKE_library.h
|
||||
BKE_library_idmap.h
|
||||
BKE_library_query.h
|
||||
BKE_linestyle.h
|
||||
BKE_main.h
|
||||
|
174
source/blender/blenkernel/intern/library_idmap.c
Normal file
174
source/blender/blenkernel/intern/library_idmap.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BKE_idcode.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_library_idmap.h" /* own include */
|
||||
|
||||
/** \file blender/blenkernel/intern/library_map.c
|
||||
* \ingroup bke
|
||||
*
|
||||
* Utility functions for faster ID lookups.
|
||||
*/
|
||||
|
||||
/** \name BKE_main_idmap API
|
||||
*
|
||||
* Cache ID (name, library lookups).
|
||||
* This doesn't account for adding/removing data-blocks,
|
||||
* and should only be used when performing many lookups.
|
||||
*
|
||||
* \note GHash's are initialized on demand,
|
||||
* since its likely some types will never have lookups run on them,
|
||||
* so its a waste to create and never use.
|
||||
* \{ */
|
||||
|
||||
struct IDNameLib_Key {
|
||||
/** ``ID.name + 2``: without the ID type prefix, since each id type gets it's own 'map' */
|
||||
const char *name;
|
||||
/** ``ID.lib``: */
|
||||
const Library *lib;
|
||||
};
|
||||
|
||||
struct IDNameLib_TypeMap {
|
||||
GHash *map;
|
||||
short id_type;
|
||||
/* only for storage of keys in the ghash, avoid many single allocs */
|
||||
struct IDNameLib_Key *keys;
|
||||
};
|
||||
|
||||
/**
|
||||
* Opaque structure, external API users only see this.
|
||||
*/
|
||||
struct IDNameLib_Map {
|
||||
struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY];
|
||||
struct Main *bmain;
|
||||
};
|
||||
|
||||
static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map, short id_type)
|
||||
{
|
||||
for (int i = 0; i < MAX_LIBARRAY; i++) {
|
||||
if (id_map->type_maps[i].id_type == id_type) {
|
||||
return &id_map->type_maps[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain)
|
||||
{
|
||||
struct IDNameLib_Map *id_map = MEM_mallocN(sizeof(*id_map), __func__);
|
||||
|
||||
int index = 0;
|
||||
while (index < MAX_LIBARRAY) {
|
||||
id_map->type_maps[index].map = NULL;
|
||||
id_map->type_maps[index].id_type = BKE_idcode_iter_step(&index);
|
||||
}
|
||||
BLI_assert(index == MAX_LIBARRAY);
|
||||
|
||||
id_map->bmain = bmain;
|
||||
|
||||
return id_map;
|
||||
}
|
||||
|
||||
struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_map)
|
||||
{
|
||||
return id_map->bmain;
|
||||
}
|
||||
|
||||
static unsigned int idkey_hash(const void *ptr)
|
||||
{
|
||||
const struct IDNameLib_Key *idkey = ptr;
|
||||
unsigned int key = BLI_ghashutil_strhash(idkey->name);
|
||||
if (idkey->lib) {
|
||||
key ^= BLI_ghashutil_ptrhash(idkey->lib);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
static bool idkey_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct IDNameLib_Key *idkey_a = a;
|
||||
const struct IDNameLib_Key *idkey_b = b;
|
||||
return strcmp(idkey_a->name, idkey_b->name) || (idkey_a->lib != idkey_b->lib);
|
||||
}
|
||||
|
||||
ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_map, short id_type, const char *name, const Library *lib)
|
||||
{
|
||||
struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type);
|
||||
|
||||
if (UNLIKELY(type_map == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* lazy init */
|
||||
if (type_map->map == NULL) {
|
||||
ListBase *lb = which_libbase(id_map->bmain, id_type);
|
||||
const int lb_len = BLI_listbase_count(lb);
|
||||
if (lb_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
type_map->map = BLI_ghash_new_ex(idkey_hash, idkey_cmp, __func__, lb_len);
|
||||
type_map->keys = MEM_mallocN(sizeof(struct IDNameLib_Key) * lb_len, __func__);
|
||||
|
||||
GHash *map = type_map->map;
|
||||
struct IDNameLib_Key *key = type_map->keys;
|
||||
|
||||
for (ID *id = lb->first; id; id = id->next, key++) {
|
||||
key->name = id->name + 2;
|
||||
key->lib = id->lib;
|
||||
BLI_ghash_insert(map, key, id);
|
||||
}
|
||||
}
|
||||
|
||||
const struct IDNameLib_Key key_lookup = {name, lib};
|
||||
return BLI_ghash_lookup(type_map->map, &key_lookup);
|
||||
}
|
||||
|
||||
ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_map, const ID *id)
|
||||
{
|
||||
return BKE_main_idmap_lookup(id_map, GS(id->name), id->name + 2, id->lib);
|
||||
}
|
||||
|
||||
void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map)
|
||||
{
|
||||
struct IDNameLib_TypeMap *type_map = id_map->type_maps;
|
||||
for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
|
||||
if (type_map->map) {
|
||||
BLI_ghash_free(type_map->map, NULL, NULL);
|
||||
type_map->map = NULL;
|
||||
MEM_freeN(type_map->keys);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(id_map);
|
||||
}
|
||||
|
||||
/** \} */
|
@ -124,6 +124,7 @@
|
||||
#include "BKE_global.h" // for G
|
||||
#include "BKE_group.h"
|
||||
#include "BKE_library.h" // for which_libbase
|
||||
#include "BKE_library_idmap.h"
|
||||
#include "BKE_library_query.h"
|
||||
#include "BKE_idcode.h"
|
||||
#include "BKE_material.h"
|
||||
@ -211,6 +212,9 @@
|
||||
/* use GHash for BHead name-based lookups (speeds up linking) */
|
||||
#define USE_GHASH_BHEAD
|
||||
|
||||
/* Use GHash for restoring pointers by name */
|
||||
#define USE_GHASH_RESTORE_POINTER
|
||||
|
||||
/***/
|
||||
|
||||
typedef struct OldNew {
|
||||
@ -6389,68 +6393,96 @@ typedef enum ePointerUserMode {
|
||||
USER_REAL = 1, /* ensure at least one real user (fake user ignored) */
|
||||
} ePointerUserMode;
|
||||
|
||||
static bool restore_pointer(ID *id, ID *newid, ePointerUserMode user)
|
||||
static void restore_pointer_user(ID *id, ID *newid, ePointerUserMode user)
|
||||
{
|
||||
if (STREQ(newid->name + 2, id->name + 2)) {
|
||||
if (newid->lib == id->lib) {
|
||||
if (user == USER_REAL) {
|
||||
id_us_ensure_real(newid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
BLI_assert(STREQ(newid->name + 2, id->name + 2));
|
||||
BLI_assert(newid->lib == id->lib);
|
||||
UNUSED_VARS_NDEBUG(id);
|
||||
|
||||
if (user == USER_REAL) {
|
||||
id_us_ensure_real(newid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef USE_GHASH_RESTORE_POINTER
|
||||
/**
|
||||
* Only for undo files, or to restore a screen after reading without UI...
|
||||
*
|
||||
* user
|
||||
* - USER_IGNORE: no usercount change
|
||||
* - USER_REAL: ensure a real user (even if a fake one is set)
|
||||
* A version of #restore_pointer_by_name that performs a full search (slow!).
|
||||
* Use only for limited lookups, when the overhead of
|
||||
* creating a #IDNameLib_Map for a single lookup isn't worthwhile.
|
||||
*/
|
||||
static void *restore_pointer_by_name(Main *mainp, ID *id, ePointerUserMode user)
|
||||
static void *restore_pointer_by_name_main(Main *mainp, ID *id, ePointerUserMode user)
|
||||
{
|
||||
if (id) {
|
||||
ListBase *lb = which_libbase(mainp, GS(id->name));
|
||||
if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
|
||||
if (lb) { /* there's still risk of checking corrupt mem (freed Ids in oops) */
|
||||
ID *idn = lb->first;
|
||||
|
||||
for (; idn; idn = idn->next) {
|
||||
if (restore_pointer(id, idn, user))
|
||||
break;
|
||||
if (STREQ(idn->name + 2, id->name + 2)) {
|
||||
if (idn->lib == id->lib) {
|
||||
restore_pointer_user(id, idn, user);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lib_link_seq_clipboard_pt_restore(ID *id, Main *newmain)
|
||||
/**
|
||||
* Only for undo files, or to restore a screen after reading without UI...
|
||||
*
|
||||
* \param user:
|
||||
* - USER_IGNORE: no usercount change
|
||||
* - USER_REAL: ensure a real user (even if a fake one is set)
|
||||
* \param id_map: lookup table, use when performing many lookups.
|
||||
* this could be made an optional agument (falling back to a full lookup),
|
||||
* however at the moment it's always available.
|
||||
*/
|
||||
static void *restore_pointer_by_name(struct IDNameLib_Map *id_map, ID *id, ePointerUserMode user)
|
||||
{
|
||||
#ifdef USE_GHASH_RESTORE_POINTER
|
||||
if (id) {
|
||||
/* use fast lookup when available */
|
||||
ID *idn = BKE_main_idmap_lookup_id(id_map, id);
|
||||
if (idn) {
|
||||
restore_pointer_user(id, idn, user);
|
||||
}
|
||||
return idn;
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Main *mainp = BKE_main_idmap_main_get(id_map);
|
||||
return restore_pointer_by_name_main(mainp, id, user);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lib_link_seq_clipboard_pt_restore(ID *id, struct IDNameLib_Map *id_map)
|
||||
{
|
||||
if (id) {
|
||||
/* clipboard must ensure this */
|
||||
BLI_assert(id->newid != NULL);
|
||||
id->newid = restore_pointer_by_name(newmain, (ID *)id->newid, USER_REAL);
|
||||
id->newid = restore_pointer_by_name(id_map, id->newid, USER_REAL);
|
||||
}
|
||||
}
|
||||
static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
|
||||
{
|
||||
Main *newmain = (Main *)arg_pt;
|
||||
struct IDNameLib_Map *id_map = arg_pt;
|
||||
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->scene, newmain);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->scene_camera, newmain);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->clip, newmain);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->mask, newmain);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->sound, newmain);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->scene, id_map);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->scene_camera, id_map);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->clip, id_map);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->mask, id_map);
|
||||
lib_link_seq_clipboard_pt_restore((ID *)seq->sound, id_map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void lib_link_clipboard_restore(Main *newmain)
|
||||
static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
|
||||
{
|
||||
/* update IDs stored in sequencer clipboard */
|
||||
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, newmain);
|
||||
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
|
||||
}
|
||||
|
||||
/* called from kernel/blender.c */
|
||||
@ -6462,11 +6494,13 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
wmWindowManager *wm;
|
||||
bScreen *sc;
|
||||
ScrArea *sa;
|
||||
|
||||
|
||||
struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
|
||||
|
||||
/* first windowmanager */
|
||||
for (wm = newmain->wm.first; wm; wm = wm->id.next) {
|
||||
for (win= wm->windows.first; win; win= win->next) {
|
||||
win->screen = restore_pointer_by_name(newmain, (ID *)win->screen, USER_REAL);
|
||||
win->screen = restore_pointer_by_name(id_map, (ID *)win->screen, USER_REAL);
|
||||
|
||||
if (win->screen == NULL)
|
||||
win->screen = curscreen;
|
||||
@ -6479,7 +6513,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
for (sc = newmain->screen.first; sc; sc = sc->id.next) {
|
||||
Scene *oldscene = sc->scene;
|
||||
|
||||
sc->scene= restore_pointer_by_name(newmain, (ID *)sc->scene, USER_REAL);
|
||||
sc->scene= restore_pointer_by_name(id_map, (ID *)sc->scene, USER_REAL);
|
||||
if (sc->scene == NULL)
|
||||
sc->scene = curscene;
|
||||
|
||||
@ -6498,16 +6532,16 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
if (v3d->scenelock)
|
||||
v3d->camera = NULL; /* always get from scene */
|
||||
else
|
||||
v3d->camera = restore_pointer_by_name(newmain, (ID *)v3d->camera, USER_REAL);
|
||||
v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
|
||||
if (v3d->camera == NULL)
|
||||
v3d->camera = sc->scene->camera;
|
||||
v3d->ob_centre = restore_pointer_by_name(newmain, (ID *)v3d->ob_centre, USER_REAL);
|
||||
v3d->ob_centre = restore_pointer_by_name(id_map, (ID *)v3d->ob_centre, USER_REAL);
|
||||
|
||||
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
|
||||
if ((bgpic->ima = restore_pointer_by_name(newmain, (ID *)bgpic->ima, USER_IGNORE))) {
|
||||
if ((bgpic->ima = restore_pointer_by_name(id_map, (ID *)bgpic->ima, USER_IGNORE))) {
|
||||
id_us_plus((ID *)bgpic->ima);
|
||||
}
|
||||
if ((bgpic->clip = restore_pointer_by_name(newmain, (ID *)bgpic->clip, USER_IGNORE))) {
|
||||
if ((bgpic->clip = restore_pointer_by_name(id_map, (ID *)bgpic->clip, USER_IGNORE))) {
|
||||
id_us_plus((ID *)bgpic->clip);
|
||||
}
|
||||
}
|
||||
@ -6551,10 +6585,10 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
bDopeSheet *ads = sipo->ads;
|
||||
|
||||
if (ads) {
|
||||
ads->source = restore_pointer_by_name(newmain, (ID *)ads->source, USER_REAL);
|
||||
ads->source = restore_pointer_by_name(id_map, (ID *)ads->source, USER_REAL);
|
||||
|
||||
if (ads->filter_grp)
|
||||
ads->filter_grp = restore_pointer_by_name(newmain, (ID *)ads->filter_grp, USER_IGNORE);
|
||||
ads->filter_grp = restore_pointer_by_name(id_map, (ID *)ads->filter_grp, USER_IGNORE);
|
||||
}
|
||||
|
||||
/* force recalc of list of channels (i.e. includes calculating F-Curve colors)
|
||||
@ -6564,7 +6598,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
}
|
||||
else if (sl->spacetype == SPACE_BUTS) {
|
||||
SpaceButs *sbuts = (SpaceButs *)sl;
|
||||
sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, USER_IGNORE);
|
||||
sbuts->pinid = restore_pointer_by_name(id_map, sbuts->pinid, USER_IGNORE);
|
||||
if (sbuts->pinid == NULL) {
|
||||
sbuts->flag &= ~SB_PIN_CONTEXT;
|
||||
}
|
||||
@ -6581,11 +6615,11 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
else if (sl->spacetype == SPACE_ACTION) {
|
||||
SpaceAction *saction = (SpaceAction *)sl;
|
||||
|
||||
saction->action = restore_pointer_by_name(newmain, (ID *)saction->action, USER_REAL);
|
||||
saction->ads.source = restore_pointer_by_name(newmain, (ID *)saction->ads.source, USER_REAL);
|
||||
saction->action = restore_pointer_by_name(id_map, (ID *)saction->action, USER_REAL);
|
||||
saction->ads.source = restore_pointer_by_name(id_map, (ID *)saction->ads.source, USER_REAL);
|
||||
|
||||
if (saction->ads.filter_grp)
|
||||
saction->ads.filter_grp = restore_pointer_by_name(newmain, (ID *)saction->ads.filter_grp, USER_IGNORE);
|
||||
saction->ads.filter_grp = restore_pointer_by_name(id_map, (ID *)saction->ads.filter_grp, USER_IGNORE);
|
||||
|
||||
|
||||
/* force recalc of list of channels, potentially updating the active action
|
||||
@ -6596,7 +6630,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
else if (sl->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)sl;
|
||||
|
||||
sima->image = restore_pointer_by_name(newmain, (ID *)sima->image, USER_REAL);
|
||||
sima->image = restore_pointer_by_name(id_map, (ID *)sima->image, USER_REAL);
|
||||
|
||||
/* this will be freed, not worth attempting to find same scene,
|
||||
* since it gets initialized later */
|
||||
@ -6611,8 +6645,8 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
|
||||
* so assume that here we're doing for undo only...
|
||||
*/
|
||||
sima->gpd = restore_pointer_by_name(newmain, (ID *)sima->gpd, USER_REAL);
|
||||
sima->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sima->mask_info.mask, USER_REAL);
|
||||
sima->gpd = restore_pointer_by_name(id_map, (ID *)sima->gpd, USER_REAL);
|
||||
sima->mask_info.mask = restore_pointer_by_name(id_map, (ID *)sima->mask_info.mask, USER_REAL);
|
||||
}
|
||||
else if (sl->spacetype == SPACE_SEQ) {
|
||||
SpaceSeq *sseq = (SpaceSeq *)sl;
|
||||
@ -6620,29 +6654,29 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
/* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
|
||||
* so assume that here we're doing for undo only...
|
||||
*/
|
||||
sseq->gpd = restore_pointer_by_name(newmain, (ID *)sseq->gpd, USER_REAL);
|
||||
sseq->gpd = restore_pointer_by_name(id_map, (ID *)sseq->gpd, USER_REAL);
|
||||
}
|
||||
else if (sl->spacetype == SPACE_NLA) {
|
||||
SpaceNla *snla = (SpaceNla *)sl;
|
||||
bDopeSheet *ads = snla->ads;
|
||||
|
||||
if (ads) {
|
||||
ads->source = restore_pointer_by_name(newmain, (ID *)ads->source, USER_REAL);
|
||||
ads->source = restore_pointer_by_name(id_map, (ID *)ads->source, USER_REAL);
|
||||
|
||||
if (ads->filter_grp)
|
||||
ads->filter_grp = restore_pointer_by_name(newmain, (ID *)ads->filter_grp, USER_IGNORE);
|
||||
ads->filter_grp = restore_pointer_by_name(id_map, (ID *)ads->filter_grp, USER_IGNORE);
|
||||
}
|
||||
}
|
||||
else if (sl->spacetype == SPACE_TEXT) {
|
||||
SpaceText *st = (SpaceText *)sl;
|
||||
|
||||
st->text = restore_pointer_by_name(newmain, (ID *)st->text, USER_REAL);
|
||||
st->text = restore_pointer_by_name(id_map, (ID *)st->text, USER_REAL);
|
||||
if (st->text == NULL) st->text = newmain->text.first;
|
||||
}
|
||||
else if (sl->spacetype == SPACE_SCRIPT) {
|
||||
SpaceScript *scpt = (SpaceScript *)sl;
|
||||
|
||||
scpt->script = restore_pointer_by_name(newmain, (ID *)scpt->script, USER_REAL);
|
||||
scpt->script = restore_pointer_by_name(id_map, (ID *)scpt->script, USER_REAL);
|
||||
|
||||
/*sc->script = NULL; - 2.45 set to null, better re-run the script */
|
||||
if (scpt->script) {
|
||||
@ -6652,7 +6686,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
else if (sl->spacetype == SPACE_OUTLINER) {
|
||||
SpaceOops *so= (SpaceOops *)sl;
|
||||
|
||||
so->search_tse.id = restore_pointer_by_name(newmain, so->search_tse.id, USER_IGNORE);
|
||||
so->search_tse.id = restore_pointer_by_name(id_map, so->search_tse.id, USER_IGNORE);
|
||||
|
||||
if (so->treestore) {
|
||||
TreeStoreElem *tselem;
|
||||
@ -6662,7 +6696,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
while ((tselem = BLI_mempool_iterstep(&iter))) {
|
||||
/* Do not try to restore pointers to drivers/sequence/etc., can crash in undo case! */
|
||||
if (TSE_IS_REAL_ID(tselem)) {
|
||||
tselem->id = restore_pointer_by_name(newmain, tselem->id, USER_IGNORE);
|
||||
tselem->id = restore_pointer_by_name(id_map, tselem->id, USER_IGNORE);
|
||||
}
|
||||
else {
|
||||
tselem->id = NULL;
|
||||
@ -6680,14 +6714,14 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
bNodeTree *ntree;
|
||||
|
||||
/* node tree can be stored locally in id too, link this first */
|
||||
snode->id = restore_pointer_by_name(newmain, snode->id, USER_REAL);
|
||||
snode->from = restore_pointer_by_name(newmain, snode->from, USER_IGNORE);
|
||||
snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL);
|
||||
snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE);
|
||||
|
||||
ntree = nodetree_from_id(snode->id);
|
||||
if (ntree)
|
||||
snode->nodetree = ntree;
|
||||
else
|
||||
snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, USER_REAL);
|
||||
snode->nodetree = restore_pointer_by_name(id_map, (ID*)snode->nodetree, USER_REAL);
|
||||
|
||||
for (path = snode->treepath.first; path; path = path->next) {
|
||||
if (path == snode->treepath.first) {
|
||||
@ -6695,7 +6729,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
path->nodetree = snode->nodetree;
|
||||
}
|
||||
else
|
||||
path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, USER_REAL);
|
||||
path->nodetree= restore_pointer_by_name(id_map, (ID*)path->nodetree, USER_REAL);
|
||||
|
||||
if (!path->nodetree)
|
||||
break;
|
||||
@ -6721,22 +6755,24 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
else if (sl->spacetype == SPACE_CLIP) {
|
||||
SpaceClip *sclip = (SpaceClip *)sl;
|
||||
|
||||
sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, USER_REAL);
|
||||
sclip->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sclip->mask_info.mask, USER_REAL);
|
||||
sclip->clip = restore_pointer_by_name(id_map, (ID *)sclip->clip, USER_REAL);
|
||||
sclip->mask_info.mask = restore_pointer_by_name(id_map, (ID *)sclip->mask_info.mask, USER_REAL);
|
||||
|
||||
sclip->scopes.ok = 0;
|
||||
}
|
||||
else if (sl->spacetype == SPACE_LOGIC) {
|
||||
SpaceLogic *slogic = (SpaceLogic *)sl;
|
||||
|
||||
slogic->gpd = restore_pointer_by_name(newmain, (ID *)slogic->gpd, USER_REAL);
|
||||
slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* update IDs stored in all possible clipboards */
|
||||
lib_link_clipboard_restore(newmain);
|
||||
lib_link_clipboard_restore(id_map);
|
||||
|
||||
BKE_main_idmap_destroy(id_map);
|
||||
}
|
||||
|
||||
static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
|
||||
|
Loading…
Reference in New Issue
Block a user