Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenloader/intern/readfile.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 9,525 Lines • ▼ Show 20 Lines | if (bhead->code == ID_LI) { | ||||
| } | } | ||||
| } | } | ||||
| else if (bhead->code == ID_LINK_PLACEHOLDER) { | else if (bhead->code == ID_LINK_PLACEHOLDER) { | ||||
| if (read_libblock_undo_restore_linked(fd, main, id, bhead)) { | if (read_libblock_undo_restore_linked(fd, main, id, bhead)) { | ||||
| MEM_freeN(id); | MEM_freeN(id); | ||||
| return blo_bhead_next(fd, bhead); | return blo_bhead_next(fd, bhead); | ||||
| } | } | ||||
| } | } | ||||
| else if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { | |||||
| /* Skip reading any UI datablocks, existing ones are kept. */ | |||||
| MEM_freeN(id); | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| } | } | ||||
| /* Restore existing datablocks for undo. */ | /* Restore existing datablocks for undo. */ | ||||
| const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0; | const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0; | ||||
| /* Used when undoing from memfile, we swap changed IDs into their old addresses when found. */ | /* Used when undoing from memfile, we swap changed IDs into their old addresses when found. */ | ||||
| ID *id_old = NULL; | ID *id_old = NULL; | ||||
| bool do_id_swap = false; | bool do_id_swap = false; | ||||
| Show All 9 Lines | if (bhead->code != ID_LINK_PLACEHOLDER) { | ||||
| /* Find the 'current' existing ID we want to reuse instead of the one we would read from | /* Find the 'current' existing ID we want to reuse instead of the one we would read from | ||||
| * the undo memfile. */ | * the undo memfile. */ | ||||
| DEBUG_PRINTF("\t Looking for ID %s with uuid %u instead of newly read one\n", | DEBUG_PRINTF("\t Looking for ID %s with uuid %u instead of newly read one\n", | ||||
| id->name, | id->name, | ||||
| id->session_uuid); | id->session_uuid); | ||||
| id_old = do_partial_undo ? BKE_main_idmap_lookup_uuid(fd->old_idmap, id->session_uuid) : | id_old = do_partial_undo ? BKE_main_idmap_lookup_uuid(fd->old_idmap, id->session_uuid) : | ||||
| NULL; | NULL; | ||||
| bool can_finalize_and_return = false; | |||||
| if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { | if (id_old != NULL && is_identical) { | ||||
| /* Read WindowManager, Screen and WorkSpace IDs are never actually used during undo (see | |||||
| * `setup_app_data()` in `blendfile.c`). | |||||
| * So we can just abort here, just ensuring libmapping is set accordingly. */ | |||||
| can_finalize_and_return = true; | |||||
| } | |||||
| else if (id_old != NULL && is_identical) { | |||||
| /* Do not add LIB_TAG_NEW here, this should not be needed/used in undo case anyway (as | /* Do not add LIB_TAG_NEW here, this should not be needed/used in undo case anyway (as | ||||
| * this is only for do_version-like code), but for sake of consistency, and also because | * this is only for do_version-like code), but for sake of consistency, and also because | ||||
| * it will tell us which ID is re-used from old Main, and which one is actually new. */ | * it will tell us which ID is re-used from old Main, and which one is actually new. */ | ||||
| id_old->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_UNDO_OLD_ID_REUSED; | id_old->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_UNDO_OLD_ID_REUSED; | ||||
| id_old->lib = main->curlib; | id_old->lib = main->curlib; | ||||
| id_old->us = ID_FAKE_USERS(id_old); | id_old->us = ID_FAKE_USERS(id_old); | ||||
| /* Do not reset id->icon_id here, memory allocated for it remains valid. */ | /* Do not reset id->icon_id here, memory allocated for it remains valid. */ | ||||
| /* Needed because .blend may have been saved with crap value here... */ | /* Needed because .blend may have been saved with crap value here... */ | ||||
| id_old->newid = NULL; | id_old->newid = NULL; | ||||
| id_old->orig_id = NULL; | id_old->orig_id = NULL; | ||||
| /* About recalc: since that ID did not change at all, we know that its recalc fields also | /* About recalc: since that ID did not change at all, we know that its recalc fields also | ||||
| * remained unchanged, so no need to handle neither recalc nor recalc_undo_future here. | * remained unchanged, so no need to handle neither recalc nor recalc_undo_future here. | ||||
| */ | */ | ||||
| Main *old_bmain = fd->old_mainlist->first; | Main *old_bmain = fd->old_mainlist->first; | ||||
| ListBase *old_lb = which_libbase(old_bmain, idcode); | ListBase *old_lb = which_libbase(old_bmain, idcode); | ||||
| ListBase *new_lb = which_libbase(main, idcode); | ListBase *new_lb = which_libbase(main, idcode); | ||||
| BLI_remlink(old_lb, id_old); | BLI_remlink(old_lb, id_old); | ||||
| BLI_addtail(new_lb, id_old); | BLI_addtail(new_lb, id_old); | ||||
| can_finalize_and_return = true; | |||||
| } | |||||
| if (can_finalize_and_return) { | |||||
| DEBUG_PRINTF("Re-using existing ID %s instead of newly read one\n", id_old->name); | DEBUG_PRINTF("Re-using existing ID %s instead of newly read one\n", id_old->name); | ||||
| oldnewmap_insert(fd->libmap, bhead->old, id_old, bhead->code); | oldnewmap_insert(fd->libmap, bhead->old, id_old, bhead->code); | ||||
| oldnewmap_insert(fd->libmap, id_old, id_old, bhead->code); | oldnewmap_insert(fd->libmap, id_old, id_old, bhead->code); | ||||
| if (r_id) { | if (r_id) { | ||||
| *r_id = id_old; | *r_id = id_old; | ||||
| } | } | ||||
| Show All 40 Lines | if (do_partial_undo && id->lib == NULL) { | ||||
| id->session_uuid); | id->session_uuid); | ||||
| id_old = BKE_main_idmap_lookup_uuid(fd->old_idmap, id->session_uuid); | id_old = BKE_main_idmap_lookup_uuid(fd->old_idmap, id->session_uuid); | ||||
| if (id_old != NULL) { | if (id_old != NULL) { | ||||
| BLI_assert(MEM_allocN_len(id) == MEM_allocN_len(id_old)); | BLI_assert(MEM_allocN_len(id) == MEM_allocN_len(id_old)); | ||||
| /* UI IDs are always re-used from old bmain at higher-level calling code, so never swap | /* UI IDs are always re-used from old bmain at higher-level calling code, so never swap | ||||
| * those. Besides maybe custom properties, no other ID should have pointers to those | * those. Besides maybe custom properties, no other ID should have pointers to those | ||||
| * anyway... | * anyway... | ||||
| * And linked IDs are handled separately as well. */ | * And linked IDs are handled separately as well. */ | ||||
| do_id_swap = !ELEM(idcode, ID_WM, ID_SCR, ID_WS) && !(bhead->code == ID_LINK_PLACEHOLDER); | do_id_swap = !(bhead->code == ID_LINK_PLACEHOLDER); | ||||
| } | } | ||||
| } | } | ||||
| /* At this point, we know we are going to keep that newly read & allocated ID, so we need to | /* At this point, we know we are going to keep that newly read & allocated ID, so we need to | ||||
| * reallocate it to ensure we actually get a unique memory address for it. */ | * reallocate it to ensure we actually get a unique memory address for it. */ | ||||
| if (!do_id_swap) { | if (!do_id_swap) { | ||||
| DEBUG_PRINTF("using newly-read ID %s to a new mem address\n", id->name); | DEBUG_PRINTF("using newly-read ID %s to a new mem address\n", id->name); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 2,820 Lines • Show Last 20 Lines | |||||