int new_id(ListBase *lb, ID *id, const char *tname) { int result; char name[MAX_ID_NAME - 2]; /* if library, don't rename */ if (id->lib) return 0; /* if no libdata given, look up based on ID */ if (lb == NULL) lb = which_libbase(G.main, GS(id->name)); /* if no name given, use name of current ID * else make a copy (tname args can be const) */ if (tname == NULL) tname = id->name + 2; strncpy(name, tname, sizeof(name) - 1); /* if result > MAX_ID_NAME-3, strncpy don't put the final '\0' to name. * easier to assign each time then to check if its needed */ name[sizeof(name) - 1] = 0; if (name[0] == '\0') { /* disallow empty names */ strcpy(name, ID_FALLBACK_NAME); } else { /* disallow non utf8 chars, * the interface checks for this but new ID's based on file names don't */ BLI_utf8_invalid_strip(name, strlen(name)); } result = check_for_dupid(lb, id, name); strcpy(id->name + 2, name); /* This was in 2.43 and previous releases * however all data in blender should be sorted, not just duplicate names * sorting should not hurt, but noting just incause it alters the way other * functions work, so sort every time */ #if 0 if (result) id_sort_by_name(lb, id); #endif id_sort_by_name(lb, id); return result; }
/* frees main in end */ int BKE_copybuffer_save(const char *filename, ReportList *reports) { Main *mainb = MEM_callocN(sizeof(Main), "copybuffer"); ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY]; int a, retval; /* path backup/restore */ void *path_list_backup; const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE); path_list_backup = BKE_bpath_list_backup(G.main, path_list_flag); BLO_main_expander(copybuffer_doit); BLO_expand_main(NULL, G.main); /* move over all tagged blocks */ set_listbasepointers(G.main, fromarray); a = set_listbasepointers(mainb, lbarray); while (a--) { ID *id, *nextid; ListBase *lb1 = lbarray[a], *lb2 = fromarray[a]; for (id = lb2->first; id; id = nextid) { nextid = id->next; if (id->flag & LIB_DOIT) { BLI_remlink(lb2, id); BLI_addtail(lb1, id); } } } /* save the buffer */ retval = BLO_write_file(mainb, filename, G_FILE_RELATIVE_REMAP, reports, NULL); /* move back the main, now sorted again */ set_listbasepointers(G.main, lbarray); a = set_listbasepointers(mainb, fromarray); while (a--) { ID *id; ListBase *lb1 = lbarray[a], *lb2 = fromarray[a]; while ((id = BLI_pophead(lb2))) { BLI_addtail(lb1, id); id_sort_by_name(lb1, id); } } MEM_freeN(mainb); /* set id flag to zero; */ BKE_main_id_flag_all(G.main, LIB_NEED_EXPAND | LIB_DOIT, false); if (path_list_backup) { BKE_bpath_list_restore(G.main, path_list_flag, path_list_backup); BKE_bpath_list_free(path_list_backup); } return retval; }
/** * \return Success. */ bool BKE_blendfile_write_partial( Main *bmain_src, const char *filepath, const int write_flags, ReportList *reports) { Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer"); ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY]; int a, retval; void *path_list_backup = NULL; const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE); if (write_flags & G_FILE_RELATIVE_REMAP) { path_list_backup = BKE_bpath_list_backup(bmain_src, path_list_flag); } BLO_main_expander(blendfile_write_partial_cb); BLO_expand_main(NULL, bmain_src); /* move over all tagged blocks */ set_listbasepointers(bmain_src, lbarray_src); a = set_listbasepointers(bmain_dst, lbarray_dst); while (a--) { ID *id, *nextid; ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a]; for (id = lb_src->first; id; id = nextid) { nextid = id->next; if (id->tag & LIB_TAG_DOIT) { BLI_remlink(lb_src, id); BLI_addtail(lb_dst, id); } } } /* save the buffer */ retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL); /* move back the main, now sorted again */ set_listbasepointers(bmain_src, lbarray_dst); a = set_listbasepointers(bmain_dst, lbarray_src); while (a--) { ID *id; ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a]; while ((id = BLI_pophead(lb_src))) { BLI_addtail(lb_dst, id); id_sort_by_name(lb_dst, id); } } MEM_freeN(bmain_dst); if (path_list_backup) { BKE_bpath_list_restore(bmain_src, path_list_flag, path_list_backup); BKE_bpath_list_free(path_list_backup); } return retval; }
/* if lib!=NULL, only all from lib local * bmain is almost certainly G.main */ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only) { ListBase *lbarray[MAX_LIBARRAY], tempbase = {NULL, NULL}; ID *id, *idn; int a; a = set_listbasepointers(bmain, lbarray); while (a--) { id = lbarray[a]->first; while (id) { id->newid = NULL; idn = id->next; /* id is possibly being inserted again */ /* The check on the second line (LIB_PRE_EXISTING) is done so its * possible to tag data you don't want to be made local, used for * appending data, so any libdata already linked wont become local * (very nasty to discover all your links are lost after appending) * */ if (id->flag & (LIB_EXTERN | LIB_INDIRECT | LIB_NEW) && (untagged_only == 0 || !(id->flag & LIB_PRE_EXISTING))) { if (lib == NULL || id->lib == lib) { if (id->lib) { id_clear_lib_data(bmain, id); /* sets 'id->flag' */ /* why sort alphabetically here but not in * id_clear_lib_data() ? - campbell */ id_sort_by_name(lbarray[a], id); } else { id->flag &= ~(LIB_EXTERN | LIB_INDIRECT | LIB_NEW); } } } id = idn; } /* patch2: make it aphabetically */ while ( (id = tempbase.first) ) { BLI_remlink(&tempbase, id); BLI_addtail(lbarray[a], id); new_id(lbarray[a], id, NULL); } } /* patch 3: make sure library data isn't indirect falsely... */ a = set_listbasepointers(bmain, lbarray); while (a--) { for (id = lbarray[a]->first; id; id = id->next) lib_indirect_test_id(id, lib); } }
/* frees main in end */ int BKE_copybuffer_save(char *filename, ReportList *reports) { Main *mainb = MEM_callocN(sizeof(Main), "copybuffer"); ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY]; int a, retval; BLO_main_expander(copybuffer_doit); BLO_expand_main(NULL, G.main); /* move over all tagged blocks */ set_listbasepointers(G.main, fromarray); a = set_listbasepointers(mainb, lbarray); while (a--) { ID *id, *nextid; ListBase *lb1 = lbarray[a], *lb2 = fromarray[a]; for (id = lb2->first; id; id = nextid) { nextid = id->next; if (id->flag & LIB_DOIT) { BLI_remlink(lb2, id); BLI_addtail(lb1, id); } } } /* save the buffer */ retval = BLO_write_file(mainb, filename, 0, reports, NULL); /* move back the main, now sorted again */ set_listbasepointers(G.main, lbarray); a = set_listbasepointers(mainb, fromarray); while (a--) { ID *id; ListBase *lb1 = lbarray[a], *lb2 = fromarray[a]; while (lb2->first) { id = lb2->first; BLI_remlink(lb2, id); BLI_addtail(lb1, id); id_sort_by_name(lb1, id); } } MEM_freeN(mainb); /* set id flag to zero; */ flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0); return retval; }
void test_idbutton(char *name) { /* called from buttons: when name already exists: call new_id */ ListBase *lb; ID *idtest; lb = which_libbase(G.main, GS(name - 2) ); if (lb == NULL) return; /* search for id */ idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); if (idtest) if (new_id(lb, idtest, name) == 0) id_sort_by_name(lb, idtest); }
/* if lib!=NULL, only all from lib local * bmain is almost certainly G.main */ void BKE_library_make_local(Main *bmain, Library *lib, bool untagged_only) { ListBase *lbarray[MAX_LIBARRAY]; ID *id, *idn; int a; a = set_listbasepointers(bmain, lbarray); while (a--) { id = lbarray[a]->first; while (id) { id->newid = NULL; idn = id->next; /* id is possibly being inserted again */ /* The check on the second line (LIB_PRE_EXISTING) is done so its * possible to tag data you don't want to be made local, used for * appending data, so any libdata already linked wont become local * (very nasty to discover all your links are lost after appending) * */ if (id->flag & (LIB_EXTERN | LIB_INDIRECT | LIB_NEW) && ((untagged_only == false) || !(id->flag & LIB_PRE_EXISTING))) { if (lib == NULL || id->lib == lib) { if (id->lib) { /* for Make Local > All we should be calling id_make_local, * but doing that breaks append (see #36003 and #36006), we * we should make it work with all datablocks and id.us==0 */ id_clear_lib_data(bmain, id); /* sets 'id->flag' */ /* why sort alphabetically here but not in * id_clear_lib_data() ? - campbell */ id_sort_by_name(lbarray[a], id); } else { id->flag &= ~(LIB_EXTERN | LIB_INDIRECT | LIB_NEW); } } } id = idn; } } a = set_listbasepointers(bmain, lbarray); while (a--) { for (id = lbarray[a]->first; id; id = id->next) lib_indirect_test_id(id, lib); } }
/** * \return Success. */ bool BKE_blendfile_write_partial( Main *bmain_src, const char *filepath, const int write_flags, ReportList *reports) { Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer"); ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY]; int a, retval; void *path_list_backup = NULL; const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE); /* This is needed to be able to load that file as a real one later * (otherwise main->name will not be set at read time). */ BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name)); BLO_main_expander(blendfile_write_partial_cb); BLO_expand_main(NULL, bmain_src); /* move over all tagged blocks */ set_listbasepointers(bmain_src, lbarray_src); a = set_listbasepointers(bmain_dst, lbarray_dst); while (a--) { ID *id, *nextid; ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a]; for (id = lb_src->first; id; id = nextid) { nextid = id->next; if (id->tag & LIB_TAG_DOIT) { BLI_remlink(lb_src, id); BLI_addtail(lb_dst, id); } } } /* Backup paths because remap relative will overwrite them. * * NOTE: we do this only on the list of datablocks that we are writing * because the restored full list is not guaranteed to be in the same * order as before, as expected by BKE_bpath_list_restore. * * This happens because id_sort_by_name does not take into account * string case or the library name, so the order is not strictly * defined for two linked datablocks with the same name! */ if (write_flags & G_FILE_RELATIVE_REMAP) { path_list_backup = BKE_bpath_list_backup(bmain_dst, path_list_flag); } /* save the buffer */ retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL); if (path_list_backup) { BKE_bpath_list_restore(bmain_dst, path_list_flag, path_list_backup); BKE_bpath_list_free(path_list_backup); } /* move back the main, now sorted again */ set_listbasepointers(bmain_src, lbarray_dst); a = set_listbasepointers(bmain_dst, lbarray_src); while (a--) { ID *id; ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a]; while ((id = BLI_pophead(lb_src))) { BLI_addtail(lb_dst, id); id_sort_by_name(lb_dst, id); } } MEM_freeN(bmain_dst); return retval; }