Refactor: move library linking arguments into a parameter struct

Move arguments to BLO_library_link_{begin/named_part/end} into
a single parameter struct, to ensure arguments always match.

This allows is to skip tagging ID's LIB_TAG_DOIT when it's not needed,
previously it was always cleared just in case it was needed.

This also makes it possible to remove BLO_library_link_named_part_ex
which was only used when tagging was needed.
This commit is contained in:
2020-09-08 15:32:43 +10:00
parent 48690d967a
commit e467c54d58
5 changed files with 172 additions and 92 deletions

View File

@@ -93,9 +93,12 @@ bool BKE_copybuffer_read(Main *bmain_dst,
return false;
}
/* Here appending/linking starts. */
Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
const int flag = 0;
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init(&liblink_params, bmain_dst, flag);
Main *mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
BLO_library_link_copypaste(mainl, bh, id_types_mask);
BLO_library_link_end(mainl, &bh, 0, NULL, NULL, NULL, NULL);
BLO_library_link_end(mainl, &bh, &liblink_params);
/* Mark all library linked objects to be updated. */
BKE_main_lib_objects_recalc_all(bmain_dst);
IMB_colormanagement_check_file_config(bmain_dst);
@@ -144,11 +147,13 @@ int BKE_copybuffer_paste(bContext *C,
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* here appending/linking starts */
mainl = BLO_library_link_begin(bmain, &bh, libname);
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init_with_context(&liblink_params, bmain, flag, scene, view_layer, v3d);
mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
const int num_pasted = BLO_library_link_copypaste(mainl, bh, id_types_mask);
BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer, v3d);
BLO_library_link_end(mainl, &bh, &liblink_params);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);

View File

@@ -138,6 +138,10 @@ void BLO_blendhandle_close(BlendHandle *bh);
bool BLO_has_bfile_extension(const char *str);
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name);
/* -------------------------------------------------------------------- */
/** \name BLO Blend File Linking API
* \{ */
/* Options controlling behavior of append/link code.
* Note: merged with 'user-level' options from operators etc. in 16 lower bits
* (see eFileSel_Params_Flag in DNA_space_types.h). */
@@ -146,25 +150,63 @@ typedef enum BLO_LibLinkFlags {
BLO_LIBLINK_USE_PLACEHOLDERS = 1 << 16,
/* Force loaded ID to be tagged as LIB_TAG_INDIRECT (used in reload context only). */
BLO_LIBLINK_FORCE_INDIRECT = 1 << 17,
/**
* When set, tag ID types that pass the internal check #library_link_idcode_needs_tag_check
*
* Currently this is only used to instantiate objects in the scene.
* Set this from #BLO_library_link_params_init_with_context so callers
* don't need to remember to set this flag.
*/
BLO_LIBLINK_NEEDS_ID_TAG_DOIT = 1 << 18,
} BLO_LinkFlags;
struct Main *BLO_library_link_begin(struct Main *mainvar, BlendHandle **bh, const char *filepath);
/**
* Struct for passing arguments to
* #BLO_library_link_begin, #BLO_library_link_named_part & #BLO_library_link_end.
* Wrap these in parameters since it's important both functions receive matching values.
*/
struct LibraryLink_Params {
/** The current main database, e.g. #G_MAIN or `CTX_data_main(C)`. */
struct Main *bmain;
/** Options for linking, used for instantiating. */
int flag;
/** Context for instancing objects (optional, no instantiation will be performed when NULL). */
struct {
/** The scene in which to instantiate objects/collections. */
struct Scene *scene;
/** The scene layer in which to instantiate objects/collections. */
struct ViewLayer *view_layer;
/** The active 3D viewport (only used to define local-view). */
const struct View3D *v3d;
} context;
};
void BLO_library_link_params_init(struct LibraryLink_Params *params,
struct Main *bmain,
const int flag);
void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params,
struct Main *bmain,
const int flag,
struct Scene *scene,
struct ViewLayer *view_layer,
const struct View3D *v3d);
struct Main *BLO_library_link_begin(BlendHandle **bh,
const char *filepath,
const struct LibraryLink_Params *params);
struct ID *BLO_library_link_named_part(struct Main *mainl,
BlendHandle **bh,
const short idcode,
const char *name);
struct ID *BLO_library_link_named_part_ex(
struct Main *mainl, BlendHandle **bh, const short idcode, const char *name, const int flag);
const char *name,
const struct LibraryLink_Params *params);
void BLO_library_link_end(struct Main *mainl,
BlendHandle **bh,
int flag,
struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
const struct View3D *v3d);
const struct LibraryLink_Params *params);
int BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh, const uint64_t id_types_mask);
/** \} */
void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname);
/* internal function but we need to expose it */

View File

