This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/windowmanager/intern/wm_files_link.c
Campbell Barton d450a791c3 Cleanup: assign operator type flags in their initialization
Some operators OR'ed the existing flags in a way that made it seem
the value might already have some values set.
Replace this with assignment as no flags are set and the convention
with almost all operators is to write the value directly.
2022-06-05 23:05:38 +10:00

852 lines
27 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2007 Blender Foundation. All rights reserved. */
/** \file
* \ingroup wm
*
* Functions for dealing with append/link operators and helpers.
*/
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
#include "DNA_collection_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_utildefines.h"
#include "BLO_readfile.h"
#include "BKE_armature.h"
#include "BKE_blendfile_link_append.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_idtype.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "IMB_colormanagement.h"
#include "ED_datafiles.h"
#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "wm_files.h"
static CLG_LogRef LOG = {"wm.files_link"};
/* -------------------------------------------------------------------- */
/** \name Link/Append Operator
* \{ */
static bool wm_link_append_poll(bContext *C)
{
if (WM_operator_winactive(C)) {
/* linking changes active object which is pretty useful in general,
* but which totally confuses edit mode (i.e. it becoming not so obvious
* to leave from edit mode and invalid tools in toolbar might be displayed)
* so disable link/append when in edit mode (sergey) */
if (CTX_data_edit_object(C)) {
return 0;
}
return 1;
}
return 0;
}
static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
const char *blendfile_path = BKE_main_blendfile_path_from_global();
if (G.lib[0] != '\0') {
RNA_string_set(op->ptr, "filepath", G.lib);
}
else if (blendfile_path[0] != '\0') {
char path[FILE_MAX];
STRNCPY(path, blendfile_path);
BLI_path_parent_dir(path);
RNA_string_set(op->ptr, "filepath", path);
}
}
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int wm_link_append_flag(wmOperator *op)
{
PropertyRNA *prop;
int flag = 0;
if (RNA_boolean_get(op->ptr, "autoselect")) {
flag |= FILE_AUTOSELECT;
}
if (RNA_boolean_get(op->ptr, "active_collection")) {
flag |= FILE_ACTIVE_COLLECTION;
}
if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
RNA_property_boolean_get(op->ptr, prop)) {
flag |= FILE_RELPATH;
}
if (RNA_boolean_get(op->ptr, "link")) {
flag |= FILE_LINK;
}
else {
if (RNA_boolean_get(op->ptr, "use_recursive")) {
flag |= BLO_LIBLINK_APPEND_RECURSIVE;
}
if (RNA_boolean_get(op->ptr, "set_fake")) {
flag |= BLO_LIBLINK_APPEND_SET_FAKEUSER;
}
if (RNA_boolean_get(op->ptr, "do_reuse_local_id")) {
flag |= BLO_LIBLINK_APPEND_LOCAL_ID_REUSE;
}
}
if (RNA_boolean_get(op->ptr, "instance_collections")) {
flag |= BLO_LIBLINK_COLLECTION_INSTANCE;
}
if (RNA_boolean_get(op->ptr, "instance_object_data")) {
flag |= BLO_LIBLINK_OBDATA_INSTANCE;
}
return flag;
}
/**
* 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 do_append)
{
short idcode;
if (!group || !name) {
CLOG_WARN(&LOG, "Skipping %s", path);
return false;
}
idcode = BKE_idtype_idcode_from_name(group);
if (!BKE_idtype_idcode_is_linkable(idcode) ||
(!do_append && BKE_idtype_idcode_is_only_appendable(idcode))) {
if (reports) {
if (do_append) {
BKE_reportf(reports,
RPT_ERROR_INVALID_INPUT,
"Can't append data-block '%s' of type '%s'",
name,
group);
}
else {
BKE_reportf(reports,
RPT_ERROR_INVALID_INPUT,
"Can't link data-block '%s' of type '%s'",
name,
group);
}
}
return false;
}
return true;
}
static int wm_link_append_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
PropertyRNA *prop;
BlendfileLinkAppendContext *lapp_context;
char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
char *group, *name;
int totfiles = 0;
RNA_string_get(op->ptr, "filename", relname);
RNA_string_get(op->ptr, "directory", root);
BLI_join_dirfile(path, sizeof(path), root, relname);
/* test if we have a valid data */
if (!BLO_library_path_explode(path, libname, &group, &name)) {
BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path);
return OPERATOR_CANCELLED;
}
if (!group) {
BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
if (BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0) {
BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", path);
return OPERATOR_CANCELLED;
}
/* check if something is indicated for append/link */
prop = RNA_struct_find_property(op->ptr, "files");
if (prop) {
totfiles = RNA_property_collection_length(op->ptr, prop);
if (totfiles == 0) {
if (!name) {
BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
}
}
else if (!name) {
BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
int flag = wm_link_append_flag(op);
const bool do_append = (flag & FILE_LINK) == 0;
/* sanity checks for flag */
if (scene && scene->id.lib) {
BKE_reportf(op->reports,
RPT_WARNING,
"Scene '%s' is linked, instantiation of objects is disabled",
scene->id.name + 2);
flag &= ~(BLO_LIBLINK_COLLECTION_INSTANCE | BLO_LIBLINK_OBDATA_INSTANCE);
scene = NULL;
}
/* from here down, no error returns */
if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
BKE_view_layer_base_deselect_all(view_layer);
}
/* 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_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* We define our working data...
* Note that here, each item 'uses' one library, and only one. */
LibraryLink_Params lapp_params;
BLO_library_link_params_init_with_context(
&lapp_params, bmain, flag, 0, scene, view_layer, CTX_wm_view3d(C));
lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
BKE_blendfile_link_append_context_embedded_blendfile_set(
lapp_context, datatoc_startup_blend, datatoc_startup_blend_size);
if (totfiles != 0) {
GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
int lib_idx = 0;
RNA_BEGIN (op->ptr, itemptr, "files") {
RNA_string_get(&itemptr, "name", relname);
BLI_join_dirfile(path, sizeof(path), root, relname);
if (BLO_library_path_explode(path, libname, &group, &name)) {
if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) {
continue;
}
if (!BLI_ghash_haskey(libraries, libname)) {
BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx));
lib_idx++;
BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
}
}
}
RNA_END;
RNA_BEGIN (op->ptr, itemptr, "files") {
RNA_string_get(&itemptr, "name", relname);
BLI_join_dirfile(path, sizeof(path), root, relname);
if (BLO_library_path_explode(path, libname, &group, &name)) {
BlendfileLinkAppendContextItem *item;
if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) {
continue;
}
lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname));
item = BKE_blendfile_link_append_context_item_add(
lapp_context, name, BKE_idtype_idcode_from_name(group), NULL);
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, lib_idx);
}
}
RNA_END;
BLI_ghash_free(libraries, MEM_freeN, NULL);
}
else {
BlendfileLinkAppendContextItem *item;
BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
item = BKE_blendfile_link_append_context_item_add(
lapp_context, name, BKE_idtype_idcode_from_name(group), NULL);
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0);
}
if (BKE_blendfile_link_append_context_is_empty(lapp_context)) {
/* Early out in case there is nothing to link. */
BKE_blendfile_link_append_context_free(lapp_context);
/* Clear pre existing tag. */
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return OPERATOR_CANCELLED;
}
/* XXX We'd need re-entrant locking on Main for this to work... */
// BKE_main_lock(bmain);
BKE_blendfile_link(lapp_context, op->reports);
// BKE_main_unlock(bmain);
/* 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 */
if (do_append) {
BKE_blendfile_append(lapp_context, op->reports);
}
BKE_blendfile_link_append_context_free(lapp_context);
/* important we unset, otherwise these object won't
* link into other scenes from this blend file */
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* TODO(sergey): Use proper flag for tagging here. */
/* TODO(dalai): Temporary solution!
* Ideally we only need to tag the new objects themselves, not the scene.
* This way we'll avoid flush of collection properties
* to all objects and limit update to the particular object only.
* But afraid first we need to change collection evaluation in DEG
* according to depsgraph manifesto. */
DEG_id_tag_update(&scene->id, 0);
/* recreate dependency graph to include new objects */
DEG_relations_tag_update(bmain);
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
BLI_strncpy(G.lib, root, FILE_MAX);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
{
PropertyRNA *prop;
/* better not save _any_ settings for this operator */
/* properties */
prop = RNA_def_boolean(
ot->srna, "link", is_link, "Link", "Link the objects or data-blocks rather than appending");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
prop = RNA_def_boolean(
ot->srna,
"do_reuse_local_id",
false,
"Re-Use Local Data",
"Try to re-use previously matching appended data-blocks instead of appending a new copy");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna,
"active_collection",
true,
"Active Collection",
"Put new objects on the active collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(
ot->srna,
"instance_collections",
is_link,
"Instance Collections",
"Create instances for collections, rather than adding them directly to the scene");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(
ot->srna,
"instance_object_data",
true,
"Instance Object Data",
"Create instances for object data which are not referenced by any objects");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void WM_OT_link(wmOperatorType *ot)
{
ot->name = "Link";
ot->idname = "WM_OT_link";
ot->description = "Link from a Library .blend file";
ot->invoke = wm_link_append_invoke;
ot->exec = wm_link_append_exec;
ot->poll = wm_link_append_poll;
ot->flag = OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB,
FILE_LOADLIB,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME |
WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
wm_link_append_properties_common(ot, true);
}
void WM_OT_append(wmOperatorType *ot)
{
ot->name = "Append";
ot->idname = "WM_OT_append";
ot->description = "Append from a Library .blend file";
ot->invoke = wm_link_append_invoke;
ot->exec = wm_link_append_exec;
ot->poll = wm_link_append_poll;
ot->flag = OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_BLENDER | FILE_TYPE_BLENDERLIB,
FILE_LOADLIB,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME |
WM_FILESEL_FILES | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
wm_link_append_properties_common(ot, false);
RNA_def_boolean(ot->srna,
"set_fake",
false,
"Fake User",
"Set \"Fake User\" for appended items (except objects and collections)");
RNA_def_boolean(
ot->srna,
"use_recursive",
true,
"Localize All",
"Localize all appended data, including those indirectly linked from other libraries");
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Link/Append Single Data-Block & Return it
*
* \{ */
static ID *wm_file_link_append_datablock_ex(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
const char *filepath,
const short id_code,
const char *id_name,
const int flag)
{
const bool do_append = (flag & FILE_LINK) == 0;
/* Tag everything so we can make local only the new datablock. */
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* Define working data, with just the one item we want to link. */
LibraryLink_Params lapp_params;
BLO_library_link_params_init_with_context(&lapp_params, bmain, flag, 0, scene, view_layer, v3d);
BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
BKE_blendfile_link_append_context_embedded_blendfile_set(
lapp_context, datatoc_startup_blend, datatoc_startup_blend_size);
BKE_blendfile_link_append_context_library_add(lapp_context, filepath, NULL);
BlendfileLinkAppendContextItem *item = BKE_blendfile_link_append_context_item_add(
lapp_context, id_name, id_code, NULL);
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0);
/* Link datablock. */
BKE_blendfile_link(lapp_context, NULL);
if (do_append) {
BKE_blendfile_append(lapp_context, NULL);
}
/* Get linked datablock and free working data. */
ID *id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item);
BKE_blendfile_link_append_context_free(lapp_context);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return id;
}
ID *WM_file_link_datablock(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
const char *filepath,
const short id_code,
const char *id_name,
int flag)
{
flag |= FILE_LINK;
return wm_file_link_append_datablock_ex(
bmain, scene, view_layer, v3d, filepath, id_code, id_name, flag);
}
ID *WM_file_append_datablock(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
const char *filepath,
const short id_code,
const char *id_name,
int flag)
{
BLI_assert((flag & FILE_LINK) == 0);
ID *id = wm_file_link_append_datablock_ex(
bmain, scene, view_layer, v3d, filepath, id_code, id_name, flag);
return id;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Library Relocate Operator & Library Reload API
* \{ */
static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Library *lib;
char lib_name[MAX_NAME];
RNA_string_get(op->ptr, "library", lib_name);
lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name);
if (lib) {
if (lib->parent) {
BKE_reportf(op->reports,
RPT_ERROR_INVALID_INPUT,
"Cannot relocate indirectly linked library '%s'",
lib->filepath_abs);
return OPERATOR_CANCELLED;
}
RNA_string_set(op->ptr, "filepath", lib->filepath_abs);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_CANCELLED;
}
void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
{
if (!BLO_has_bfile_extension(lib->filepath_abs)) {
BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath_abs);
return;
}
if (!BLI_exists(lib->filepath_abs)) {
BKE_reportf(reports,
RPT_ERROR,
"Trying to reload library '%s' from invalid path '%s'",
lib->id.name,
lib->filepath_abs);
return;
}
Main *bmain = CTX_data_main(C);
LibraryLink_Params lapp_params;
BLO_library_link_params_init_with_context(&lapp_params,
bmain,
BLO_LIBLINK_USE_PLACEHOLDERS |
BLO_LIBLINK_FORCE_INDIRECT,
0,
CTX_data_scene(C),
CTX_data_view_layer(C),
NULL);
BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
BKE_blendfile_link_append_context_library_add(lapp_context, lib->filepath_abs, NULL);
BKE_blendfile_library_relocate(lapp_context, reports, lib, true);
BKE_blendfile_link_append_context_free(lapp_context);
BKE_main_lib_objects_recalc_all(bmain);
IMB_colormanagement_check_file_config(bmain);
/* Important we unset, otherwise these object won't link into other scenes from this blend file.
*/
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* Recreate dependency graph to include new IDs. */
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
{
Library *lib;
char lib_name[MAX_NAME];
RNA_string_get(op->ptr, "library", lib_name);
lib = (Library *)BKE_libblock_find_name(CTX_data_main(C), ID_LI, lib_name);
if (lib) {
Main *bmain = CTX_data_main(C);
PropertyRNA *prop;
BlendfileLinkAppendContext *lapp_context;
char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
short flag = 0;
if (RNA_boolean_get(op->ptr, "relative_path")) {
flag |= FILE_RELPATH;
}
if (lib->parent && !do_reload) {
BKE_reportf(op->reports,
RPT_ERROR_INVALID_INPUT,
"Cannot relocate indirectly linked library '%s'",
lib->filepath_abs);
return OPERATOR_CANCELLED;
}
RNA_string_get(op->ptr, "directory", root);
RNA_string_get(op->ptr, "filename", libname);
if (!BLO_has_bfile_extension(libname)) {
BKE_report(op->reports, RPT_ERROR, "Not a library");
return OPERATOR_CANCELLED;
}
BLI_join_dirfile(path, sizeof(path), root, libname);
if (!BLI_exists(path)) {
BKE_reportf(op->reports,
RPT_ERROR_INVALID_INPUT,
"Trying to reload or relocate library '%s' to invalid path '%s'",
lib->id.name,
path);
return OPERATOR_CANCELLED;
}
if (BLI_path_cmp(BKE_main_blendfile_path(bmain), path) == 0) {
BKE_reportf(op->reports,
RPT_ERROR_INVALID_INPUT,
"Cannot relocate library '%s' to current blend file '%s'",
lib->id.name,
path);
return OPERATOR_CANCELLED;
}
LibraryLink_Params lapp_params;
BLO_library_link_params_init_with_context(
&lapp_params, bmain, flag, 0, CTX_data_scene(C), CTX_data_view_layer(C), NULL);
if (BLI_path_cmp(lib->filepath_abs, path) == 0) {
CLOG_INFO(&LOG, 4, "We are supposed to reload '%s' lib (%d)", lib->filepath, lib->id.us);
do_reload = true;
lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
else {
int totfiles = 0;
CLOG_INFO(
&LOG, 4, "We are supposed to relocate '%s' lib to new '%s' one", lib->filepath, libname);
/* Check if something is indicated for relocate. */
prop = RNA_struct_find_property(op->ptr, "files");
if (prop) {
totfiles = RNA_property_collection_length(op->ptr, prop);
if (totfiles == 0) {
if (!libname[0]) {
BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
return OPERATOR_CANCELLED;
}
}
}
lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
if (totfiles) {
RNA_BEGIN (op->ptr, itemptr, "files") {
RNA_string_get(&itemptr, "name", relname);
BLI_join_dirfile(path, sizeof(path), root, relname);
if (BLI_path_cmp(path, lib->filepath_abs) == 0 || !BLO_has_bfile_extension(relname)) {
continue;
}
CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path);
BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
RNA_END;
}
else {
CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path);
BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
}
BKE_blendfile_link_append_context_flag_set(lapp_context,
BLO_LIBLINK_FORCE_INDIRECT |
(do_reload ? BLO_LIBLINK_USE_PLACEHOLDERS : 0),
true);
BKE_blendfile_library_relocate(lapp_context, op->reports, lib, do_reload);
BKE_blendfile_link_append_context_free(lapp_context);
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
BLI_strncpy(G.lib, root, FILE_MAX);
BKE_main_lib_objects_recalc_all(bmain);
IMB_colormanagement_check_file_config(bmain);
/* Important we unset, otherwise these object won't link into other scenes from this blend
* file.
*/
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* Recreate dependency graph to include new IDs. */
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
static int wm_lib_relocate_exec(bContext *C, wmOperator *op)
{
return wm_lib_relocate_exec_do(C, op, false);
}
void WM_OT_lib_relocate(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name = "Relocate Library";
ot->idname = "WM_OT_lib_relocate";
ot->description = "Relocate the given library to one or several others";
ot->invoke = wm_lib_relocate_invoke;
ot->exec = wm_lib_relocate_exec;
ot->flag = OPTYPE_UNDO;
prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to relocate");
RNA_def_property_flag(prop, PROP_HIDDEN);
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_BLENDER,
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME |
WM_FILESEL_FILES | WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
}
static int wm_lib_reload_exec(bContext *C, wmOperator *op)
{
return wm_lib_relocate_exec_do(C, op, true);
}
void WM_OT_lib_reload(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name = "Reload Library";
ot->idname = "WM_OT_lib_reload";
ot->description = "Reload the given library";
ot->exec = wm_lib_reload_exec;
ot->flag = OPTYPE_UNDO;
prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to reload");
RNA_def_property_flag(prop, PROP_HIDDEN);
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_BLENDER,
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME |
WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
}
/** \} */