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 464 Lines • ▼ Show 20 Lines | if (id == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (!lib || id->lib) { | if (!lib || id->lib) { | ||||
| return id; | return id; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void oldnewmap_free_unused(OldNewMap *onm) | static void oldnewmap_clear(OldNewMap *onm) | ||||
| { | { | ||||
| /* Free unused data. */ | |||||
| for (int i = 0; i < onm->nentries; i++) { | for (int i = 0; i < onm->nentries; i++) { | ||||
| OldNew *entry = &onm->entries[i]; | OldNew *entry = &onm->entries[i]; | ||||
| if (entry->nr == 0) { | if (entry->nr == 0) { | ||||
| MEM_freeN(entry->newp); | MEM_freeN(entry->newp); | ||||
| entry->newp = NULL; | entry->newp = NULL; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| static void oldnewmap_clear(OldNewMap *onm) | |||||
| { | |||||
| onm->capacity_exp = DEFAULT_SIZE_EXP; | onm->capacity_exp = DEFAULT_SIZE_EXP; | ||||
| oldnewmap_clear_map(onm); | oldnewmap_clear_map(onm); | ||||
| onm->nentries = 0; | onm->nentries = 0; | ||||
| } | } | ||||
| static void oldnewmap_free(OldNewMap *onm) | static void oldnewmap_free(OldNewMap *onm) | ||||
| { | { | ||||
| MEM_freeN(onm->entries); | MEM_freeN(onm->entries); | ||||
| ▲ Show 20 Lines • Show All 2,269 Lines • ▼ Show 20 Lines | |||||
| static void direct_link_id_override_property_cb(FileData *fd, void *data) | static void direct_link_id_override_property_cb(FileData *fd, void *data) | ||||
| { | { | ||||
| IDOverrideLibraryProperty *op = data; | IDOverrideLibraryProperty *op = data; | ||||
| op->rna_path = newdataadr(fd, op->rna_path); | op->rna_path = newdataadr(fd, op->rna_path); | ||||
| link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb); | link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb); | ||||
| } | } | ||||
| static void direct_link_id(FileData *fd, ID *id, ID *id_old); | static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag); | ||||
| static void direct_link_nodetree(FileData *fd, bNodeTree *ntree); | static void direct_link_nodetree(FileData *fd, bNodeTree *ntree); | ||||
| static void direct_link_collection(FileData *fd, Collection *collection); | static void direct_link_collection(FileData *fd, Collection *collection); | ||||
| static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) | static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) | ||||
| { | { | ||||
| /* Handle 'private IDs'. */ | /* Handle 'private IDs'. */ | ||||
| bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); | bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); | ||||
| if (nodetree != NULL && *nodetree != NULL) { | if (nodetree != NULL && *nodetree != NULL) { | ||||
| *nodetree = newdataadr(fd, *nodetree); | *nodetree = newdataadr(fd, *nodetree); | ||||
| direct_link_id(fd, (ID *)*nodetree, id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL); | direct_link_id_common( | ||||
| fd, (ID *)*nodetree, id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL, 0); | |||||
| direct_link_nodetree(fd, *nodetree); | direct_link_nodetree(fd, *nodetree); | ||||
| } | } | ||||
| if (GS(id->name) == ID_SCE) { | if (GS(id->name) == ID_SCE) { | ||||
| Scene *scene = (Scene *)id; | Scene *scene = (Scene *)id; | ||||
| if (scene->master_collection != NULL) { | if (scene->master_collection != NULL) { | ||||
| scene->master_collection = newdataadr(fd, scene->master_collection); | scene->master_collection = newdataadr(fd, scene->master_collection); | ||||
| direct_link_id(fd, | direct_link_id_common(fd, | ||||
| &scene->master_collection->id, | &scene->master_collection->id, | ||||
| id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL); | id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL, | ||||
| 0); | |||||
| direct_link_collection(fd, scene->master_collection); | direct_link_collection(fd, scene->master_collection); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void direct_link_id(FileData *fd, ID *id, ID *id_old) | static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag) | ||||
| { | { | ||||
| /*link direct data of ID properties*/ | /*link direct data of ID properties*/ | ||||
| if (id->properties) { | if (id->properties) { | ||||
| id->properties = newdataadr(fd, id->properties); | id->properties = newdataadr(fd, id->properties); | ||||
| /* this case means the data was written incorrectly, it should not happen */ | /* this case means the data was written incorrectly, it should not happen */ | ||||
| IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); | IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); | ||||
| } | } | ||||
| id->py_instance = NULL; | id->py_instance = NULL; | ||||
| /* That way data-lock reading not going through main read_libblock() | /* Initialize with provided tag. */ | ||||
| * function are still in a clear tag state. | id->tag = tag; | ||||
| * (glowering at certain nodetree fake data-lock here...). */ | |||||
| id->tag = 0; | |||||
| id->flag &= ~LIB_INDIRECT_WEAK_LINK; | id->flag &= ~LIB_INDIRECT_WEAK_LINK; | ||||
| /* NOTE: It is important to not clear the recalc flags for undo/redo. | /* NOTE: It is important to not clear the recalc flags for undo/redo. | ||||
| * Preserving recalc flags on redo/undo is the only way to make dependency graph detect | * Preserving recalc flags on redo/undo is the only way to make dependency graph detect | ||||
| * that animation is to be evaluated on undo/redo. If this is not enforced by the recalc | * that animation is to be evaluated on undo/redo. If this is not enforced by the recalc | ||||
| * flags dependency graph does not do animation update to avoid loss of unkeyed changes., | * flags dependency graph does not do animation update to avoid loss of unkeyed changes., | ||||
| * which conflicts with undo/redo of changes to animation data itself. | * which conflicts with undo/redo of changes to animation data itself. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 5,556 Lines • ▼ Show 20 Lines | void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions) | ||||
| /* this was not initialized correct always */ | /* this was not initialized correct always */ | ||||
| if (v3d->gridsubdiv == 0) { | if (v3d->gridsubdiv == 0) { | ||||
| v3d->gridsubdiv = 10; | v3d->gridsubdiv = 10; | ||||
| } | } | ||||
| } | } | ||||
| static bool direct_link_screen(FileData *fd, bScreen *screen) | static bool direct_link_screen(FileData *fd, bScreen *screen) | ||||
| { | { | ||||
| bool wrong_id = false; | bool success = true; | ||||
| screen->regionbase.first = screen->regionbase.last = NULL; | screen->regionbase.first = screen->regionbase.last = NULL; | ||||
| screen->context = NULL; | screen->context = NULL; | ||||
| screen->active_region = NULL; | screen->active_region = NULL; | ||||
| screen->preview = direct_link_preview_image(fd, screen->preview); | screen->preview = direct_link_preview_image(fd, screen->preview); | ||||
| if (!direct_link_area_map(fd, AREAMAP_FROM_SCREEN(screen))) { | if (!direct_link_area_map(fd, AREAMAP_FROM_SCREEN(screen))) { | ||||
| printf("Error reading Screen %s... removing it.\n", screen->id.name + 2); | printf("Error reading Screen %s... removing it.\n", screen->id.name + 2); | ||||
| wrong_id = true; | success = false; | ||||
| } | } | ||||
| return wrong_id; | return success; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Read ID: Library | /** \name Read ID: Library | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 819 Lines • ▼ Show 20 Lines | switch (id_code) { | ||||
| case ID_PT: | case ID_PT: | ||||
| return "Data from PT"; | return "Data from PT"; | ||||
| case ID_VO: | case ID_VO: | ||||
| return "Data from VO"; | return "Data from VO"; | ||||
| } | } | ||||
| return "Data from Lib Block"; | return "Data from Lib Block"; | ||||
| } | } | ||||
| static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old) | |||||
| { | |||||
| if (fd->memfile == NULL) { | |||||
| /* When actually reading a file , we do want to reset/re-generate session uuids. | |||||
| * In undo case, we want to re-use existing ones. */ | |||||
| id->session_uuid = MAIN_ID_SESSION_UUID_UNSET; | |||||
| } | |||||
| BKE_lib_libblock_session_uuid_ensure(id); | |||||
| id->lib = main->curlib; | |||||
| id->us = ID_FAKE_USERS(id); | |||||
| id->icon_id = 0; | |||||
| id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ | |||||
| id->orig_id = NULL; | |||||
| if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) { | |||||
| /* For placeholder we only need to set the tag, no further data to read. */ | |||||
| id->tag = tag; | |||||
| return true; | |||||
| } | |||||
| /* Read part of datablock that is common between real and embedded datablocks. */ | |||||
| direct_link_id_common(fd, id, id_old, tag); | |||||
| /* XXX Very weakly handled currently, see comment in read_libblock() before trying to | |||||
| * use it for anything new. */ | |||||
| bool success = true; | |||||
| switch (GS(id->name)) { | |||||
| case ID_WM: | |||||
| direct_link_windowmanager(fd, (wmWindowManager *)id); | |||||
| break; | |||||
| case ID_SCR: | |||||
| success = direct_link_screen(fd, (bScreen *)id); | |||||
| break; | |||||
| case ID_SCE: | |||||
| direct_link_scene(fd, (Scene *)id); | |||||
| break; | |||||
| case ID_OB: | |||||
| direct_link_object(fd, (Object *)id); | |||||
| break; | |||||
| case ID_ME: | |||||
| direct_link_mesh(fd, (Mesh *)id); | |||||
| break; | |||||
| case ID_CU: | |||||
| direct_link_curve(fd, (Curve *)id); | |||||
| break; | |||||
| case ID_MB: | |||||
| direct_link_mball(fd, (MetaBall *)id); | |||||
| break; | |||||
| case ID_MA: | |||||
| direct_link_material(fd, (Material *)id); | |||||
| break; | |||||
| case ID_TE: | |||||
| direct_link_texture(fd, (Tex *)id); | |||||
| break; | |||||
| case ID_IM: | |||||
| direct_link_image(fd, (Image *)id); | |||||
| break; | |||||
| case ID_LA: | |||||
| direct_link_light(fd, (Light *)id); | |||||
| break; | |||||
| case ID_VF: | |||||
| direct_link_vfont(fd, (VFont *)id); | |||||
| break; | |||||
| case ID_TXT: | |||||
| direct_link_text(fd, (Text *)id); | |||||
| break; | |||||
| case ID_IP: | |||||
| direct_link_ipo(fd, (Ipo *)id); | |||||
| break; | |||||
| case ID_KE: | |||||
| direct_link_key(fd, (Key *)id); | |||||
| break; | |||||
| case ID_LT: | |||||
| direct_link_latt(fd, (Lattice *)id); | |||||
| break; | |||||
| case ID_WO: | |||||
| direct_link_world(fd, (World *)id); | |||||
| break; | |||||
| case ID_LI: | |||||
| direct_link_library(fd, (Library *)id, main); | |||||
| break; | |||||
| case ID_CA: | |||||
| direct_link_camera(fd, (Camera *)id); | |||||
| break; | |||||
| case ID_SPK: | |||||
| direct_link_speaker(fd, (Speaker *)id); | |||||
| break; | |||||
| case ID_SO: | |||||
| direct_link_sound(fd, (bSound *)id); | |||||
| break; | |||||
| case ID_LP: | |||||
| direct_link_lightprobe(fd, (LightProbe *)id); | |||||
| break; | |||||
| case ID_GR: | |||||
| direct_link_collection(fd, (Collection *)id); | |||||
| break; | |||||
| case ID_AR: | |||||
| direct_link_armature(fd, (bArmature *)id); | |||||
| break; | |||||
| case ID_AC: | |||||
| direct_link_action(fd, (bAction *)id); | |||||
| break; | |||||
| case ID_NT: | |||||
| direct_link_nodetree(fd, (bNodeTree *)id); | |||||
| break; | |||||
| case ID_BR: | |||||
| direct_link_brush(fd, (Brush *)id); | |||||
| break; | |||||
| case ID_PA: | |||||
| direct_link_particlesettings(fd, (ParticleSettings *)id); | |||||
| break; | |||||
| case ID_GD: | |||||
| direct_link_gpencil(fd, (bGPdata *)id); | |||||
| break; | |||||
| case ID_MC: | |||||
| direct_link_movieclip(fd, (MovieClip *)id); | |||||
| break; | |||||
| case ID_MSK: | |||||
| direct_link_mask(fd, (Mask *)id); | |||||
| break; | |||||
| case ID_LS: | |||||
| direct_link_linestyle(fd, (FreestyleLineStyle *)id); | |||||
| break; | |||||
| case ID_PAL: | |||||
| direct_link_palette(fd, (Palette *)id); | |||||
| break; | |||||
| case ID_PC: | |||||
| direct_link_paint_curve(fd, (PaintCurve *)id); | |||||
| break; | |||||
| case ID_CF: | |||||
| direct_link_cachefile(fd, (CacheFile *)id); | |||||
| break; | |||||
| case ID_WS: | |||||
| direct_link_workspace(fd, (WorkSpace *)id, main); | |||||
| break; | |||||
| case ID_HA: | |||||
| direct_link_hair(fd, (Hair *)id); | |||||
| break; | |||||
| case ID_PT: | |||||
| direct_link_pointcloud(fd, (PointCloud *)id); | |||||
| break; | |||||
| case ID_VO: | |||||
| direct_link_volume(fd, (Volume *)id); | |||||
| break; | |||||
| } | |||||
| return success; | |||||
| } | |||||
| static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *allocname) | static BHead *read_data_into_oldnewmap(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 */ | ||||
| Show All 18 Lines | |||||
| static BHead *read_libblock(FileData *fd, | static BHead *read_libblock(FileData *fd, | ||||
| Main *main, | Main *main, | ||||
| BHead *bhead, | BHead *bhead, | ||||
| const int tag, | const int tag, | ||||
| const bool placeholder_set_indirect_extern, | const bool placeholder_set_indirect_extern, | ||||
| ID **r_id) | ID **r_id) | ||||
| { | { | ||||
| /* this routine reads a libblock and its direct data. Use link functions to connect it all | /* This routine reads a libblock and its direct data. Lib link functions will | ||||
| */ | * set points between datablocks. */ | ||||
mont29: points -> pointers? | |||||
| ID *id; | |||||
| ListBase *lb; | |||||
| const char *allocname; | |||||
| /* XXX Very weakly handled currently, see comment at the end of this function before trying to | |||||
| * use it for anything new. */ | |||||
| bool wrong_id = false; | |||||
| /* 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, | ||||
| Show All 28 Lines | if (bhead->code == ID_LI) { | ||||
| } | } | ||||
| DEBUG_PRINTF("nothing...\n"); | DEBUG_PRINTF("nothing...\n"); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| DEBUG_PRINTF("... in %s (%s): ", | DEBUG_PRINTF("... in %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>"); | ||||
| if ((id = BKE_libblock_find_name(main, GS(idname), idname + 2))) { | ID *id = BKE_libblock_find_name(main, GS(idname), idname + 2); | ||||
| if (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 (id != bhead->old) { | if (id != bhead->old) { | ||||
| oldnewmap_insert(fd->libmap, bhead->old, id, GS(id->name)); | oldnewmap_insert(fd->libmap, bhead->old, id, GS(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. */ | ||||
| if (r_id) { | if (r_id) { | ||||
| *r_id = NULL; /* Just in case... */ | *r_id = NULL; /* Just in case... */ | ||||
| } | } | ||||
| return blo_bhead_next(fd, bhead); | return blo_bhead_next(fd, bhead); | ||||
| } | } | ||||
| DEBUG_PRINTF("nothing...\n"); | DEBUG_PRINTF("nothing...\n"); | ||||
| } | } | ||||
| } | } | ||||
| /* read libblock */ | /* read libblock */ | ||||
| fd->are_memchunks_identical = true; | fd->are_memchunks_identical = true; | ||||
| id = read_struct(fd, bhead, "lib block"); | ID *id = read_struct(fd, bhead, "lib block"); | ||||
| const short idcode = id != NULL ? GS(id->name) : 0; | const short idcode = id != NULL ? GS(id->name) : 0; | ||||
| BHead *id_bhead = bhead; | BHead *id_bhead = bhead; | ||||
| /* 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 (id != NULL) { | if (id != NULL) { | ||||
| 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; | ||||
| 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 */ | ||||
| allocname = dataname(idcode); | const char *allocname = dataname(idcode); | ||||
| /* read all data into fd->datamap */ | /* read all data into fd->datamap */ | ||||
| /* TODO: instead of building oldnewmap here we could just quickly check the bheads... could | /* TODO: 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 depsgraph rebuild | * save some more ticks. Probably not worth it though, bottleneck is full depsgraph rebuild | ||||
| * and evaluate, not actual file reading. */ | * and evaluate, not actual file reading. */ | ||||
| bhead = read_data_into_oldnewmap(fd, id_bhead, allocname); | bhead = read_data_into_oldnewmap(fd, id_bhead, allocname); | ||||
| DEBUG_PRINTF( | DEBUG_PRINTF( | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | if (id_bhead->code != ID_LINK_PLACEHOLDER) { | ||||
| /* We need to 'accumulate' the accumulated recalc flags of all undo steps until we | /* We need to 'accumulate' the accumulated recalc flags of all undo steps until we | ||||
| * actually perform a depsgraph update, otherwise we'd only ever use the flags from one | * actually perform a depsgraph update, otherwise we'd only ever use the flags from one | ||||
| * of the steps, and never get proper flags matching all others. */ | * of the steps, and never get proper flags matching all others. */ | ||||
| id_old->recalc_undo_accumulated |= id->recalc_undo_accumulated; | id_old->recalc_undo_accumulated |= id->recalc_undo_accumulated; | ||||
| } | } | ||||
| MEM_freeN(id); | MEM_freeN(id); | ||||
| oldnewmap_free_unused(fd->datamap); | |||||
| oldnewmap_clear(fd->datamap); | oldnewmap_clear(fd->datamap); | ||||
| return bhead; | return bhead; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* do after read_struct, for dna reconstruct */ | /* do after read_struct, for dna reconstruct */ | ||||
| lb = which_libbase(main, idcode); | ListBase *lb = which_libbase(main, idcode); | ||||
| if (lb) { | if (lb) { | ||||
| /* Some re-used old IDs might also use newly read ones, so we have to check for old memory | /* Some re-used old IDs might also use newly read ones, so we have to check for old memory | ||||
| * addresses for those as well. */ | * addresses for those as well. */ | ||||
| if (fd->memfile != NULL && do_partial_undo && id->lib == NULL) { | if (fd->memfile != NULL && do_partial_undo && id->lib == NULL) { | ||||
| BLI_assert(fd->old_idmap != NULL); | BLI_assert(fd->old_idmap != NULL); | ||||
| 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); | ||||
| Show All 19 Lines | if (lb) { | ||||
| } | } | ||||
| /* for ID_LINK_PLACEHOLDER check */ | /* for ID_LINK_PLACEHOLDER check */ | ||||
| ID *id_target = do_id_swap ? id_old : id; | ID *id_target = do_id_swap ? id_old : id; | ||||
| oldnewmap_insert(fd->libmap, id_bhead->old, id_target, id_bhead->code); | oldnewmap_insert(fd->libmap, id_bhead->old, id_target, id_bhead->code); | ||||
| oldnewmap_insert(fd->libmap, id_old, id_target, id_bhead->code); | oldnewmap_insert(fd->libmap, id_old, id_target, id_bhead->code); | ||||
| BLI_addtail(lb, id); | BLI_addtail(lb, id); | ||||
| if (fd->memfile == NULL) { | |||||
| /* When actually reading a file , we do want to reset/re-generate session uuids. | |||||
| * In unod case, we want to re-use existing ones. */ | |||||
| id->session_uuid = MAIN_ID_SESSION_UUID_UNSET; | |||||
| } | |||||
| BKE_lib_libblock_session_uuid_ensure(id); | |||||
| } | } | ||||
| else { | else { | ||||
| /* unknown ID type */ | /* unknown ID type */ | ||||
| printf("%s: unknown id code '%c%c'\n", __func__, (idcode & 0xff), (idcode >> 8)); | printf("%s: unknown id code '%c%c'\n", __func__, (idcode & 0xff), (idcode >> 8)); | ||||
| MEM_freeN(id); | MEM_freeN(id); | ||||
| id = NULL; | id = NULL; | ||||
| } | } | ||||
| } | } | ||||
| if (r_id) { | if (r_id) { | ||||
| *r_id = do_id_swap ? id_old : id; | *r_id = do_id_swap ? id_old : id; | ||||
| } | } | ||||
| if (!id) { | if (!id) { | ||||
| return blo_bhead_next(fd, id_bhead); | return blo_bhead_next(fd, id_bhead); | ||||
| } | } | ||||
| id->lib = main->curlib; | /* Set tag for new datablock to indicate lib linking and versioning needs | ||||
| id->us = ID_FAKE_USERS(id); | * to be done still. */ | ||||
| id->icon_id = 0; | int id_tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW; | ||||
| id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ | |||||
| id->orig_id = NULL; | |||||
| /* this case cannot be direct_linked: it's just the ID part */ | |||||
| if (id_bhead->code == ID_LINK_PLACEHOLDER) { | if (id_bhead->code == ID_LINK_PLACEHOLDER) { | ||||
| /* That way, we know which data-lock needs do_versions (required currently for linking). */ | /* Tag to get replaced by the actual linked datablock. */ | ||||
| id->tag = tag | LIB_TAG_ID_LINK_PLACEHOLDER | LIB_TAG_NEED_LINK | LIB_TAG_NEW; | id_tag |= LIB_TAG_ID_LINK_PLACEHOLDER; | ||||
| if (placeholder_set_indirect_extern) { | if (placeholder_set_indirect_extern) { | ||||
| if (id->flag & LIB_INDIRECT_WEAK_LINK) { | if (id->flag & LIB_INDIRECT_WEAK_LINK) { | ||||
| id->tag |= LIB_TAG_INDIRECT; | id_tag |= LIB_TAG_INDIRECT; | ||||
| } | } | ||||
| else { | else { | ||||
| id->tag |= LIB_TAG_EXTERN; | id_tag |= LIB_TAG_EXTERN; | ||||
| } | } | ||||
| } | } | ||||
| return blo_bhead_next(fd, id_bhead); | |||||
| } | } | ||||
| /* init pointers direct data */ | /* Read datablock contents. */ | ||||
| direct_link_id(fd, id, id_old); | const bool success = direct_link_id(fd, main, id_tag, id, id_old); | ||||
| /* That way, we know which data-lock needs do_versions (required currently for linking). */ | /* For placeholders we are done here. */ | ||||
| /* Note: doing this after direct_link_id(), which resets that field. */ | if (id_bhead->code == ID_LINK_PLACEHOLDER) { | ||||
| id->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW; | return blo_bhead_next(fd, id_bhead); | ||||
| switch (idcode) { | |||||
| case ID_WM: | |||||
| direct_link_windowmanager(fd, (wmWindowManager *)id); | |||||
| break; | |||||
| case ID_SCR: | |||||
| wrong_id = direct_link_screen(fd, (bScreen *)id); | |||||
| break; | |||||
| case ID_SCE: | |||||
| direct_link_scene(fd, (Scene *)id); | |||||
| break; | |||||
| case ID_OB: | |||||
| direct_link_object(fd, (Object *)id); | |||||
| break; | |||||
| case ID_ME: | |||||
| direct_link_mesh(fd, (Mesh *)id); | |||||
| break; | |||||
| case ID_CU: | |||||
| direct_link_curve(fd, (Curve *)id); | |||||
| break; | |||||
| case ID_MB: | |||||
| direct_link_mball(fd, (MetaBall *)id); | |||||
| break; | |||||
| case ID_MA: | |||||
| direct_link_material(fd, (Material *)id); | |||||
| break; | |||||
| case ID_TE: | |||||
| direct_link_texture(fd, (Tex *)id); | |||||
| break; | |||||
| case ID_IM: | |||||
| direct_link_image(fd, (Image *)id); | |||||
| break; | |||||
| case ID_LA: | |||||
| direct_link_light(fd, (Light *)id); | |||||
| break; | |||||
| case ID_VF: | |||||
| direct_link_vfont(fd, (VFont *)id); | |||||
| break; | |||||
| case ID_TXT: | |||||
| direct_link_text(fd, (Text *)id); | |||||
| break; | |||||
| case ID_IP: | |||||
| direct_link_ipo(fd, (Ipo *)id); | |||||
| break; | |||||
| case ID_KE: | |||||
| direct_link_key(fd, (Key *)id); | |||||
| break; | |||||
| case ID_LT: | |||||
| direct_link_latt(fd, (Lattice *)id); | |||||
| break; | |||||
| case ID_WO: | |||||
| direct_link_world(fd, (World *)id); | |||||
| break; | |||||
| case ID_LI: | |||||
| direct_link_library(fd, (Library *)id, main); | |||||
| break; | |||||
| case ID_CA: | |||||
| direct_link_camera(fd, (Camera *)id); | |||||
| break; | |||||
| case ID_SPK: | |||||
| direct_link_speaker(fd, (Speaker *)id); | |||||
| break; | |||||
| case ID_SO: | |||||
| direct_link_sound(fd, (bSound *)id); | |||||
| break; | |||||
| case ID_LP: | |||||
| direct_link_lightprobe(fd, (LightProbe *)id); | |||||
| break; | |||||
| case ID_GR: | |||||
| direct_link_collection(fd, (Collection *)id); | |||||
| break; | |||||
| case ID_AR: | |||||
| direct_link_armature(fd, (bArmature *)id); | |||||
| break; | |||||
| case ID_AC: | |||||
| direct_link_action(fd, (bAction *)id); | |||||
| break; | |||||
| case ID_NT: | |||||
| direct_link_nodetree(fd, (bNodeTree *)id); | |||||
| break; | |||||
| case ID_BR: | |||||
| direct_link_brush(fd, (Brush *)id); | |||||
| break; | |||||
| case ID_PA: | |||||
| direct_link_particlesettings(fd, (ParticleSettings *)id); | |||||
| break; | |||||
| case ID_GD: | |||||
| direct_link_gpencil(fd, (bGPdata *)id); | |||||
| break; | |||||
| case ID_MC: | |||||
| direct_link_movieclip(fd, (MovieClip *)id); | |||||
| break; | |||||
| case ID_MSK: | |||||
| direct_link_mask(fd, (Mask *)id); | |||||
| break; | |||||
| case ID_LS: | |||||
| direct_link_linestyle(fd, (FreestyleLineStyle *)id); | |||||
| break; | |||||
| case ID_PAL: | |||||
| direct_link_palette(fd, (Palette *)id); | |||||
| break; | |||||
| case ID_PC: | |||||
| direct_link_paint_curve(fd, (PaintCurve *)id); | |||||
| break; | |||||
| case ID_CF: | |||||
| direct_link_cachefile(fd, (CacheFile *)id); | |||||
| break; | |||||
| case ID_WS: | |||||
| direct_link_workspace(fd, (WorkSpace *)id, main); | |||||
| break; | |||||
| case ID_HA: | |||||
| direct_link_hair(fd, (Hair *)id); | |||||
| break; | |||||
| case ID_PT: | |||||
| direct_link_pointcloud(fd, (PointCloud *)id); | |||||
| break; | |||||
| case ID_VO: | |||||
| direct_link_volume(fd, (Volume *)id); | |||||
| break; | |||||
| } | } | ||||
| oldnewmap_free_unused(fd->datamap); | |||||
| oldnewmap_clear(fd->datamap); | oldnewmap_clear(fd->datamap); | ||||
| if (wrong_id) { | if (!success) { | ||||
| /* XXX This is probably working OK currently given the very limited scope of that flag. | /* XXX This is probably working OK currently given the very limited scope of that flag. | ||||
| * However, it is absolutely **not** handled correctly: it is freeing an ID pointer that has | * However, it is absolutely **not** handled correctly: it is freeing an ID pointer that has | ||||
| * been added to the fd->libmap mapping, which in theory could lead to nice crashes... | * been added to the fd->libmap mapping, which in theory could lead to nice crashes... | ||||
| * This should be properly solved at some point. */ | * This should be properly solved at some point. */ | ||||
| BKE_id_free(main, id); | BKE_id_free(main, id); | ||||
| if (r_id != NULL) { | if (r_id != NULL) { | ||||
| *r_id = NULL; | *r_id = NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 470 Lines • ▼ Show 20 Lines | static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) | ||||
| /* Don't read the active app template, use the default one. */ | /* Don't read the active app template, use the default one. */ | ||||
| user->app_template[0] = '\0'; | user->app_template[0] = '\0'; | ||||
| /* Clear runtime data. */ | /* Clear runtime data. */ | ||||
| user->runtime.is_dirty = false; | user->runtime.is_dirty = false; | ||||
| user->edit_studio_light = 0; | user->edit_studio_light = 0; | ||||
| /* free fd->datamap again */ | /* free fd->datamap again */ | ||||
| oldnewmap_free_unused(fd->datamap); | |||||
| oldnewmap_clear(fd->datamap); | oldnewmap_clear(fd->datamap); | ||||
| return bhead; | return bhead; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| ▲ Show 20 Lines • Show All 2,281 Lines • Show Last 20 Lines | |||||
points -> pointers?