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,400 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| bhead = blo_bhead_next(fd, bhead); | bhead = blo_bhead_next(fd, bhead); | ||||
| } | } | ||||
| return bhead; | return bhead; | ||||
| } | } | ||||
| static BHead *read_libblock(FileData *fd, | static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id) | ||||
| Main *main, | |||||
| BHead *bhead, | |||||
| const int tag, | |||||
| const bool placeholder_set_indirect_extern, | |||||
| ID **r_id) | |||||
| { | { | ||||
| /* This routine reads a libblock and its direct data. Lib link functions will | |||||
| * set points between datablocks. */ | |||||
| if (r_id) { | |||||
| *r_id = NULL; /* In case of early return. */ | |||||
| } | |||||
| /* Read libblock struct. */ | |||||
| fd->are_memchunks_identical = true; | |||||
| ID *id = read_struct(fd, bhead, "lib block"); | |||||
| if (id == NULL) { | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| /* Determine ID type. */ | |||||
| const short idcode = GS(id->name); | |||||
| ListBase *lb = which_libbase(main, idcode); | |||||
| if (lb == NULL) { | |||||
| /* Unknown ID type. */ | |||||
| printf("%s: unknown id code '%c%c'\n", __func__, (idcode & 0xff), (idcode >> 8)); | |||||
| MEM_freeN(id); | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| /* In undo case, most libs and linked data should be kept as is from previous state | /* In undo case, most libs and linked data should be kept as is from previous state | ||||
| * (see BLO_read_from_memfile). | * (see BLO_read_from_memfile). | ||||
| * However, some needed by the snapshot being read may have been removed in previous one, | * However, some needed by the snapshot being read may have been removed in previous one, | ||||
| * and would go missing. | * and would go missing. | ||||
| * This leads e.g. to disappearing objects in some undo/redo case, see T34446. | * This leads e.g. to disappearing objects in some undo/redo case, see T34446. | ||||
| * That means we have to carefully check whether current lib or | * That means we have to carefully check whether current lib or | ||||
| * libdata already exits in old main, if it does we merely copy it over into new main area, | * libdata already exits in old main, if it does we merely copy it over into new main area, | ||||
| * otherwise we have to do a full read of that bhead... */ | * otherwise we have to do a full read of that bhead... */ | ||||
| if (fd->memfile != NULL && ELEM(bhead->code, ID_LI, ID_LINK_PLACEHOLDER)) { | DEBUG_PRINTF("UNDO: restore library %s\n", id->name); | ||||
| DEBUG_PRINTF("Checking %s...\n", id->name); | |||||
| if (bhead->code == ID_LI) { | |||||
| Main *libmain = fd->old_mainlist->first; | Main *libmain = fd->old_mainlist->first; | ||||
| /* Skip oldmain itself... */ | /* Skip oldmain itself... */ | ||||
| for (libmain = libmain->next; libmain; libmain = libmain->next) { | for (libmain = libmain->next; libmain; libmain = libmain->next) { | ||||
| DEBUG_PRINTF("... against %s: ", libmain->curlib ? libmain->curlib->id.name : "<NULL>"); | DEBUG_PRINTF(" compare with %s -> ", libmain->curlib ? libmain->curlib->id.name : "<NULL>"); | ||||
| if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) { | if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) { | ||||
| Main *oldmain = fd->old_mainlist->first; | Main *oldmain = fd->old_mainlist->first; | ||||
| DEBUG_PRINTF("FOUND!\n"); | DEBUG_PRINTF("match!\n"); | ||||
| /* In case of a library, we need to re-add its main to fd->mainlist, | /* In case of a library, we need to re-add its main to fd->mainlist, | ||||
| * because if we have later a missing ID_LINK_PLACEHOLDER, | * because if we have later a missing ID_LINK_PLACEHOLDER, | ||||
| * we need to get the correct lib it is linked to! | * we need to get the correct lib it is linked to! | ||||
| * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile() | * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile() | ||||
| * like it used to be. */ | * like it used to be. */ | ||||
| BLI_remlink(fd->old_mainlist, libmain); | BLI_remlink(fd->old_mainlist, libmain); | ||||
| BLI_remlink_safe(&oldmain->libraries, libmain->curlib); | BLI_remlink_safe(&oldmain->libraries, libmain->curlib); | ||||
| BLI_addtail(fd->mainlist, libmain); | BLI_addtail(fd->mainlist, libmain); | ||||
| BLI_addtail(&main->libraries, libmain->curlib); | BLI_addtail(&main->libraries, libmain->curlib); | ||||
| return true; | |||||
| MEM_freeN(id); | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | } | ||||
| DEBUG_PRINTF("nothing...\n"); | DEBUG_PRINTF("no match\n"); | ||||
| } | } | ||||
| return false; | |||||
| } | } | ||||
| else { | |||||
| DEBUG_PRINTF("... in %s (%s): ", | static bool read_libblock_undo_restore_linked(FileData *fd, Main *main, const ID *id, BHead *bhead) | ||||
| { | |||||
| DEBUG_PRINTF("UNDO: restore linked datablock %s\n", id->name); | |||||
| DEBUG_PRINTF(" from %s (%s): ", | |||||
| main->curlib ? main->curlib->id.name : "<NULL>", | main->curlib ? main->curlib->id.name : "<NULL>", | ||||
| main->curlib ? main->curlib->name : "<NULL>"); | main->curlib ? main->curlib->name : "<NULL>"); | ||||
| ID *existing_id = BKE_libblock_find_name(main, GS(id->name), id->name + 2); | ID *existing_id = BKE_libblock_find_name(main, GS(id->name), id->name + 2); | ||||
| if (existing_id != NULL) { | if (existing_id != NULL) { | ||||
| DEBUG_PRINTF("FOUND!\n"); | DEBUG_PRINTF(" found!\n"); | ||||
| /* Even though we found our linked ID, | /* Even though we found our linked ID, | ||||
| * there is no guarantee its address is still the same. */ | * there is no guarantee its address is still the same. */ | ||||
| if (existing_id != bhead->old) { | if (existing_id != bhead->old) { | ||||
| oldnewmap_insert(fd->libmap, bhead->old, existing_id, GS(existing_id->name)); | oldnewmap_insert(fd->libmap, bhead->old, existing_id, GS(existing_id->name)); | ||||
| } | } | ||||
| /* No need to do anything else for ID_LINK_PLACEHOLDER, | /* No need to do anything else for ID_LINK_PLACEHOLDER, | ||||
| * it's assumed already present in its lib's main. */ | * it's assumed already present in its lib's main. */ | ||||
| return true; | |||||
| } | |||||
| DEBUG_PRINTF(" not found\n"); | |||||
| return false; | |||||
| } | |||||
| static BHead *read_libblock(FileData *fd, | |||||
| Main *main, | |||||
| BHead *bhead, | |||||
| const int tag, | |||||
| const bool placeholder_set_indirect_extern, | |||||
| ID **r_id) | |||||
| { | |||||
| /* This routine reads a libblock and its direct data. Lib link functions will | |||||
| * set points between datablocks. */ | |||||
| if (r_id) { | |||||
| *r_id = NULL; /* In case of early return. */ | |||||
| } | |||||
| /* Read libblock struct. */ | |||||
| fd->are_memchunks_identical = true; | |||||
| ID *id = read_struct(fd, bhead, "lib block"); | |||||
| if (id == NULL) { | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| /* Determine ID type. */ | |||||
| const short idcode = GS(id->name); | |||||
| ListBase *lb = which_libbase(main, idcode); | |||||
| if (lb == NULL) { | |||||
| /* Unknown ID type. */ | |||||
| printf("%s: unknown id code '%c%c'\n", __func__, (idcode & 0xff), (idcode >> 8)); | |||||
| MEM_freeN(id); | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| /* Restore library and linked datablocks for undo. */ | |||||
| if (fd->memfile != NULL) { | |||||
| if (bhead->code == ID_LI) { | |||||
| if (read_libblock_undo_restore_library(fd, main, id)) { | |||||
| MEM_freeN(id); | |||||
| return blo_bhead_next(fd, bhead); | |||||
| } | |||||
| } | |||||
| else if (bhead->code == ID_LINK_PLACEHOLDER) { | |||||
| 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); | ||||
| } | } | ||||
| DEBUG_PRINTF("nothing...\n"); | |||||
| } | } | ||||
| } | } | ||||
| /* read libblock */ | /* read libblock */ | ||||
| BHead *id_bhead = bhead; | BHead *id_bhead = bhead; | ||||
| if (id_bhead->code != ID_LINK_PLACEHOLDER) { | if (id_bhead->code != ID_LINK_PLACEHOLDER) { | ||||
| /* need a name for the mallocN, just for debugging and sane prints on leaks */ | /* need a name for the mallocN, just for debugging and sane prints on leaks */ | ||||
| ▲ Show 20 Lines • Show All 2,953 Lines • Show Last 20 Lines | |||||