diff options
author | Brecht Van Lommel <brecht@blender.org> | 2020-04-03 14:34:12 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2020-04-07 14:19:52 +0300 |
commit | 0aac74f18f2d4de1cdde6ca9bf4f8b9a97085d28 (patch) | |
tree | 1508569e7e189414be9ead7d7c09de82922735ff /source/blender | |
parent | c4def7992b589aaf9f45aca04b5dcb0b760ad36e (diff) |
Cleanup: split off direct_link_id() function
Differential Revision: https://developer.blender.org/D7324
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 365 |
1 files changed, 187 insertions, 178 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 07cd39e2559..3c5908efa3f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -470,8 +470,9 @@ static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *l 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++) { OldNew *entry = &onm->entries[i]; if (entry->nr == 0) { @@ -479,10 +480,7 @@ static void oldnewmap_free_unused(OldNewMap *onm) entry->newp = NULL; } } -} -static void oldnewmap_clear(OldNewMap *onm) -{ onm->capacity_exp = DEFAULT_SIZE_EXP; oldnewmap_clear_map(onm); onm->nentries = 0; @@ -2768,7 +2766,7 @@ static void direct_link_id_override_property_cb(FileData *fd, void *data) 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_collection(FileData *fd, Collection *collection); @@ -2778,7 +2776,8 @@ static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); if (nodetree != NULL && *nodetree != NULL) { *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); } @@ -2786,15 +2785,16 @@ static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) Scene *scene = (Scene *)id; if (scene->master_collection != NULL) { scene->master_collection = newdataadr(fd, scene->master_collection); - direct_link_id(fd, - &scene->master_collection->id, - id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL); + direct_link_id_common(fd, + &scene->master_collection->id, + id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL, + 0); 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*/ if (id->properties) { @@ -2804,10 +2804,8 @@ static void direct_link_id(FileData *fd, ID *id, ID *id_old) } id->py_instance = NULL; - /* That way data-lock reading not going through main read_libblock() - * function are still in a clear tag state. - * (glowering at certain nodetree fake data-lock here...). */ - id->tag = 0; + /* Initialize with provided tag. */ + id->tag = tag; id->flag &= ~LIB_INDIRECT_WEAK_LINK; /* NOTE: It is important to not clear the recalc flags for undo/redo. @@ -8378,7 +8376,7 @@ void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions) static bool direct_link_screen(FileData *fd, bScreen *screen) { - bool wrong_id = false; + bool success = true; screen->regionbase.first = screen->regionbase.last = NULL; screen->context = NULL; @@ -8388,10 +8386,10 @@ static bool direct_link_screen(FileData *fd, bScreen *screen) if (!direct_link_area_map(fd, AREAMAP_FROM_SCREEN(screen))) { printf("Error reading Screen %s... removing it.\n", screen->id.name + 2); - wrong_id = true; + success = false; } - return wrong_id; + return success; } /** \} */ @@ -9227,6 +9225,158 @@ static const char *dataname(short id_code) 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) { bhead = blo_bhead_next(fd, bhead); @@ -9261,15 +9411,8 @@ static BHead *read_libblock(FileData *fd, const bool placeholder_set_indirect_extern, ID **r_id) { - /* this routine reads a libblock and its direct data. Use link functions to connect it all - */ - 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; + /* This routine reads a libblock and its direct data. Lib link functions will + * set points between datablocks. */ /* In undo case, most libs and linked data should be kept as is from previous state * (see BLO_read_from_memfile). @@ -9314,7 +9457,8 @@ static BHead *read_libblock(FileData *fd, DEBUG_PRINTF("... in %s (%s): ", main->curlib ? main->curlib->id.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"); /* Even though we found our linked ID, * there is no guarantee its address is still the same. */ @@ -9335,7 +9479,7 @@ static BHead *read_libblock(FileData *fd, /* read libblock */ 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; BHead *id_bhead = bhead; @@ -9348,7 +9492,7 @@ static BHead *read_libblock(FileData *fd, if (id_bhead->code != ID_LINK_PLACEHOLDER) { /* 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 */ /* TODO: instead of building oldnewmap here we could just quickly check the bheads... could @@ -9442,7 +9586,6 @@ static BHead *read_libblock(FileData *fd, } MEM_freeN(id); - oldnewmap_free_unused(fd->datamap); oldnewmap_clear(fd->datamap); return bhead; @@ -9451,7 +9594,7 @@ static BHead *read_libblock(FileData *fd, } /* do after read_struct, for dna reconstruct */ - lb = which_libbase(main, idcode); + ListBase *lb = which_libbase(main, idcode); if (lb) { /* Some re-used old IDs might also use newly read ones, so we have to check for old memory * addresses for those as well. */ @@ -9487,14 +9630,6 @@ static BHead *read_libblock(FileData *fd, oldnewmap_insert(fd->libmap, id_old, id_target, id_bhead->code); 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 { /* unknown ID type */ @@ -9511,160 +9646,35 @@ static BHead *read_libblock(FileData *fd, return blo_bhead_next(fd, id_bhead); } - 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; + /* Set tag for new datablock to indicate lib linking and versioning needs + * to be done still. */ + int id_tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW; - /* this case cannot be direct_linked: it's just the ID part */ if (id_bhead->code == ID_LINK_PLACEHOLDER) { - /* That way, we know which data-lock needs do_versions (required currently for linking). */ - id->tag = tag | LIB_TAG_ID_LINK_PLACEHOLDER | LIB_TAG_NEED_LINK | LIB_TAG_NEW; + /* Tag to get replaced by the actual linked datablock. */ + id_tag |= LIB_TAG_ID_LINK_PLACEHOLDER; if (placeholder_set_indirect_extern) { if (id->flag & LIB_INDIRECT_WEAK_LINK) { - id->tag |= LIB_TAG_INDIRECT; + id_tag |= LIB_TAG_INDIRECT; } else { - id->tag |= LIB_TAG_EXTERN; + id_tag |= LIB_TAG_EXTERN; } } - - return blo_bhead_next(fd, id_bhead); } - /* init pointers direct data */ - direct_link_id(fd, id, id_old); + /* Read datablock contents. */ + 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). */ - /* Note: doing this after direct_link_id(), which resets that field. */ - id->tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW; - - 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; + /* For placeholders we are done here. */ + if (id_bhead->code == ID_LINK_PLACEHOLDER) { + return blo_bhead_next(fd, id_bhead); } - oldnewmap_free_unused(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. * 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... @@ -10151,7 +10161,6 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) user->edit_studio_light = 0; /* free fd->datamap again */ - oldnewmap_free_unused(fd->datamap); oldnewmap_clear(fd->datamap); return bhead; |