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 2,368 Lines • ▼ Show 20 Lines | #ifdef USE_BHEAD_READ_ON_DEMAND | ||||
| } | } | ||||
| } | } | ||||
| #else | #else | ||||
| memcpy(temp, (bh + 1), bh->len); | memcpy(temp, (bh + 1), bh->len); | ||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| if (!BHEADN_FROM_BHEAD(bh)->is_memchunk_identical) { | |||||
| fd->are_memchunks_identical = false; | |||||
| } | |||||
| #ifdef USE_BHEAD_READ_ON_DEMAND | #ifdef USE_BHEAD_READ_ON_DEMAND | ||||
| if (bh_orig != bh) { | if (bh_orig != bh) { | ||||
| MEM_freeN(BHEADN_FROM_BHEAD(bh)); | MEM_freeN(BHEADN_FROM_BHEAD(bh)); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| return temp; | return temp; | ||||
| ▲ Show 20 Lines • Show All 6,986 Lines • ▼ Show 20 Lines | switch (GS(id->name)) { | ||||
| case ID_VO: | case ID_VO: | ||||
| direct_link_volume(fd, (Volume *)id); | direct_link_volume(fd, (Volume *)id); | ||||
| break; | break; | ||||
| } | } | ||||
| return success; | return success; | ||||
| } | } | ||||
| static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *allocname) | /* Read all data associated with a datablock into datamap. */ | ||||
| static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *allocname) | |||||
| { | { | ||||
| bhead = blo_bhead_next(fd, bhead); | bhead = blo_bhead_next(fd, bhead); | ||||
| while (bhead && bhead->code == DATA) { | while (bhead && bhead->code == DATA) { | ||||
| void *data; | void *data; | ||||
| #if 0 | #if 0 | ||||
| /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ | /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ | ||||
| short* sp = fd->filesdna->structs[bhead->SDNAnr]; | short* sp = fd->filesdna->structs[bhead->SDNAnr]; | ||||
| Show All 10 Lines | #endif | ||||
| } | } | ||||
| bhead = blo_bhead_next(fd, bhead); | bhead = blo_bhead_next(fd, bhead); | ||||
| } | } | ||||
| return bhead; | return bhead; | ||||
| } | } | ||||
| /* Verify if the datablock and all associated data is identical. */ | |||||
| static bool read_libblock_is_identical(FileData *fd, BHead *bhead) | |||||
| { | |||||
| /* Test ID itself. */ | |||||
| if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) { | |||||
| return false; | |||||
| } | |||||
| /* Test any other data that is part of ID (logic must match read_data_into_datamap). */ | |||||
| bhead = blo_bhead_next(fd, bhead); | |||||
| while (bhead && bhead->code == DATA) { | |||||
| if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) { | |||||
| return false; | |||||
| } | |||||
| bhead = blo_bhead_next(fd, bhead); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id) | static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id) | ||||
| { | { | ||||
| /* 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 | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| /* This routine reads a libblock and its direct data. Lib link functions will | /* This routine reads a libblock and its direct data. Lib link functions will | ||||
| * set points between datablocks. */ | * set points between datablocks. */ | ||||
| if (r_id) { | if (r_id) { | ||||
| *r_id = NULL; /* In case of early return. */ | *r_id = NULL; /* In case of early return. */ | ||||
| } | } | ||||
| /* Read libblock struct. */ | /* Read libblock struct. */ | ||||
| fd->are_memchunks_identical = true; | BHead *first_bhead = bhead; | ||||
| ID *id = read_struct(fd, bhead, "lib block"); | ID *id = read_struct(fd, bhead, "lib block"); | ||||
| if (id == NULL) { | if (id == NULL) { | ||||
| return blo_bhead_next(fd, bhead); | return blo_bhead_next(fd, bhead); | ||||
| } | } | ||||
| /* Determine ID type. */ | /* Determine ID type. */ | ||||
| const short idcode = GS(id->name); | const short idcode = GS(id->name); | ||||
| ListBase *lb = which_libbase(main, idcode); | ListBase *lb = which_libbase(main, idcode); | ||||
| Show All 26 Lines | static BHead *read_libblock(FileData *fd, | ||||
| 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 */ | ||||
| const char *allocname = dataname(idcode); | const char *allocname = dataname(idcode); | ||||
| /* read all data into fd->datamap */ | /* read all data into fd->datamap */ | ||||
| /* TODO: for the undo case instead of building oldnewmap here we could just quickly check the | /* TODO: for the undo case instead of building oldnewmap here we could just quickly check the | ||||
| * bheads... could save some more ticks. Probably not worth it though, bottleneck is full | * bheads... could save some more ticks. Probably not worth it though, bottleneck is full | ||||
| * depsgraph rebuild and evaluate, not actual file reading. */ | * depsgraph rebuild and evaluate, not actual file reading. */ | ||||
| bhead = read_data_into_oldnewmap(fd, id_bhead, allocname); | bhead = read_data_into_datamap(fd, id_bhead, allocname); | ||||
| } | } | ||||
| /* 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; | ||||
| if (fd->memfile != NULL) { | if (fd->memfile != NULL) { | ||||
| if (id_bhead->code != ID_LINK_PLACEHOLDER) { | if (id_bhead->code != ID_LINK_PLACEHOLDER) { | ||||
| DEBUG_PRINTF( | const bool is_identical = read_libblock_is_identical(fd, first_bhead); | ||||
| "%s: ID %s is unchanged: %d\n", __func__, id->name, fd->are_memchunks_identical); | DEBUG_PRINTF("%s: ID %s is unchanged: %d\n", __func__, id->name, is_identical); | ||||
| BLI_assert(fd->old_idmap != NULL || !do_partial_undo); | BLI_assert(fd->old_idmap != NULL || !do_partial_undo); | ||||
| /* This code should only ever be reached for local data-blocks. */ | /* This code should only ever be reached for local data-blocks. */ | ||||
| BLI_assert(main->curlib == NULL); | BLI_assert(main->curlib == NULL); | ||||
| /* 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; | bool can_finalize_and_return = false; | ||||
| if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { | if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { | ||||
| /* Read WindowManager, Screen and WorkSpace IDs are never actually used during undo (see | /* Read WindowManager, Screen and WorkSpace IDs are never actually used during undo (see | ||||
| * `setup_app_data()` in `blendfile.c`). | * `setup_app_data()` in `blendfile.c`). | ||||
| * So we can just abort here, just ensuring libmapping is set accordingly. */ | * So we can just abort here, just ensuring libmapping is set accordingly. */ | ||||
| can_finalize_and_return = true; | can_finalize_and_return = true; | ||||
| } | } | ||||
| else if (id_old != NULL && fd->are_memchunks_identical) { | 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... */ | ||||
| ▲ Show 20 Lines • Show All 539 Lines • ▼ Show 20 Lines | static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) | ||||
| bfd->user = user = read_struct(fd, bhead, "user def"); | bfd->user = user = read_struct(fd, bhead, "user def"); | ||||
| /* User struct has separate do-version handling */ | /* User struct has separate do-version handling */ | ||||
| user->versionfile = bfd->main->versionfile; | user->versionfile = bfd->main->versionfile; | ||||
| user->subversionfile = bfd->main->subversionfile; | user->subversionfile = bfd->main->subversionfile; | ||||
| /* read all data into fd->datamap */ | /* read all data into fd->datamap */ | ||||
| bhead = read_data_into_oldnewmap(fd, bhead, "user def"); | bhead = read_data_into_datamap(fd, bhead, "user def"); | ||||
| link_list(fd, &user->themes); | link_list(fd, &user->themes); | ||||
| link_list(fd, &user->user_keymaps); | link_list(fd, &user->user_keymaps); | ||||
| link_list(fd, &user->user_keyconfig_prefs); | link_list(fd, &user->user_keyconfig_prefs); | ||||
| link_list(fd, &user->user_menus); | link_list(fd, &user->user_menus); | ||||
| link_list(fd, &user->addons); | link_list(fd, &user->addons); | ||||
| link_list(fd, &user->autoexec_paths); | link_list(fd, &user->autoexec_paths); | ||||
| ▲ Show 20 Lines • Show All 2,348 Lines • Show Last 20 Lines | |||||