LibLink Append: Expose 'reuse ID' through new BLO flag, and add basic tests.

Option is now available to append operator, alsthough hidden and
disabled by default.
This commit is contained in:
Bastien Montagne 2021-09-23 12:56:05 +02:00
parent cb173d05dc
commit f48a4aa0f9
3 changed files with 88 additions and 8 deletions

View File

@ -213,6 +213,8 @@ typedef enum eBLOLibLinkFlags {
BLO_LIBLINK_APPEND_SET_FAKEUSER = 1 << 19,
/** Append (make local) also indirect dependencies of appendeds IDs. */
BLO_LIBLINK_APPEND_RECURSIVE = 1 << 20,
/** Try to re-use previously appended matching ID on new append. */
BLO_LIBLINK_APPEND_LOCAL_ID_REUSE = 1 << 21,
/** Instantiate object data IDs (i.e. create objects for them if needed). */
BLO_LIBLINK_OBDATA_INSTANCE = 1 << 24,
/** Instantiate collections as empties, instead of linking them into current view layer. */

View File

@ -152,6 +152,9 @@ static int wm_link_append_flag(wmOperator *op)
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;
@ -630,6 +633,7 @@ static void wm_append_do(WMLinkAppendData *lapp_data,
const bool do_recursive = (lapp_data->flag & BLO_LIBLINK_APPEND_RECURSIVE) != 0;
const bool set_fakeuser = (lapp_data->flag & BLO_LIBLINK_APPEND_SET_FAKEUSER) != 0;
const bool do_reuse_local_id = (lapp_data->flag & BLO_LIBLINK_APPEND_LOCAL_ID_REUSE) != 0;
LinkNode *itemlink;
@ -644,7 +648,6 @@ static void wm_append_do(WMLinkAppendData *lapp_data,
BLI_ghash_insert(lapp_data->new_id_to_item, id, item);
}
const bool do_reuse_existing_id = false;
lapp_data->library_weak_reference_mapping = BKE_main_library_weak_reference_create(bmain);
/* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
@ -676,7 +679,7 @@ static void wm_append_do(WMLinkAppendData *lapp_data,
CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
item->append_action = WM_APPEND_ACT_KEEP_LINKED;
}
else if (do_reuse_existing_id && existing_local_id != NULL) {
else if (do_reuse_local_id && existing_local_id != NULL) {
CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
item->append_action = WM_APPEND_ACT_REUSE_LOCAL;
item->customdata = existing_local_id;
@ -1219,14 +1222,25 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
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",

View File

@ -165,7 +165,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Mesh")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=False)
instance_object_data=False, set_fake=False, use_recursive=False, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
@ -179,7 +179,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Mesh")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=True, set_fake=False, use_recursive=False)
instance_object_data=True, set_fake=False, use_recursive=False, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
@ -194,7 +194,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Mesh")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=True, use_recursive=False)
instance_object_data=False, set_fake=True, use_recursive=False, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
@ -208,7 +208,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Object")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=False)
instance_object_data=False, set_fake=False, use_recursive=False, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
# This one fails currently, for unclear reasons.
@ -224,7 +224,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Object")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=True)
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
@ -239,7 +239,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
link_dir = os.path.join(output_lib_path, "Collection")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=True)
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
assert(bpy.data.meshes[0].library is None)
assert(bpy.data.meshes[0].users == 1)
@ -251,9 +251,73 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
assert(bpy.data.collections[0].users == 1)
class TestBlendLibAppendReuseID(TestBlendLibLinkHelper):
def __init__(self, args):
self.args = args
def test_append(self):
output_dir = self.args.output_dir
output_lib_path = self.init_lib_data_basic()
# Append of a single Object, and then append it again.
self.reset_blender()
link_dir = os.path.join(output_lib_path, "Object")
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
assert(bpy.data.meshes[0].use_fake_user is False)
assert(bpy.data.meshes[0].users == 1)
assert(bpy.data.meshes[0].library_weak_reference is not None)
assert(bpy.data.meshes[0].library_weak_reference.filepath == output_lib_path)
assert(bpy.data.meshes[0].library_weak_reference.id_name == "MELibMesh")
assert(len(bpy.data.objects) == 1)
for ob in bpy.data.objects:
assert(ob.library is None)
assert(ob.library_weak_reference is None)
assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=True)
assert(len(bpy.data.meshes) == 1)
assert(bpy.data.meshes[0].library is None)
assert(bpy.data.meshes[0].use_fake_user is False)
assert(bpy.data.meshes[0].users == 2)
assert(bpy.data.meshes[0].library_weak_reference is not None)
assert(bpy.data.meshes[0].library_weak_reference.filepath == output_lib_path)
assert(bpy.data.meshes[0].library_weak_reference.id_name == "MELibMesh")
assert(len(bpy.data.objects) == 2)
for ob in bpy.data.objects:
assert(ob.library is None)
assert(ob.library_weak_reference is None)
assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
assert(len(bpy.data.meshes) == 2)
assert(bpy.data.meshes[0].library_weak_reference is None)
assert(bpy.data.meshes[1].library is None)
assert(bpy.data.meshes[1].use_fake_user is False)
assert(bpy.data.meshes[1].users == 1)
assert(bpy.data.meshes[1].library_weak_reference is not None)
assert(bpy.data.meshes[1].library_weak_reference.filepath == output_lib_path)
assert(bpy.data.meshes[1].library_weak_reference.id_name == "MELibMesh")
assert(len(bpy.data.objects) == 3)
for ob in bpy.data.objects:
assert(ob.library is None)
assert(ob.library_weak_reference is None)
assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
TESTS = (
TestBlendLibLinkSaveLoadBasic,
TestBlendLibAppendBasic,
TestBlendLibAppendReuseID,
)