@@ -262,6 +262,7 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static void direct_link_modifiers(BlendDataReader *reader, ListBase *lb, Object *ob);
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
static bool library_link_idcode_needs_tag_check(const short idcode, const int flag);
#ifdef USE_COLLECTION_COMPAT_28
static void expand_scene_collection(BlendExpander *expander, SceneCollection *sc);
@@ -10469,6 +10470,14 @@ static ID *link_named_part(
/* if we found the id but the id is NULL, this is really bad */
BLI_assert(!((bhead != NULL) && (id == NULL)));
/* Tag as loose object (or data associated with objects)
* needing to be instantiated in #LibraryLink_Params.scene. */
if ((id != NULL) && (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT)) {
if (library_link_idcode_needs_tag_check(idcode, flag)) {
id->tag |= LIB_TAG_DOIT;
}
}
return id;
}
@@ -10514,23 +10523,6 @@ int BLO_library_link_copypaste(Main *mainl, BlendHandle *bh, const uint64_t id_t
return num_directly_linked;
}
static ID *link_named_part_ex(
Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
{
ID *id = link_named_part(mainl, fd, idcode, name, flag);
if (id && (GS(id->name) == ID_OB)) {
/* Tag as loose object needing to be instantiated somewhere... */
id->tag |= LIB_TAG_DOIT;
}
else if (id && (GS(id->name) == ID_GR)) {
/* tag as needing to be instantiated or linked */
id->tag |= LIB_TAG_DOIT;
}
return id;
}
/**
* Link a named data-block from an external blend file.
*
@@ -10543,41 +10535,53 @@ static ID *link_named_part_ex(
ID *BLO_library_link_named_part(Main *mainl,
BlendHandle **bh,
const short idcode,
const char *name)
const char *name,
const struct LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
return link_named_part(mainl, fd, idcode, name, 0);
}
/**
* Link a named data-block from an external blend file.
* Optionally instantiate the object/collection in the scene when the flags are set.
*
* \param mainl: The main database to link from (not the active one).
* \param bh: The blender file handle.
* \param idcode: The kind of data-block to link.
* \param name: The name of the data-block (without the 2 char ID prefix).
* \param flag: Options for linking, used for instantiating.
* \return the linked ID when found.
*/
ID *BLO_library_link_named_part_ex(
Main *mainl, BlendHandle **bh, const short idcode, const char *name, const int flag)
{
FileData *fd = (FileData *)(*bh);
return link_named_part_ex(mainl, fd, idcode, name, flag);
return link_named_part(mainl, fd, idcode, name, params->flag);
}
/* common routine to append/link something from a library */
static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepath)
/**
* Checks if the \a idcode needs to be tagged with #LIB_TAG_DOIT when linking/appending.
*/
static bool library_link_idcode_needs_tag_check(const short idcode, const int flag)
{
if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
/* Always true because of #add_loose_objects_to_scene & #add_collections_to_scene. */
if (ELEM(idcode, ID_OB, ID_GR)) {
return true;
}
}
return false;
}
/**
* Clears #LIB_TAG_DOIT based on the result of #library_link_idcode_needs_tag_check.
*/
static void library_link_clear_tag(Main *mainvar, const int flag)
{
for (int i = 0; i < MAX_LIBARRAY; i++) {
const short idcode = BKE_idtype_idcode_from_index(i);
BLI_assert(idcode != -1);
if (library_link_idcode_needs_tag_check(idcode, flag)) {
BKE_main_id_tag_idcode(mainvar, idcode, LIB_TAG_DOIT, false);
}
}
}
static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepath, const int flag)
{
Main *mainl;
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
/* clear for objects and collections instantiating tag */
BKE_main_id_tag_listbase(&(mainvar->objects), LIB_TAG_DOIT, false);
BKE_main_id_tag_listbase(&(mainvar->collections), LIB_TAG_DOIT, false);
if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
/* Clear for objects and collections instantiating tag. */
library_link_clear_tag(mainvar, flag);
}
/* make mains */
blo_split_main((*fd)->mainlist, mainvar);
@@ -10595,19 +10599,49 @@ static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepa
return mainl;
}
void BLO_library_link_params_init(struct LibraryLink_Params *params,
struct Main *bmain,
const int flag)
{
memset(params, 0, sizeof(*params));
params->bmain = bmain;
params->flag = flag;
}
void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params,
struct Main *bmain,
const int flag,
/* Context arguments. */
struct Scene *scene,
struct ViewLayer *view_layer,
const struct View3D *v3d)
{
BLO_library_link_params_init(params, bmain, flag);
if (scene != NULL) {
/* Tagging is needed for instancing. */
params->flag |= BLO_LIBLINK_NEEDS_ID_TAG_DOIT;
params->context.scene = scene;
params->context.view_layer = view_layer;
params->context.v3d = v3d;
}
}
/**
* Initialize the #BlendHandle for linking library data.
*
* \param mainvar: The current main database, e.g. #G_MAIN or #CTX_data_main(C).
* \param bh: A blender file handle as returned by
* #BLO_blendhandle_from_file or #BLO_blendhandle_from_memory.
* \param filepath: Used for relative linking, copied to the `lib->filepath`.
* \return the library #Main, to be passed to #BLO_library_link_named_part_ex as \a mainl.
* \param params: Settings for linking that don't change from beginning to end of linking.
* \return the library #Main, to be passed to #BLO_library_link_named_part as \a mainl.
*/
Main *BLO_library_link_begin(Main *mainvar, BlendHandle **bh, const char *filepath)
Main *BLO_library_link_begin(BlendHandle **bh,
const char *filepath,
const struct LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
return library_link_begin(mainvar, &fd, filepath);
return library_link_begin(params->bmain, &fd, filepath, params->flag);
}
static void split_main_newid(Main *mainptr, Main *main_newid)
@@ -10642,8 +10676,8 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
*/
static void library_link_end(Main *mainl,
FileData **fd,
const short flag,
Main *bmain,
const int flag,
Scene *scene,
ViewLayer *view_layer,
const View3D *v3d)
@@ -10720,19 +10754,18 @@ static void library_link_end(Main *mainl,
/* Give a base to loose objects and collections.
* Only directly linked objects & collections are instantiated by
* #BLO_library_link_named_part_ex & co,
* #BLO_library_link_named_part & co,
* here we handle indirect ones and other possible edge-cases. */
if (scene) {
add_collections_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
}
else {
/* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */
}
if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
/* Should always be true. */
if (scene != NULL) {
add_collections_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
}
/* Clear objects and collections instantiating tag. */
BKE_main_id_tag_listbase(&(mainvar->objects), LIB_TAG_DOIT, false);
BKE_main_id_tag_listbase(&(mainvar->collections), LIB_TAG_DOIT, false);
/* Clear objects and collections instantiating tag. */
library_link_clear_tag(mainvar, flag);
}
/* patch to prevent switch_endian happens twice */
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
@@ -10748,25 +10781,18 @@ static void library_link_end(Main *mainl,
*
* \param mainl: The main database to link from (not the active one).
* \param bh: The blender file handle (WARNING! may be freed by this function!).
* \param flag: Options for linking, used for instantiating.
* \param bmain: The main database in which to instantiate objects/collections
* \param scene: The scene in which to instantiate objects/collections
* (if NULL, no instantiation is done).
* \param view_layer: The scene layer in which to instantiate objects/collections
* (if NULL, no instantiation is done).
* \param v3d: The active 3D viewport
* (only to define local-view for instantiated objects & groups, can be NULL).
* \param params: Settings for linking that don't change from beginning to end of linking.
*/
void BLO_library_link_end(Main *mainl,
BlendHandle **bh,
int flag,
Main *bmain,
Scene *scene,
ViewLayer *view_layer,
const View3D *v3d)
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const struct LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
library_link_end(mainl, &fd, flag, bmain, scene, view_layer, v3d);
library_link_end(mainl,
&fd,
params->bmain,
params->flag,
params->context.scene,
params->context.view_layer,
params->context.v3d);
*bh = (BlendHandle *)fd;
}

