Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_files_link.c
| Show First 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { | ||||
| } | } | ||||
| } | } | ||||
| BLO_library_link_end(mainl, &bh, flag, scene, v3d); | BLO_library_link_end(mainl, &bh, flag, scene, v3d); | ||||
| BLO_blendhandle_close(bh); | BLO_blendhandle_close(bh); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Check if an item defined by \a name and \a group can be appended/linked. | |||||
| * | |||||
| * \param reports: Optionally report an error when an item can't be appended/linked. | |||||
| */ | |||||
| static bool wm_link_append_item_poll(ReportList *reports, const char *path, const char *group, const char *name, | |||||
| const bool is_append) | |||||
| { | |||||
| short idcode; | |||||
| if (!group || !name) { | |||||
| printf("skipping %s\n", path); | |||||
| return false; | |||||
| } | |||||
| idcode = BKE_idcode_from_name(group); | |||||
| if ((is_append && !BKE_idcode_is_appendable(idcode)) || | |||||
| (!is_append && !BKE_idcode_is_linkable(idcode))) | |||||
| { | |||||
| if (reports) { | |||||
| BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't %s data-block '%s' of type '%s'", | |||||
| is_append ? "append" : "link", name, group); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| static int wm_link_append_exec(bContext *C, wmOperator *op) | static int wm_link_append_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| WMLinkAppendData *lapp_data; | WMLinkAppendData *lapp_data; | ||||
| char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; | char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; | ||||
| char *group, *name; | char *group, *name; | ||||
| int totfiles = 0; | int totfiles = 0; | ||||
| short flag; | short flag; | ||||
| bool has_item = false; | |||||
| bool is_append; | |||||
| RNA_string_get(op->ptr, "filename", relname); | RNA_string_get(op->ptr, "filename", relname); | ||||
| RNA_string_get(op->ptr, "directory", root); | RNA_string_get(op->ptr, "directory", root); | ||||
| BLI_join_dirfile(path, sizeof(path), root, relname); | BLI_join_dirfile(path, sizeof(path), root, relname); | ||||
| /* test if we have a valid data */ | /* test if we have a valid data */ | ||||
| if (!BLO_library_path_explode(path, libname, &group, &name)) { | if (!BLO_library_path_explode(path, libname, &group, &name)) { | ||||
| Show All 21 Lines | if (prop) { | ||||
| } | } | ||||
| } | } | ||||
| else if (!name) { | else if (!name) { | ||||
| BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); | BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| flag = wm_link_append_flag(op); | flag = wm_link_append_flag(op); | ||||
| is_append = (flag & FILE_LINK) == 0; | |||||
| /* sanity checks for flag */ | /* sanity checks for flag */ | ||||
| if (scene && scene->id.lib) { | if (scene && scene->id.lib) { | ||||
| BKE_reportf(op->reports, RPT_WARNING, | BKE_reportf(op->reports, RPT_WARNING, | ||||
| "Scene '%s' is linked, instantiation of objects & groups is disabled", scene->id.name + 2); | "Scene '%s' is linked, instantiation of objects & groups is disabled", scene->id.name + 2); | ||||
| flag &= ~FILE_GROUP_INSTANCE; | flag &= ~FILE_GROUP_INSTANCE; | ||||
| scene = NULL; | scene = NULL; | ||||
| } | } | ||||
| Show All 19 Lines | if (totfiles != 0) { | ||||
| RNA_BEGIN (op->ptr, itemptr, "files") | RNA_BEGIN (op->ptr, itemptr, "files") | ||||
| { | { | ||||
| RNA_string_get(&itemptr, "name", relname); | RNA_string_get(&itemptr, "name", relname); | ||||
| BLI_join_dirfile(path, sizeof(path), root, relname); | BLI_join_dirfile(path, sizeof(path), root, relname); | ||||
| if (BLO_library_path_explode(path, libname, &group, &name)) { | if (BLO_library_path_explode(path, libname, &group, &name)) { | ||||
| if (!group || !name) { | if (!wm_link_append_item_poll(NULL, path, group, name, is_append)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (!BLI_ghash_haskey(libraries, libname)) { | if (!BLI_ghash_haskey(libraries, libname)) { | ||||
| BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx)); | BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx)); | ||||
| lib_idx++; | lib_idx++; | ||||
| wm_link_append_data_library_add(lapp_data, libname); | wm_link_append_data_library_add(lapp_data, libname); | ||||
| has_item = true; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| RNA_END; | RNA_END; | ||||
| RNA_BEGIN (op->ptr, itemptr, "files") | RNA_BEGIN (op->ptr, itemptr, "files") | ||||
| { | { | ||||
| RNA_string_get(&itemptr, "name", relname); | RNA_string_get(&itemptr, "name", relname); | ||||
| BLI_join_dirfile(path, sizeof(path), root, relname); | BLI_join_dirfile(path, sizeof(path), root, relname); | ||||
| if (BLO_library_path_explode(path, libname, &group, &name)) { | if (BLO_library_path_explode(path, libname, &group, &name)) { | ||||
| WMLinkAppendDataItem *item; | WMLinkAppendDataItem *item; | ||||
| if (!group || !name) { | |||||
| printf("skipping %s\n", path); | if (!wm_link_append_item_poll(op->reports, path, group, name, is_append)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| lib_idx = GET_INT_FROM_POINTER(BLI_ghash_lookup(libraries, libname)); | lib_idx = GET_INT_FROM_POINTER(BLI_ghash_lookup(libraries, libname)); | ||||
| item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); | item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); | ||||
| BLI_BITMAP_ENABLE(item->libraries, lib_idx); | BLI_BITMAP_ENABLE(item->libraries, lib_idx); | ||||
| has_item = true; | |||||
| } | } | ||||
| } | } | ||||
| RNA_END; | RNA_END; | ||||
| BLI_ghash_free(libraries, MEM_freeN, NULL); | BLI_ghash_free(libraries, MEM_freeN, NULL); | ||||
| } | } | ||||
| else { | else { | ||||
| WMLinkAppendDataItem *item; | WMLinkAppendDataItem *item; | ||||
| wm_link_append_data_library_add(lapp_data, libname); | wm_link_append_data_library_add(lapp_data, libname); | ||||
| item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); | item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); | ||||
| BLI_BITMAP_ENABLE(item->libraries, 0); | BLI_BITMAP_ENABLE(item->libraries, 0); | ||||
| } | } | ||||
| if (!has_item) { | |||||
| wm_link_append_data_free(lapp_data); | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| /* XXX We'd need re-entrant locking on Main for this to work... */ | /* XXX We'd need re-entrant locking on Main for this to work... */ | ||||
| /* BKE_main_lock(bmain); */ | /* BKE_main_lock(bmain); */ | ||||
| wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C), false, false); | wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C), false, false); | ||||
| /* BKE_main_unlock(bmain); */ | /* BKE_main_unlock(bmain); */ | ||||
| /* mark all library linked objects to be updated */ | /* mark all library linked objects to be updated */ | ||||
| BKE_main_lib_objects_recalc_all(bmain); | BKE_main_lib_objects_recalc_all(bmain); | ||||
| IMB_colormanagement_check_file_config(bmain); | IMB_colormanagement_check_file_config(bmain); | ||||
| /* append, rather than linking */ | /* append, rather than linking */ | ||||
| if ((flag & FILE_LINK) == 0) { | if (is_append) { | ||||
| const bool set_fake = RNA_boolean_get(op->ptr, "set_fake"); | const bool set_fake = RNA_boolean_get(op->ptr, "set_fake"); | ||||
| const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive"); | const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive"); | ||||
| if (use_recursive) { | if (use_recursive) { | ||||
| BKE_library_make_local(bmain, NULL, NULL, true, set_fake); | BKE_library_make_local(bmain, NULL, NULL, true, set_fake); | ||||
| } | } | ||||
| else { | else { | ||||
| LinkNode *itemlink; | LinkNode *itemlink; | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | void WM_OT_link(wmOperatorType *ot) | ||||
| ot->invoke = wm_link_append_invoke; | ot->invoke = wm_link_append_invoke; | ||||
| ot->exec = wm_link_append_exec; | ot->exec = wm_link_append_exec; | ||||
| ot->poll = wm_link_append_poll; | ot->poll = wm_link_append_poll; | ||||
| ot->flag |= OPTYPE_UNDO; | ot->flag |= OPTYPE_UNDO; | ||||
| WM_operator_properties_filesel( | WM_operator_properties_filesel( | ||||
| ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE, | ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB_LINKABLE, FILE_OPENFILE, | ||||
| WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES, | WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES, | ||||
| FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | ||||
| wm_link_append_properties_common(ot, true); | wm_link_append_properties_common(ot, true); | ||||
| } | } | ||||
| void WM_OT_append(wmOperatorType *ot) | void WM_OT_append(wmOperatorType *ot) | ||||
| { | { | ||||
| ot->name = "Append from Library"; | ot->name = "Append from Library"; | ||||
| ot->idname = "WM_OT_append"; | ot->idname = "WM_OT_append"; | ||||
| ot->description = "Append from a Library .blend file"; | ot->description = "Append from a Library .blend file"; | ||||
| ot->invoke = wm_link_append_invoke; | ot->invoke = wm_link_append_invoke; | ||||
| ot->exec = wm_link_append_exec; | ot->exec = wm_link_append_exec; | ||||
| ot->poll = wm_link_append_poll; | ot->poll = wm_link_append_poll; | ||||
| ot->flag |= OPTYPE_UNDO; | ot->flag |= OPTYPE_UNDO; | ||||
| WM_operator_properties_filesel( | WM_operator_properties_filesel( | ||||
| ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB, FILE_OPENFILE, | ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB, FILE_LOADLIB_APPENDABLE, FILE_OPENFILE, | ||||
| WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES, | WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES, | ||||
| FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | ||||
| wm_link_append_properties_common(ot, false); | wm_link_append_properties_common(ot, false); | ||||
| RNA_def_boolean(ot->srna, "set_fake", false, "Fake User", | RNA_def_boolean(ot->srna, "set_fake", false, "Fake User", | ||||
| "Set Fake User for appended items (except Objects and Groups)"); | "Set Fake User for appended items (except Objects and Groups)"); | ||||
| RNA_def_boolean(ot->srna, "use_recursive", true, "Localize All", | RNA_def_boolean(ot->srna, "use_recursive", true, "Localize All", | ||||
| "Localize all appended data, including those indirectly linked from other libraries"); | "Localize all appended data, including those indirectly linked from other libraries"); | ||||
| Show All 31 Lines | static void lib_relocate_do( | ||||
| Main *bmain, Scene *scene, | Main *bmain, Scene *scene, | ||||
| Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload) | Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload) | ||||
| { | { | ||||
| ListBase *lbarray[MAX_LIBARRAY]; | ListBase *lbarray[MAX_LIBARRAY]; | ||||
| int lba_idx; | int lba_idx; | ||||
| LinkNode *itemlink; | LinkNode *itemlink; | ||||
| int item_idx; | int item_idx; | ||||
| bool has_item = false; | |||||
| /* Remove all IDs to be reloaded from Main. */ | /* Remove all IDs to be reloaded from Main. */ | ||||
| lba_idx = set_listbasepointers(bmain, lbarray); | lba_idx = set_listbasepointers(bmain, lbarray); | ||||
| while (lba_idx--) { | while (lba_idx--) { | ||||
| ID *id = lbarray[lba_idx]->first; | ID *id = lbarray[lba_idx]->first; | ||||
| const short idcode = id ? GS(id->name) : 0; | const short idcode = id ? GS(id->name) : 0; | ||||
| if (!id || !BKE_idcode_is_linkable(idcode)) { | /* Could continue for non-linkable ID types here already, but we | ||||
| /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ | * want to show an error message for all un-linkable IDs. */ | ||||
| continue; | |||||
| } | |||||
| for (; id; id = id->next) { | for (; id; id = id->next) { | ||||
| if (id->lib == library) { | if (id->lib == library) { | ||||
| WMLinkAppendDataItem *item; | WMLinkAppendDataItem *item; | ||||
| if (!BKE_idcode_is_linkable(idcode)) { | |||||
| /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ | |||||
| BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can not %s '%s': Data-blocks of type '%s' " | |||||
| "don't support linking", do_reload ? "reload" : "relocate", | |||||
| id->name + 2, BKE_idcode_to_name(idcode)); | |||||
| continue; | |||||
| } | |||||
| /* We remove it from current Main, and add it to items to link... */ | /* We remove it from current Main, and add it to items to link... */ | ||||
| /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */ | /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */ | ||||
| BLI_remlink(lbarray[lba_idx], id); | BLI_remlink(lbarray[lba_idx], id); | ||||
| item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); | item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); | ||||
| BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries); | BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries); | ||||
| has_item = true; | |||||
| #ifdef PRINT_DEBUG | #ifdef PRINT_DEBUG | ||||
| printf("\tdatablock to seek for: %s\n", id->name); | printf("\tdatablock to seek for: %s\n", id->name); | ||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (!has_item) { | |||||
| /* nothing to relocate */ | |||||
| return; | |||||
| } | |||||
| BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); | BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); | ||||
| /* We do not want any instanciation here! */ | /* We do not want any instanciation here! */ | ||||
| wm_link_do(lapp_data, reports, bmain, NULL, NULL, do_reload, do_reload); | wm_link_do(lapp_data, reports, bmain, NULL, NULL, do_reload, do_reload); | ||||
| BKE_main_lock(bmain); | BKE_main_lock(bmain); | ||||
| /* We add back old id to bmain. | /* We add back old id to bmain. | ||||
| ▲ Show 20 Lines • Show All 338 Lines • Show Last 20 Lines | |||||