/** * Pull an ID out of a library (make it local). Only call this for IDs that * don't have other library users. */ void id_clear_lib_data(Main *bmain, ID *id) { bNodeTree *ntree = NULL; BKE_id_lib_local_paths(bmain, id->lib, id); if (id->flag & LIB_FAKEUSER) { id->us--; id->flag &= ~LIB_FAKEUSER; } id->lib = NULL; id->flag = LIB_LOCAL; new_id(which_libbase(bmain, GS(id->name)), id, NULL); /* internal bNodeTree blocks inside ID types below * also stores id->lib, make sure this stays in sync. */ switch (GS(id->name)) { case ID_SCE: ntree = ((Scene *)id)->nodetree; break; case ID_MA: ntree = ((Material *)id)->nodetree; break; case ID_LA: ntree = ((Lamp *)id)->nodetree; break; case ID_WO: ntree = ((World *)id)->nodetree; break; case ID_TE: ntree = ((Tex *)id)->nodetree; break; } if (ntree) ntree->id.lib = NULL; }
int id_unlink(ID *id, int test) { Main *mainlib= G.main; ListBase *lb; switch(GS(id->name)) { case ID_TXT: if(test) return 1; unlink_text(mainlib, (Text*)id); break; case ID_GR: if(test) return 1; unlink_group((Group*)id); break; case ID_OB: if(test) return 1; unlink_object((Object*)id); break; } if(id->us == 0) { if(test) return 1; lb= which_libbase(mainlib, GS(id->name)); free_libblock(lb, id); return 1; } return 0; }
/** * Rename if the ID doesn't exist. */ static ID *rename_id_for_versioning(Main *bmain, const short id_type, const char *name_src, const char *name_dst) { /* We can ignore libraries */ ListBase *lb = which_libbase(bmain, id_type); ID *id = NULL; for (ID *idtest = lb->first; idtest; idtest = idtest->next) { if (idtest->lib == NULL) { if (STREQ(idtest->name + 2, name_src)) { id = idtest; } if (STREQ(idtest->name + 2, name_dst)) { return NULL; } } } if (id != NULL) { BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); /* We know it's unique, this just sorts. */ BLI_libblock_ensure_unique_name(bmain, id->name); } return id; }
/* used everywhere in blenkernel */ void *BKE_libblock_copy_ex(Main *bmain, ID *id) { ID *idn; ListBase *lb; size_t idn_len; lb = which_libbase(bmain, GS(id->name)); idn = BKE_libblock_alloc(lb, GS(id->name), id->name + 2); assert(idn != NULL); idn_len = MEM_allocN_len(idn); if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ const char *cp = (const char *)id; char *cpn = (char *)idn; memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID)); } id->newid = idn; idn->flag |= LIB_NEW; BKE_libblock_copy_data(idn, id, false); return idn; }
bool id_unlink(ID *id, int test) { Main *mainlib = G.main; ListBase *lb; switch (GS(id->name)) { case ID_TXT: if (test) return true; BKE_text_unlink(mainlib, (Text *)id); break; case ID_GR: if (test) return true; BKE_group_unlink((Group *)id); break; case ID_OB: if (test) return true; BKE_object_unlink((Object *)id); break; } if (id->us == 0) { if (test) return true; lb = which_libbase(mainlib, GS(id->name)); BKE_libblock_free(lb, id); return true; } return false; }
/* used everywhere in blenkernel */ void *copy_libblock(void *rt) { ID *idn, *id; ListBase *lb; char *cp, *cpn; size_t idn_len; id= rt; lb= which_libbase(G.main, GS(id->name)); idn= alloc_libblock(lb, GS(id->name), id->name+2); assert(idn != NULL); idn_len= MEM_allocN_len(idn); if((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ cp= (char *)id; cpn= (char *)idn; memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID)); } id->newid= idn; idn->flag |= LIB_NEW; copy_libblock_data(idn, id, FALSE); return idn; }
/* Pull an ID out of a library (make it local). Only call this for IDs that * don't have other library users. */ void id_clear_lib_data(Main *bmain, ID *id) { BKE_id_lib_local_paths(bmain, id->lib, id); id->lib = NULL; id->flag = LIB_LOCAL; new_id(which_libbase(bmain, GS(id->name)), id, NULL); }
void rename_id(ID *id, const char *name) { ListBase *lb; BLI_strncpy(id->name+2, name, sizeof(id->name)-2); lb= which_libbase(G.main, GS(id->name) ); new_id(lb, id, name); }
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 ) sort_alpha_id(lb, idtest); }
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; }
/** * Allocates and returns a block of the specified type, with the specified name * (adjusted as necessary to ensure uniqueness), and appended to the specified list. * The user count is set to 1, all other content (apart from name and links) being * initialized to zero. */ void *BKE_libblock_alloc(Main *bmain, short type, const char *name) { ID *id = NULL; ListBase *lb = which_libbase(bmain, type); id = alloc_libblock_notest(type); if (id) { BLI_addtail(lb, id); id->us = 1; id->icon_id = 0; *( (short *)id->name) = type; new_id(lb, id, name); /* alphabetic insertion: is in new_id */ } DAG_id_type_tag(bmain, type); return id; }
/* medium match strictness: path match only (i.e. ignore ID) */ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short from_single, const short UNUSED(to_simple)) { tAnimCopybufItem *aci; for (aci= animcopybuf.first; aci; aci= aci->next) { /* check that paths exist */ if (aci->rna_path && fcu->rna_path) { /* find the property of the fcurve and compare against the end of the tAnimCopybufItem * more involved since it needs to to path lookups. * This is not 100% reliable since the user could be editing the curves on a path that wont * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste * this should work out ok. */ if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) { /* pedantic but the ID could have been removed, and beats crashing! */ printf("paste_animedit_keys: error ID has been removed!\n"); } else { PointerRNA id_ptr, rptr; PropertyRNA *prop; RNA_id_pointer_create(aci->id, &id_ptr); RNA_path_resolve(&id_ptr, aci->rna_path, &rptr, &prop); if (prop) { const char *identifier= RNA_property_identifier(prop); int len_id = strlen(identifier); int len_path = strlen(fcu->rna_path); if (len_id <= len_path) { /* note, paths which end with "] will fail with this test - Animated ID Props */ if (strcmp(identifier, fcu->rna_path + (len_path-len_id))==0) { if ((from_single) || (aci->array_index == fcu->array_index)) break; } } } else { printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n", aci->id->name, aci->rna_path); } } } } return aci; }
/** * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c * * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. * (only applies to main database) * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to * \a id. */ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) { ID *id = idv; short type = GS(id->name); ListBase *lb = which_libbase(bmain, type); DAG_id_type_tag(bmain, type); #ifdef WITH_PYTHON BPY_id_release(id); #endif if (do_id_user) { BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); } BKE_libblock_free_datablock(id, 0); /* avoid notifying on removed data */ BKE_main_lock(bmain); if (do_ui_user) { if (free_notifier_reference_cb) { free_notifier_reference_cb(id); } if (remap_editor_id_reference_cb) { remap_editor_id_reference_cb(id, NULL); } } BLI_remlink(lb, id); BKE_libblock_free_data(id, do_id_user); BKE_main_unlock(bmain); MEM_freeN(id); }
void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const bool tag) { ListBase *lb = which_libbase(mainvar, type); BKE_main_id_tag_listbase(lb, tag); }
void tag_main_idcode(struct Main *mainvar, const short type, const short tag) { ListBase *lb= which_libbase(mainvar, type); tag_main_lb(lb, tag); }
void filelist_from_main(struct FileList *filelist) { ID *id; struct direntry *files, *firstlib = NULL; ListBase *lb; int a, fake, idcode, ok, totlib, totbl; // filelist->type = FILE_MAIN; // XXXXX TODO: add modes to filebrowser if (filelist->dir[0]=='/') filelist->dir[0]= 0; if (filelist->dir[0]) { idcode= groupname_to_code(filelist->dir); if (idcode==0) filelist->dir[0]= 0; } if ( filelist->dir[0]==0) { /* make directories */ filelist->numfiles= 24; filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); for (a=0; a<filelist->numfiles; a++) { memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry)); filelist->filelist[a].type |= S_IFDIR; } filelist->filelist[0].relname= BLI_strdup(".."); filelist->filelist[2].relname= BLI_strdup("Scene"); filelist->filelist[3].relname= BLI_strdup("Object"); filelist->filelist[4].relname= BLI_strdup("Mesh"); filelist->filelist[5].relname= BLI_strdup("Curve"); filelist->filelist[6].relname= BLI_strdup("Metaball"); filelist->filelist[7].relname= BLI_strdup("Material"); filelist->filelist[8].relname= BLI_strdup("Texture"); filelist->filelist[9].relname= BLI_strdup("Image"); filelist->filelist[10].relname= BLI_strdup("Ika"); filelist->filelist[11].relname= BLI_strdup("Wave"); filelist->filelist[12].relname= BLI_strdup("Lattice"); filelist->filelist[13].relname= BLI_strdup("Lamp"); filelist->filelist[14].relname= BLI_strdup("Camera"); filelist->filelist[15].relname= BLI_strdup("Ipo"); filelist->filelist[16].relname= BLI_strdup("World"); filelist->filelist[17].relname= BLI_strdup("Screen"); filelist->filelist[18].relname= BLI_strdup("VFont"); filelist->filelist[19].relname= BLI_strdup("Text"); filelist->filelist[20].relname= BLI_strdup("Armature"); filelist->filelist[21].relname= BLI_strdup("Action"); filelist->filelist[22].relname= BLI_strdup("NodeTree"); filelist->filelist[23].relname= BLI_strdup("Speaker"); filelist_sort(filelist, FILE_SORT_ALPHA); } else { /* make files */ idcode= groupname_to_code(filelist->dir); lb= which_libbase(G.main, idcode ); if (lb == NULL) return; id= lb->first; filelist->numfiles= 0; while (id) { if (!filelist->hide_dot || id->name[2] != '.') { filelist->numfiles++; } id= id->next; } /* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */ if (!filelist->hide_parent) filelist->numfiles+= 1; filelist->filelist= filelist->numfiles > 0 ? (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)) : NULL; files = filelist->filelist; if (!filelist->hide_parent) { memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry)); filelist->filelist[0].relname= BLI_strdup(".."); filelist->filelist[0].type |= S_IFDIR; files++; } id= lb->first; totlib= totbl= 0; while (id) { ok = 1; if (ok) { if (!filelist->hide_dot || id->name[2] != '.') { memset( files, 0 , sizeof(struct direntry)); if (id->lib==NULL) files->relname= BLI_strdup(id->name+2); else { files->relname= MEM_mallocN(FILE_MAX+32, "filename for lib"); sprintf(files->relname, "%s | %s", id->lib->name, id->name+2); } files->type |= S_IFREG; #if 0 // XXXXX TODO show the selection status of the objects if (!filelist->has_func) { /* F4 DATA BROWSE */ if (idcode==ID_OB) { if ( ((Object *)id)->flag & SELECT) files->selflag |= SELECTED_FILE; } else if (idcode==ID_SCE) { if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= SELECTED_FILE; } } #endif files->nr= totbl+1; files->poin= id; fake= id->flag & LIB_FAKEUSER; if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) { files->flags |= IMAGEFILE; } if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->extra), "LF %d", id->us); else if (id->lib) BLI_snprintf(files->extra, sizeof(files->extra), "L %d", id->us); else if (fake) BLI_snprintf(files->extra, sizeof(files->extra), "F %d", id->us); else BLI_snprintf(files->extra, sizeof(files->extra), " %d", id->us); if (id->lib) { if (totlib==0) firstlib= files; totlib++; } files++; } totbl++; } id= id->next; } /* only qsort of library blocks */ if (totlib>1) { qsort(firstlib, totlib, sizeof(struct direntry), compare_name); } } filelist->filter = 0; filelist_filter(filelist); }
ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */ { ListBase *lb = which_libbase(G.main, type); BLI_assert(lb != NULL); return BLI_findstring(lb, name, offsetof(ID, name) + 2); }
void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag) { ID *id = idv; if (use_flag_from_idtag) { if ((id->tag & LIB_TAG_NO_MAIN) != 0) { flag |= LIB_ID_FREE_NO_MAIN; } else { flag &= ~LIB_ID_FREE_NO_MAIN; } if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) { flag |= LIB_ID_FREE_NO_USER_REFCOUNT; } else { flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT; } if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) { flag |= LIB_ID_FREE_NOT_ALLOCATED; } else { flag &= ~LIB_ID_FREE_NOT_ALLOCATED; } } BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL); BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0); BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); const short type = GS(id->name); if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) { DAG_id_type_tag(bmain, type); } #ifdef WITH_PYTHON BPY_id_release(id); #endif if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); } BKE_libblock_free_datablock(id, flag); /* avoid notifying on removed data */ if (bmain) { BKE_main_lock(bmain); } if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) { if (free_notifier_reference_cb) { free_notifier_reference_cb(id); } if (remap_editor_id_reference_cb) { remap_editor_id_reference_cb(id, NULL); } } if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { ListBase *lb = which_libbase(bmain, type); BLI_remlink(lb, id); } BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); if (bmain) { BKE_main_unlock(bmain); } if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) { MEM_freeN(id); } }
ID *find_id(const char *type, const char *name) /* type: "OB" or "MA" etc */ { ListBase *lb= which_libbase(G.main, GS(type)); return BLI_findstring(lb, name, offsetof(ID, name) + 2); }
/** * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c * * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. */ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user) { ID *id = idv; short type = GS(id->name); ListBase *lb = which_libbase(bmain, type); DAG_id_type_tag(bmain, type); #ifdef WITH_PYTHON BPY_id_release(id); #endif if (do_id_user) { BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); } switch (type) { case ID_SCE: BKE_scene_free((Scene *)id); break; case ID_LI: BKE_library_free((Library *)id); break; case ID_OB: BKE_object_free((Object *)id); break; case ID_ME: BKE_mesh_free((Mesh *)id); break; case ID_CU: BKE_curve_free((Curve *)id); break; case ID_MB: BKE_mball_free((MetaBall *)id); break; case ID_MA: BKE_material_free((Material *)id); break; case ID_TE: BKE_texture_free((Tex *)id); break; case ID_IM: BKE_image_free((Image *)id); break; case ID_LT: BKE_lattice_free((Lattice *)id); break; case ID_LA: BKE_lamp_free((Lamp *)id); break; case ID_CA: BKE_camera_free((Camera *) id); break; case ID_IP: /* Deprecated. */ BKE_ipo_free((Ipo *)id); break; case ID_KE: BKE_key_free((Key *)id); break; case ID_WO: BKE_world_free((World *)id); break; case ID_SCR: BKE_screen_free((bScreen *)id); break; case ID_VF: BKE_vfont_free((VFont *)id); break; case ID_TXT: BKE_text_free((Text *)id); break; case ID_SPK: BKE_speaker_free((Speaker *)id); break; case ID_SO: BKE_sound_free((bSound *)id); break; case ID_GR: BKE_group_free((Group *)id); break; case ID_AR: BKE_armature_free((bArmature *)id); break; case ID_AC: BKE_action_free((bAction *)id); break; case ID_NT: ntreeFreeTree((bNodeTree *)id); break; case ID_BR: BKE_brush_free((Brush *)id); break; case ID_PA: BKE_particlesettings_free((ParticleSettings *)id); break; case ID_WM: if (free_windowmanager_cb) free_windowmanager_cb(NULL, (wmWindowManager *)id); break; case ID_GD: BKE_gpencil_free((bGPdata *)id, true); break; case ID_MC: BKE_movieclip_free((MovieClip *)id); break; case ID_MSK: BKE_mask_free((Mask *)id); break; case ID_LS: BKE_linestyle_free((FreestyleLineStyle *)id); break; case ID_PAL: BKE_palette_free((Palette *)id); break; case ID_PC: BKE_paint_curve_free((PaintCurve *)id); break; case ID_CF: BKE_cachefile_free((CacheFile *)id); break; } /* avoid notifying on removed data */ BKE_main_lock(bmain); if (free_notifier_reference_cb) { free_notifier_reference_cb(id); } if (remap_editor_id_reference_cb) { remap_editor_id_reference_cb(id, NULL); } BLI_remlink(lb, id); BKE_libblock_free_data(bmain, id); BKE_main_unlock(bmain); MEM_freeN(id); }
/* ***************** ID ************************ */ ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) { ListBase *lb = which_libbase(bmain, type); BLI_assert(lb != NULL); return BLI_findstring(lb, name, offsetof(ID, name) + 2); }