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 525 Lines • ▼ Show 20 Lines | void blo_split_main(ListBase *mainlist, Main *main) | ||||
| /* (Library.temp_index -> Main), lookup table */ | /* (Library.temp_index -> Main), lookup table */ | ||||
| const unsigned int lib_main_array_len = BLI_listbase_count(&main->library); | const unsigned int lib_main_array_len = BLI_listbase_count(&main->library); | ||||
| Main **lib_main_array = MEM_mallocN(lib_main_array_len * sizeof(*lib_main_array), __func__); | Main **lib_main_array = MEM_mallocN(lib_main_array_len * sizeof(*lib_main_array), __func__); | ||||
| int i = 0; | int i = 0; | ||||
| for (Library *lib = main->library.first; lib; lib = lib->id.next, i++) { | for (Library *lib = main->library.first; lib; lib = lib->id.next, i++) { | ||||
| Main *libmain = BKE_main_new(); | Main *libmain = BKE_main_new(); | ||||
| libmain->curlib = lib; | libmain->curlib = lib; | ||||
| libmain->versionfile = lib->versionfile; | |||||
| libmain->subversionfile = lib->subversionfile; | |||||
| BLI_addtail(mainlist, libmain); | BLI_addtail(mainlist, libmain); | ||||
| lib->temp_index = i; | lib->temp_index = i; | ||||
| lib_main_array[i] = libmain; | lib_main_array[i] = libmain; | ||||
| } | } | ||||
| ListBase *lbarray[MAX_LIBARRAY]; | ListBase *lbarray[MAX_LIBARRAY]; | ||||
| i = set_listbasepointers(main, lbarray); | i = set_listbasepointers(main, lbarray); | ||||
| while (i--) { | while (i--) { | ||||
| Show All 15 Lines | if (bhead->code == GLOB) { | ||||
| main->minversionfile= fg->minversion; | main->minversionfile= fg->minversion; | ||||
| main->minsubversionfile= fg->minsubversion; | main->minsubversionfile= fg->minsubversion; | ||||
| MEM_freeN(fg); | MEM_freeN(fg); | ||||
| } | } | ||||
| else if (bhead->code == ENDB) | else if (bhead->code == ENDB) | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (main->curlib) { | |||||
| main->curlib->versionfile = main->versionfile; | |||||
| main->curlib->subversionfile = main->subversionfile; | |||||
| } | |||||
| } | } | ||||
| #ifdef USE_GHASH_BHEAD | #ifdef USE_GHASH_BHEAD | ||||
| static void read_file_bhead_idname_map_create(FileData *fd) | static void read_file_bhead_idname_map_create(FileData *fd) | ||||
| { | { | ||||
| BHead *bhead; | BHead *bhead; | ||||
| /* dummy values */ | /* dummy values */ | ||||
| ▲ Show 20 Lines • Show All 7,795 Lines • ▼ Show 20 Lines | static void do_versions(FileData *fd, Library *lib, Main *main) | ||||
| blo_do_versions_270(fd, lib, main); | blo_do_versions_270(fd, lib, main); | ||||
| /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ | /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ | ||||
| /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ | /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ | ||||
| /* don't forget to set version number in BKE_blender_version.h! */ | /* don't forget to set version number in BKE_blender_version.h! */ | ||||
| } | } | ||||
| #if 0 // XXX: disabled for now... we still don't have this in the right place in the loading code for it to work | static void do_versions_after_linking(Main *main) | ||||
| static void do_versions_after_linking(FileData *fd, Library *lib, Main *main) | |||||
| { | { | ||||
| /* old Animation System (using IPO's) needs to be converted to the new Animato system */ | // printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name, | ||||
| if (main->versionfile < 250) | // main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile); | ||||
| do_versions_ipos_to_animato(main); | |||||
| } | } | ||||
| #endif | |||||
| static void lib_link_all(FileData *fd, Main *main) | static void lib_link_all(FileData *fd, Main *main) | ||||
| { | { | ||||
| oldnewmap_sort(fd); | oldnewmap_sort(fd); | ||||
| /* No load UI for undo memfiles */ | /* No load UI for undo memfiles */ | ||||
| if (fd->memfile == NULL) { | if (fd->memfile == NULL) { | ||||
| lib_link_windowmanager(fd, main); | lib_link_windowmanager(fd, main); | ||||
| ▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) | ||||
| } | } | ||||
| read_libraries(fd, &mainlist); | read_libraries(fd, &mainlist); | ||||
| blo_join_main(&mainlist); | blo_join_main(&mainlist); | ||||
| lib_link_all(fd, bfd->main); | lib_link_all(fd, bfd->main); | ||||
| //do_versions_after_linking(fd, NULL, bfd->main); // XXX: not here (or even in this function at all)! this causes crashes on many files - Aligorith (July 04, 2010) | /* Skip in undo case. */ | ||||
| if (fd->memfile == NULL) { | |||||
| /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ | |||||
| blo_split_main(&mainlist, bfd->main); | |||||
| for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) { | |||||
| BLI_assert(mainvar->versionfile != 0); | |||||
| do_versions_after_linking(mainvar); | |||||
| } | |||||
| blo_join_main(&mainlist); | |||||
| } | |||||
| BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); | BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); | ||||
| lib_verify_nodetree(bfd->main, true); | lib_verify_nodetree(bfd->main, true); | ||||
| fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ | fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ | ||||
| link_global(fd, bfd); /* as last */ | link_global(fd, bfd); /* as last */ | ||||
| fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */ | fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */ | ||||
| ▲ Show 20 Lines • Show All 1,517 Lines • ▼ Show 20 Lines | |||||
| * \return the library Main, to be passed to \a BLO_library_append_named_part as \a mainl. | * \return the library Main, to be passed to \a BLO_library_append_named_part as \a mainl. | ||||
| */ | */ | ||||
| Main *BLO_library_link_begin(Main *mainvar, BlendHandle **bh, const char *filepath) | Main *BLO_library_link_begin(Main *mainvar, BlendHandle **bh, const char *filepath) | ||||
| { | { | ||||
| FileData *fd = (FileData*)(*bh); | FileData *fd = (FileData*)(*bh); | ||||
| return library_link_begin(mainvar, &fd, filepath); | return library_link_begin(mainvar, &fd, filepath); | ||||
| } | } | ||||
| static void split_main_newid(Main *mainptr, Main *main_newid) | |||||
| { | |||||
| /* We only copy the necessary subset of data in this temp main. */ | |||||
| main_newid->versionfile = mainptr->versionfile; | |||||
| main_newid->subversionfile = mainptr->subversionfile; | |||||
| BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name)); | |||||
| main_newid->curlib = mainptr->curlib; | |||||
| ListBase *lbarray[MAX_LIBARRAY]; | |||||
| ListBase *lbarray_newid[MAX_LIBARRAY]; | |||||
| int i = set_listbasepointers(mainptr, lbarray); | |||||
| set_listbasepointers(main_newid, lbarray_newid); | |||||
| while (i--) { | |||||
| BLI_listbase_clear(lbarray_newid[i]); | |||||
| for (ID *id = lbarray[i]->first, *idnext; id; id = idnext) { | |||||
| idnext = id->next; | |||||
| if (id->tag & LIB_TAG_NEW) { | |||||
| BLI_remlink(lbarray[i], id); | |||||
| BLI_addtail(lbarray_newid[i], id); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* scene and v3d may be NULL. */ | /* scene and v3d may be NULL. */ | ||||
| static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, View3D *v3d) | static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, View3D *v3d) | ||||
| { | { | ||||
| Main *mainvar; | Main *mainvar; | ||||
| Library *curlib; | Library *curlib; | ||||
| /* expander now is callback function */ | /* expander now is callback function */ | ||||
| BLO_main_expander(expand_doit_library); | BLO_main_expander(expand_doit_library); | ||||
| Show All 12 Lines | if (flag & FILE_RELPATH) { | ||||
| BLI_strncpy(curlib->name, curlib->filepath, sizeof(curlib->name)); | BLI_strncpy(curlib->name, curlib->filepath, sizeof(curlib->name)); | ||||
| /* uses current .blend file as reference */ | /* uses current .blend file as reference */ | ||||
| BLI_path_rel(curlib->name, G.main->name); | BLI_path_rel(curlib->name, G.main->name); | ||||
| } | } | ||||
| blo_join_main((*fd)->mainlist); | blo_join_main((*fd)->mainlist); | ||||
| mainvar = (*fd)->mainlist->first; | mainvar = (*fd)->mainlist->first; | ||||
| MEM_freeN((*fd)->mainlist); | |||||
| mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ | mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ | ||||
| lib_link_all(*fd, mainvar); | lib_link_all(*fd, mainvar); | ||||
| /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ | |||||
sergey: Can this be de-duplicated with the code above? | |||||
mont29AuthorUnsubmitted Not Done Inline ActionsEeeeh… not sure I understand what you mean? deduplicated with which code? mont29: Eeeeh… not sure I understand what you mean? deduplicated with which code? | |||||
sergeyUnsubmitted Not Done Inline ActionsTwo chunks above, below /* Skip in undo case. */ sergey: Two chunks above, below `/* Skip in undo case. */` | |||||
mont29AuthorUnsubmitted Not Done Inline Actionswelll… for linking we have to only work on 'new' linked IDs (split them into own main), which we do not have to do in main file reading. Also, for lib linking we always skip the first of split mains (which is local file). Sure we can factorize that into a function with a 'do_lib' bool to switch behaviors, but not sure it’s be worth it, given the length of the code here? mont29: welll… for linking we have to only work on 'new' linked IDs (split them into own main), which… | |||||
sergeyUnsubmitted Not Done Inline ActionsWell, if it's different logic then just keep it as is. Just mentioned this because code looked suspeciosly similar. sergey: Well, if it's different logic then just keep it as is.
Just mentioned this because code looked… | |||||
| blo_split_main((*fd)->mainlist, mainvar); | |||||
| Main main_newid = {0}; | |||||
| for (mainvar = ((Main *)(*fd)->mainlist->first)->next; mainvar; mainvar = mainvar->next) { | |||||
| BLI_assert(mainvar->versionfile != 0); | |||||
| /* We need to split out IDs already existing, or they will go again through do_versions - bad, very bad! */ | |||||
| split_main_newid(mainvar, &main_newid); | |||||
| do_versions_after_linking(&main_newid); | |||||
| add_main_to_main(mainvar, &main_newid); | |||||
| } | |||||
| blo_join_main((*fd)->mainlist); | |||||
| mainvar = (*fd)->mainlist->first; | |||||
| MEM_freeN((*fd)->mainlist); | |||||
| BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); | BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); | ||||
| lib_verify_nodetree(mainvar, false); | lib_verify_nodetree(mainvar, false); | ||||
| fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ | fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ | ||||
| /* Give a base to loose objects. If group append, do it for objects too. | /* Give a base to loose objects. If group append, do it for objects too. | ||||
| * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co, | * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co, | ||||
| * here we handle indirect ones and other possible edge-cases. */ | * here we handle indirect ones and other possible edge-cases. */ | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | for (id = lbarray[a]->first; id; id = id->next) { | ||||
| if (id->tag & tag) { | if (id->tag & tag) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static void split_main_newid(Main *mainptr, Main *main_newid) | |||||
| { | |||||
| /* We only copy the necessary subset of data in this temp main. */ | |||||
| main_newid->versionfile = mainptr->versionfile; | |||||
| main_newid->subversionfile = mainptr->subversionfile; | |||||
| BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name)); | |||||
| main_newid->curlib = mainptr->curlib; | |||||
| ListBase *lbarray[MAX_LIBARRAY]; | |||||
| ListBase *lbarray_newid[MAX_LIBARRAY]; | |||||
| int i = set_listbasepointers(mainptr, lbarray); | |||||
| set_listbasepointers(main_newid, lbarray_newid); | |||||
| while (i--) { | |||||
| BLI_listbase_clear(lbarray_newid[i]); | |||||
| for (ID *id = lbarray[i]->first, *idnext; id; id = idnext) { | |||||
| idnext = id->next; | |||||
| if (id->tag & LIB_TAG_NEW) { | |||||
| BLI_remlink(lbarray[i], id); | |||||
| BLI_addtail(lbarray_newid[i], id); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| static void read_libraries(FileData *basefd, ListBase *mainlist) | static void read_libraries(FileData *basefd, ListBase *mainlist) | ||||
| { | { | ||||
| Main *mainl = mainlist->first; | Main *mainl = mainlist->first; | ||||
| Main *mainptr; | Main *mainptr; | ||||
| ListBase *lbarray[MAX_LIBARRAY]; | ListBase *lbarray[MAX_LIBARRAY]; | ||||
| int a; | int a; | ||||
| bool do_it = true; | bool do_it = true; | ||||
| ▲ Show 20 Lines • Show All 208 Lines • Show Last 20 Lines | |||||
Can this be de-duplicated with the code above?