/* return success (1) */ int BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, ReportList *reports) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); Main *mainl = NULL; Library *lib; BlendHandle *bh; bh = BLO_blendhandle_from_file(libname, reports); if (bh == NULL) { /* error reports will have been made by BLO_blendhandle_from_file() */ return 0; } BKE_scene_base_deselect_all(scene); /* tag everything, all untagged data can be made local * its also generally useful to know what is new * * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */ BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* here appending/linking starts */ mainl = BLO_library_link_begin(bmain, &bh, libname); BLO_library_link_all(mainl, bh, flag, scene, v3d); BLO_library_link_end(mainl, &bh, flag, scene, v3d); /* mark all library linked objects to be updated */ BKE_main_lib_objects_recalc_all(bmain); IMB_colormanagement_check_file_config(bmain); /* append, rather than linking */ lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath)); BKE_library_make_local(bmain, lib, true, false); /* important we unset, otherwise these object wont * link into other scenes from this blend file */ BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* recreate dependency graph to include new objects */ DAG_relations_tag_update(bmain); BLO_blendhandle_close(bh); /* remove library... */ return 1; }
bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports) { BlendHandle *bh = BLO_blendhandle_from_file(libname, reports); if (bh == NULL) { /* Error reports will have been made by BLO_blendhandle_from_file(). */ return false; } /* Here appending/linking starts. */ Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname); BLO_library_link_copypaste(mainl, bh); BLO_library_link_end(mainl, &bh, 0, NULL, NULL); /* Mark all library linked objects to be updated. */ BKE_main_lib_objects_recalc_all(bmain_dst); IMB_colormanagement_check_file_config(bmain_dst); /* Append, rather than linking. */ Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath)); BKE_library_make_local(bmain_dst, lib, true, false); /* Important we unset, otherwise these object wont * link into other scenes from this blend file. */ BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false); BLO_blendhandle_close(bh); return true; }
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { Main *bmain = CTX_data_main(BPy_GetContext()); Main *mainl = NULL; int err = 0; flag_all_listbases_ids(LIB_PRE_EXISTING, 1); /* here appending/linking starts */ mainl = BLO_library_append_begin(bmain, &(self->blo_handle), self->relpath); { int i = 0, code; while ((code = BKE_idcode_iter_step(&i))) { if (BKE_idcode_is_linkable(code)) { const char *name_plural = BKE_idcode_to_name_plural(code); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); // printf("lib: %s\n", name_plural); if (ls && PyList_Check(ls)) { /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; const char *item_str; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); item_str = _PyUnicode_AsString(item); // printf(" %s\n", item_str); if (item_str) { ID *id = BLO_library_append_named_part(mainl, &(self->blo_handle), item_str, code); if (id) { #ifdef USE_RNA_DATABLOCKS PointerRNA id_ptr; RNA_id_pointer_create(id, &id_ptr); Py_DECREF(item); item = pyrna_struct_CreatePyObject(&id_ptr); #endif } else { bpy_lib_exit_warn_idname(self, name_plural, item_str); /* just warn for now */ /* err = -1; */ #ifdef USE_RNA_DATABLOCKS item = Py_None; Py_INCREF(item); #endif } /* ID or None */ } else { /* XXX, could complain about this */ bpy_lib_exit_warn_type(self, item); PyErr_Clear(); #ifdef USE_RNA_DATABLOCKS item = Py_None; Py_INCREF(item); #endif } #ifdef USE_RNA_DATABLOCKS PyList_SET_ITEM(ls, i, item); #endif } } } } } if (err == -1) { /* exception raised above, XXX, this leaks some memory */ BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; flag_all_listbases_ids(LIB_PRE_EXISTING, 0); return NULL; } else { Library *lib = mainl->curlib; /* newly added lib, assign before append end */ BLO_library_append_end(NULL, mainl, &(self->blo_handle), 0, self->flag); BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; { /* copied from wm_operator.c */ /* mark all library linked objects to be updated */ recalc_all_library_objects(G.main); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { BKE_library_make_local(bmain, lib, 1); } } flag_all_listbases_ids(LIB_PRE_EXISTING, 0); Py_RETURN_NONE; } }
bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; int idcode= BKE_idcode_from_name(group); short flag= 0; /* don't need any special options */ ReportList reports; static char err_local[255]; /* only scene and mesh supported right now */ if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); *err_str= err_local; BLO_blendhandle_close(bpy_openlib); return false; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); *err_str= err_local; BLO_blendhandle_close(bpy_openlib); return false; } if (bpy_openlib==NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); *err_str= err_local; return false; } main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain"); BKE_reports_init(&reports, RPT_STORE); /* here appending/linking starts */ main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); int i=0; LinkNode *n= names; while(n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); n= (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy); int i=0; LinkNode *n= names; while(n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, ID_AC); n= (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag); } BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); /* done linking */ /* needed for lookups*/ GetMainDynamic().push_back(main_newlib); strncpy(main_newlib->name, path, sizeof(main_newlib->name)); if (idcode==ID_ME) { /* Convert all new meshes into BGE meshes */ ID* mesh; for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) printf("MeshName: %s\n", mesh->name+2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this); scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); } } else if (idcode==ID_AC) { /* Convert all actions */ ID *action; for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name+2); scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); } } else if (idcode==ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) printf("SceneName: %s\n", scene->name+2); /* merge into the base scene */ KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene delete other; } /* Now handle all the actions */ if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name+2); scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); } } } return true; }
void filelist_freelib(struct FileList* filelist) { if (filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); filelist->libfiledata= NULL; }
void filelist_from_library(struct FileList* filelist) { LinkNode *l, *names, *previews; struct ImBuf* ima; int ok, i, nprevs, nnames, idcode; char filename[FILE_MAX]; char dir[FILE_MAX], group[GROUP_MAX]; /* name test */ ok= filelist_islibrary(filelist, dir, group); if (!ok) { /* free */ if (filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); filelist->libfiledata= NULL; return; } BLI_strncpy(filename, G.main->name, sizeof(filename)); /* there we go */ /* for the time being only read filedata when libfiledata==0 */ if (filelist->libfiledata == NULL) { filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); if (filelist->libfiledata == NULL) return; } idcode= groupname_to_code(group); /* memory for strings is passed into filelist[i].relname * and freed in freefilelist */ if (idcode) { previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode, &nprevs); names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode, &nnames); /* ugh, no rewind, need to reopen */ BLO_blendhandle_close(filelist->libfiledata); filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); } else { previews= NULL; nprevs= 0; names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata); nnames= BLI_linklist_length(names); } filelist->numfiles= nnames + 1; filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist)); memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist)); filelist->filelist[0].relname= BLI_strdup(".."); filelist->filelist[0].type |= S_IFDIR; for (i=0, l= names; i<nnames; i++, l= l->next) { char *blockname= l->link; filelist->filelist[i + 1].relname= BLI_strdup(blockname); if (idcode) { filelist->filelist[i + 1].type |= S_IFREG; } else { filelist->filelist[i + 1].type |= S_IFDIR; } } if (previews && (nnames != nprevs)) { printf("filelist_from_library: error, found %d items, %d previews\n", nnames, nprevs); } else if (previews) { for (i=0, l= previews; i<nnames; i++, l= l->next) { PreviewImage *img= l->link; if (img) { unsigned int w = img->w[ICON_SIZE_PREVIEW]; unsigned int h = img->h[ICON_SIZE_PREVIEW]; unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; /* first allocate imbuf for copying preview into it */ if (w > 0 && h > 0 && rect) { ima = IMB_allocImBuf(w, h, 32, IB_rect); memcpy(ima->rect, rect, w*h*sizeof(unsigned int)); filelist->filelist[i + 1].image = ima; filelist->filelist[i + 1].flags = IMAGEFILE; } } } } BLI_linklist_free(names, free); if (previews) BLI_linklist_free(previews, BKE_previewimg_freefunc); filelist_sort(filelist, FILE_SORT_ALPHA); BLI_strncpy(G.main->name, filename, sizeof(filename)); // prevent G.main->name to change filelist->filter = 0; filelist_filter(filelist); }
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { Main *bmain = CTX_data_main(BPy_GetContext()); Main *mainl = NULL; int err = 0; BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* here appending/linking starts */ mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath); { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { if (BKE_idcode_is_linkable(idcode)) { const char *name_plural = BKE_idcode_to_name_plural(idcode); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); // printf("lib: %s\n", name_plural); if (ls && PyList_Check(ls)) { /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; const char *item_str; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); item_str = _PyUnicode_AsString(item); // printf(" %s\n", item_str); if (item_str) { ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str); if (id) { #ifdef USE_RNA_DATABLOCKS /* swap name for pointer to the id */ Py_DECREF(item); item = PyCapsule_New((void *)id, NULL, NULL); #endif } else { bpy_lib_exit_warn_idname(self, name_plural, item_str); /* just warn for now */ /* err = -1; */ #ifdef USE_RNA_DATABLOCKS item = Py_INCREF_RET(Py_None); #endif } /* ID or None */ } else { /* XXX, could complain about this */ bpy_lib_exit_warn_type(self, item); PyErr_Clear(); #ifdef USE_RNA_DATABLOCKS item = Py_INCREF_RET(Py_None); #endif } #ifdef USE_RNA_DATABLOCKS PyList_SET_ITEM(ls, i, item); #endif } } } } } if (err == -1) { /* exception raised above, XXX, this leaks some memory */ BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false); return NULL; } else { Library *lib = mainl->curlib; /* newly added lib, assign before append end */ BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL); BLO_blendhandle_close(self->blo_handle); self->blo_handle = NULL; /* copied from wm_operator.c */ { /* mark all library linked objects to be updated */ BKE_main_lib_objects_recalc_all(G.main); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { BKE_library_make_local(bmain, lib, true); } } BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* finally swap the capsules for real bpy objects * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { if (BKE_idcode_is_linkable(idcode)) { const char *name_plural = BKE_idcode_to_name_plural(idcode); PyObject *ls = PyDict_GetItemString(self->dict, name_plural); if (ls && PyList_Check(ls)) { Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; PyObject *item; for (i = 0; i < size; i++) { item = PyList_GET_ITEM(ls, i); if (PyCapsule_CheckExact(item)) { PointerRNA id_ptr; ID *id; id = PyCapsule_GetPointer(item, NULL); Py_DECREF(item); RNA_id_pointer_create(id, &id_ptr); item = pyrna_struct_CreatePyObject(&id_ptr); PyList_SET_ITEM(ls, i, item); } } } } } } Py_RETURN_NONE; } }
/* Does not fix anything, but checks that all linked data-blocks are still valid (i.e. pointing to the right library). */ bool BLO_main_validate_libraries(struct Main *bmain, struct ReportList *reports) { ListBase mainlist; bool is_valid = true; BKE_main_lock(bmain); blo_split_main(&mainlist, bmain); ListBase *lbarray[MAX_LIBARRAY]; int i = set_listbasepointers(bmain, lbarray); while (i--) { for (ID *id = lbarray[i]->first; id != NULL; id = id->next) { if (id->lib != NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s is in local database while being linked from library %s!\n", id->name, id->lib->name); } } } for (Main *curmain = bmain->next; curmain != NULL; curmain = curmain->next) { Library *curlib = curmain->curlib; if (curlib == NULL) { BKE_reportf(reports, RPT_ERROR, "Library database with NULL library datablock!\n"); continue; } BKE_library_filepath_set(bmain, curlib, curlib->name); BlendHandle *bh = BLO_blendhandle_from_file(curlib->filepath, reports); if (bh == NULL) { BKE_reportf(reports, RPT_ERROR, "Library ID %s not found at expected path %s!\n", curlib->id.name, curlib->filepath); continue; } i = set_listbasepointers(curmain, lbarray); while (i--) { ID *id = lbarray[i]->first; if (id == NULL) { continue; } if (GS(id->name) == ID_LI) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "Library ID %s in library %s, this should not happen!\n", id->name, curlib->name); continue; } int totnames = 0; LinkNode *names = BLO_blendhandle_get_datablock_names(bh, GS(id->name), &totnames); for (; id != NULL; id = id->next) { if (id->lib == NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s has NULL lib pointer while being in library %s!\n", id->name, curlib->name); continue; } if (id->lib != curlib) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s has mismatched lib pointer!\n", id->name); continue; } LinkNode *name = names; for (; name; name = name->next) { char *str_name = (char *)name->link; if (id->name[2] == str_name[0] && STREQ(str_name, id->name + 2)) { break; } } if (name == NULL) { is_valid = false; BKE_reportf(reports, RPT_ERROR, "ID %s not found in library %s anymore!\n", id->name, id->lib->name); continue; } } BLI_linklist_free(names, free); } BLO_blendhandle_close(bh); } blo_join_main(&mainlist); BLI_assert(BLI_listbase_is_single(&mainlist)); BLI_assert(mainlist.first == (void *)bmain); BKE_main_unlock(bmain); return is_valid; }
KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ const int idcode = BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; /* only scene and mesh supported right now */ if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); *err_str = err_local; return NULL; } main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); short flag = 0; /* don't need any special options */ /* created only for linking, then freed */ Main *main_tmp = BLO_library_link_begin(main_newlib, &bpy_openlib, (char *)path); load_datablocks(main_tmp, bpy_openlib, path, idcode); if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } BLO_library_link_end(main_tmp, &bpy_openlib, flag, NULL, NULL); BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); /* done linking */ /* needed for lookups*/ GetMainDynamic().push_back(main_newlib); BLI_strncpy(main_newlib->name, path, sizeof(main_newlib->name)); status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ ID *mesh; for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } else if (idcode == ID_AC) { /* Convert all actions */ ID *action; for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name + 2); scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { scenes->push_back((Scene *)scene); } else { /* merge into the base scene */ KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene delete other; } } if (options & LIB_LOAD_ASYNC) { status->SetData(scenes); BLI_task_pool_push(m_threadinfo->m_pool, async_convert, (void *)status, false, TASK_PRIORITY_LOW); } #ifdef WITH_PYTHON /* Handle any text datablocks */ if (options & LIB_LOAD_LOAD_SCRIPTS) addImportMain(main_newlib); #endif /* Now handle all the actions */ if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name + 2); scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); // TIMEIT_END(bge_link_blend_file); m_status_map[main_newlib->name] = status; return status; }