Fix T49856: Blender 2.78 crashes after loading data from a blendfile
Issue here was that py API code was keeping references (pointers) to the liniked data-blocks, which can actually be duplicated and then deleted during the 'make local' process... Would have like to find a better way than passing optional GHash to get the oldid->newid mapping, but could not think of a better idea.
This commit is contained in:
parent
bf1e9bc613
commit
1ee43c5aef
Notes:
blender-bot
2023-02-14 07:28:08 +01:00
Referenced by issue #49928, Wrong reflection with dupli spot lamp Referenced by issue #49893, Crash in Video Sequence Editor Referenced by issue #49856, Blender 2.78 crashes after loading data from a blendfile
|
@ -39,6 +39,7 @@ extern "C" {
|
|||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
struct BlendThumbnail;
|
||||
struct GHash;
|
||||
struct ListBase;
|
||||
struct ID;
|
||||
struct ImBuf;
|
||||
|
@ -125,7 +126,8 @@ void BKE_id_ui_prefix(char name[66 + 1], const struct ID *id);
|
|||
void BKE_library_free(struct Library *lib);
|
||||
|
||||
void BKE_library_make_local(
|
||||
struct Main *bmain, const struct Library *lib, const bool untagged_only, const bool set_fake);
|
||||
struct Main *bmain, const struct Library *lib, struct GHash *old_to_new_ids,
|
||||
const bool untagged_only, const bool set_fake);
|
||||
|
||||
|
||||
/* use when "" is given to new_id() */
|
||||
|
|
|
@ -101,7 +101,7 @@ bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *repor
|
|||
IMB_colormanagement_check_file_config(bmain_dst);
|
||||
/* Append, rather than linking. */
|
||||
Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath));
|
||||
BKE_library_make_local(bmain_dst, lib, true, false);
|
||||
BKE_library_make_local(bmain_dst, lib, NULL, true, false);
|
||||
/* Important we unset, otherwise these object wont
|
||||
* link into other scenes from this blend file.
|
||||
*/
|
||||
|
@ -150,7 +150,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
|
|||
|
||||
/* append, rather than linking */
|
||||
lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
|
||||
BKE_library_make_local(bmain, lib, true, false);
|
||||
BKE_library_make_local(bmain, lib, NULL, true, false);
|
||||
|
||||
/* important we unset, otherwise these object wont
|
||||
* link into other scenes from this blend file */
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_memarena.h"
|
||||
|
||||
|
@ -1640,7 +1641,8 @@ void BKE_main_id_clear_newpoins(Main *bmain)
|
|||
* We'll probably need at some point a true dependency graph between datablocks, but for now this should work
|
||||
* good enough (performances is not a critical point here anyway).
|
||||
*/
|
||||
void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged_only, const bool set_fake)
|
||||
void BKE_library_make_local(
|
||||
Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake)
|
||||
{
|
||||
ListBase *lbarray[MAX_LIBARRAY];
|
||||
ID *id, *id_next;
|
||||
|
@ -1712,6 +1714,9 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged
|
|||
BLI_assert(id->lib != NULL);
|
||||
|
||||
BKE_libblock_remap(bmain, id, id->newid, ID_REMAP_SKIP_INDIRECT_USAGE);
|
||||
if (old_to_new_ids) {
|
||||
BLI_ghash_insert(old_to_new_ids, id, id->newid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Third step: remove datablocks that have been copied to be localized and are no more used in the end...
|
||||
|
|
|
@ -2235,7 +2235,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
|
|||
"Orphan library objects added to the current scene to avoid loss");
|
||||
}
|
||||
|
||||
BKE_library_make_local(bmain, NULL, false, false); /* NULL is all libs */
|
||||
BKE_library_make_local(bmain, NULL, NULL, false, false); /* NULL is all libs */
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
@ -405,6 +406,8 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
|
|||
BLO_blendhandle_close(self->blo_handle);
|
||||
self->blo_handle = NULL;
|
||||
|
||||
GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__);
|
||||
|
||||
/* copied from wm_operator.c */
|
||||
{
|
||||
/* mark all library linked objects to be updated */
|
||||
|
@ -412,7 +415,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
|
|||
|
||||
/* append, rather than linking */
|
||||
if ((self->flag & FILE_LINK) == 0) {
|
||||
BKE_library_make_local(bmain, lib, true, false);
|
||||
BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,6 +442,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
|
|||
ID *id;
|
||||
|
||||
id = PyCapsule_GetPointer(item, NULL);
|
||||
id = BLI_ghash_lookup_default(old_to_new_ids, id, id);
|
||||
Py_DECREF(item);
|
||||
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
|
@ -452,6 +456,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
|
|||
}
|
||||
#endif /* USE_RNA_DATABLOCKS */
|
||||
|
||||
BLI_ghash_free(old_to_new_ids, NULL, NULL);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
|
|||
const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
|
||||
|
||||
if (use_recursive) {
|
||||
BKE_library_make_local(bmain, NULL, true, set_fake);
|
||||
BKE_library_make_local(bmain, NULL, NULL, true, set_fake);
|
||||
}
|
||||
else {
|
||||
LinkNode *itemlink;
|
||||
|
@ -430,7 +430,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
|
|||
ID *new_id = ((WMLinkAppendDataItem *)(itemlink->link))->new_id;
|
||||
|
||||
if (new_id && !BLI_gset_haskey(done_libraries, new_id->lib)) {
|
||||
BKE_library_make_local(bmain, new_id->lib, true, set_fake);
|
||||
BKE_library_make_local(bmain, new_id->lib, NULL, true, set_fake);
|
||||
BLI_gset_insert(done_libraries, new_id->lib);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue