Always clear 'fake user' flag from linked data. #111042

Merged
Bastien Montagne merged 1 commits from mont29/blender:linked-data-ignore-fakeuser into main 2023-08-21 15:33:32 +02:00
4 changed files with 27 additions and 36 deletions

View File

@ -2061,6 +2061,10 @@ static void direct_link_id_common(
}
id->lib = current_library;
if (id->lib) {
/* Always fully clear fake user flag for linked data. */
id->flag &= ~LIB_FAKEUSER;
}
id->us = ID_FAKE_USERS(id);
id->icon_id = 0;
id->newid = nullptr; /* Needed because .blend may have been saved with crap value here... */

View File

@ -1225,16 +1225,6 @@ static bool write_file_handle(Main *mainvar,
* asap afterward. */
id_lib_extern(id_iter);
}
else if (ID_FAKE_USERS(id_iter) > 0 && id_iter->asset_data == nullptr) {
/* Even though fake user is not directly editable by the user on linked data, it is a
* common 'work-around' to set it in library files on data-blocks that need to be linked
* but typically do not have an actual real user (e.g. texts, etc.).
* See e.g. #105687 and #103867.
*
* Would be good to find a better solution, but for now consider these as directly linked
* as well. */
id_lib_extern(id_iter);
}
else {
id_iter->tag |= LIB_TAG_INDIRECT;
id_iter->tag &= ~LIB_TAG_EXTERN;

View File

@ -115,10 +115,11 @@ class TestIdRuntimeTag(TestHelper):
assert linked_material.is_library_indirect is False
link_dir = os.path.join(output_lib_path, "Mesh")
bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_object_data=False)
linked_mesh = bpy.data.meshes['LibMesh']
assert linked_mesh.is_library_indirect is False
assert linked_mesh.use_fake_user is False
obj.data = linked_mesh
obj.material_slots[0].link = 'OBJECT'
@ -131,17 +132,15 @@ class TestIdRuntimeTag(TestHelper):
# so writing .blend file will have properly reset its tag to indirectly linked data.
assert linked_material.is_library_indirect
# Only usage of this linked mesh is a runtime ID (object), but it is flagged as 'fake user' in its library,
# so writing .blend file will have kept its tag to directly linked data.
assert not linked_mesh.is_library_indirect
# Only usage of this linked mesh is a runtime ID (object),
# so writing .blend file will have properly reset its tag to indirectly linked data.
assert linked_mesh.is_library_indirect
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
assert 'Cube' not in bpy.data.objects
assert 'LibMaterial' in bpy.data.materials # Pulled-in by the linked mesh.
linked_mesh = bpy.data.meshes['LibMesh']
assert linked_mesh.use_fake_user is True
assert linked_mesh.is_library_indirect is False
assert 'LibMaterial' not in bpy.data.materials
assert 'libMesh' not in bpy.data.meshes
TESTS = (

View File

@ -214,9 +214,9 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper):
material = bpy.data.materials[0]
assert material.library is not None
assert material.use_fake_user is True
assert material.users == 2 # Fake user is not cleared when linking.
assert material.is_library_indirect
assert material.use_fake_user is False # Fake user is cleared when linking.
assert material.users == 1
assert material.is_library_indirect is True
assert mesh.library is not None
assert mesh.use_fake_user is False
@ -229,29 +229,28 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper):
coll.objects.link(ob)
bpy.context.scene.collection.children.link(coll)
assert material.users == 2
assert material.is_library_indirect
assert material.users == 1
assert material.is_library_indirect is True
assert mesh.users == 1
assert mesh.is_library_indirect is False
ob.material_slots[0].link = 'OBJECT'
ob.material_slots[0].material = material
assert material.users == 3
assert material.users == 2
assert material.is_library_indirect is False
ob.material_slots[0].material = None
assert material.users == 2
assert material.users == 1
# This is not properly updated whene removing a local user of linked data.
assert material.is_library_indirect is False
output_work_path = os.path.join(output_dir, self.unique_blendfile_name("blendfile"))
bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False)
assert material.users == 2
# Currently linked data with 'fake user' set are considered as directly linked data.
assert not material.is_library_indirect
assert material.users == 1
assert material.is_library_indirect is True
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
@ -264,10 +263,9 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper):
material = bpy.data.materials[0]
assert material.library is not None
assert material.use_fake_user is True
assert material.users == 2 # Fake user is not cleared when linking.
# Currently linked data with 'fake user' set are considered as directly linked data.
assert not material.is_library_indirect
assert material.use_fake_user is False # Fake user is cleared when linking.
assert material.users == 1
assert material.is_library_indirect is True
assert mesh.library is not None
assert mesh.use_fake_user is False
@ -293,7 +291,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
assert len(bpy.data.materials) == 1
assert bpy.data.materials[0].library is not None
assert bpy.data.materials[0].users == 2 # Fake user is not cleared when linking.
assert bpy.data.materials[0].users == 1 # Fake user is cleared when linking.
assert len(bpy.data.meshes) == 1
assert bpy.data.meshes[0].library is None
assert bpy.data.meshes[0].use_fake_user is False
@ -310,7 +308,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
assert len(bpy.data.materials) == 1
assert bpy.data.materials[0].library is not None
assert bpy.data.materials[0].users == 2 # Fake user is not cleared when linking.
assert bpy.data.materials[0].users == 1 # Fake user is cleared when linking.
assert len(bpy.data.meshes) == 1
assert bpy.data.meshes[0].library is None
assert bpy.data.meshes[0].use_fake_user is False
@ -328,7 +326,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
assert len(bpy.data.materials) == 1
assert bpy.data.materials[0].library is not None
assert bpy.data.materials[0].users == 2 # Fake user is not cleared when linking.
assert bpy.data.materials[0].users == 1 # Fake user is cleared when linking.
assert len(bpy.data.meshes) == 1
assert bpy.data.meshes[0].library is None
assert bpy.data.meshes[0].use_fake_user is True
@ -345,7 +343,7 @@ class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
assert len(bpy.data.materials) == 1
assert bpy.data.materials[0].library is not None
assert bpy.data.materials[0].users == 2 # Fake user is not cleared when linking.
assert bpy.data.materials[0].users == 1 # Fake user is cleared when linking.
assert len(bpy.data.meshes) == 1
assert bpy.data.meshes[0].library is None
assert bpy.data.meshes[0].users == 1