示例#1
0
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;
}
示例#2
0
/* 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;
}
示例#3
0
/**
 * \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;
}
示例#4
0
/* 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);
    }
}
示例#5
0
/* 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;
}
示例#6
0
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);
}
示例#7
0
/* 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);
	}
}
示例#8
0
/**
 * \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;
}