View File

@@ -327,7 +327,10 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* here appending/linking starts */
mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath);
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init(&liblink_params, bmain, self->flag);
mainl = BLO_library_link_begin(&(self->blo_handle), self->relpath, &liblink_params);
{
int idcode_step = 0, idcode;
@@ -350,7 +353,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
if (item_idname) {
ID *id = BLO_library_link_named_part(
mainl, &(self->blo_handle), idcode, item_idname);
mainl, &(self->blo_handle), idcode, item_idname, &liblink_params);
if (id) {
#ifdef USE_RNA_DATABLOCKS
/* swap name for pointer to the id */
@@ -394,7 +397,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL);
BLO_library_link_end(mainl, &(self->blo_handle), &liblink_params);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;

View File

@@ -250,7 +250,11 @@ static void wm_link_do(WMLinkAppendData *lapp_data,
}
/* here appending/linking starts */
mainl = BLO_library_link_begin(bmain, &bh, libname);
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init_with_context(
&liblink_params, bmain, flag, scene, view_layer, v3d);
mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
lib = mainl->curlib;
BLI_assert(lib);
UNUSED_VARS_NDEBUG(lib);
@@ -276,7 +280,7 @@ static void wm_link_do(WMLinkAppendData *lapp_data,
continue;
}
new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag);
new_id = BLO_library_link_named_part(mainl, &bh, item->idcode, item->name, &liblink_params);
if (new_id) {
/* If the link is successful, clear item's libs 'todo' flags.
@@ -286,7 +290,7 @@ static void wm_link_do(WMLinkAppendData *lapp_data,
}
}
BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer, v3d);
BLO_library_link_end(mainl, &bh, &liblink_params);
BLO_blendhandle_close(bh);
}
}