2023-06-15 03:09:04 +00:00
|
|
|
# SPDX-FileCopyrightText: 2020-2023 Blender Foundation
|
|
|
|
#
|
2022-02-10 22:07:11 +00:00
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
2020-02-13 16:48:00 +00:00
|
|
|
|
|
|
|
# ./blender.bin --background -noaudio --python tests/python/bl_blendfile_liblink.py
|
|
|
|
import bpy
|
|
|
|
import os
|
2020-02-14 10:02:22 +00:00
|
|
|
import sys
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2020-02-14 10:02:22 +00:00
|
|
|
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
|
|
|
|
from bl_blendfile_utils import TestHelper
|
2020-02-13 16:48:00 +00:00
|
|
|
|
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
class TestBlendLibLinkHelper(TestHelper):
|
2021-09-28 21:29:18 +00:00
|
|
|
|
2020-02-13 16:48:00 +00:00
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
@staticmethod
|
|
|
|
def reset_blender():
|
2021-03-04 06:43:12 +00:00
|
|
|
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
|
2021-08-31 15:45:08 +00:00
|
|
|
bpy.data.orphans_purge(do_recursive=True)
|
|
|
|
|
|
|
|
def unique_blendfile_name(self, base_name):
|
|
|
|
return base_name + self.__class__.__name__ + ".blend"
|
|
|
|
|
|
|
|
def init_lib_data_basic(self):
|
|
|
|
self.reset_blender()
|
2021-03-04 06:43:12 +00:00
|
|
|
|
2020-02-13 16:48:00 +00:00
|
|
|
me = bpy.data.meshes.new("LibMesh")
|
2021-08-31 15:45:08 +00:00
|
|
|
ob = bpy.data.objects.new("LibMesh", me)
|
|
|
|
coll = bpy.data.collections.new("LibMesh")
|
|
|
|
coll.objects.link(ob)
|
|
|
|
bpy.context.scene.collection.children.link(coll)
|
2020-02-13 16:48:00 +00:00
|
|
|
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
self.ensure_path(output_dir)
|
2020-12-10 06:16:18 +00:00
|
|
|
# Take care to keep the name unique so multiple test jobs can run at once.
|
2021-10-20 09:56:04 +00:00
|
|
|
output_lib_path = os.path.join(output_dir, self.unique_blendfile_name("blendlib_basic"))
|
|
|
|
|
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_lib_path, check_existing=False, compress=False)
|
|
|
|
|
|
|
|
return output_lib_path
|
|
|
|
|
|
|
|
def init_lib_data_indirect_lib(self):
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
self.ensure_path(output_dir)
|
|
|
|
|
|
|
|
# Create an indirect library containing a material.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
ma = bpy.data.materials.new("LibMaterial")
|
|
|
|
ma.use_fake_user = True
|
|
|
|
# Take care to keep the name unique so multiple test jobs can run at once.
|
|
|
|
output_lib_path = os.path.join(output_dir, self.unique_blendfile_name("blendlib_indirect_material"))
|
|
|
|
|
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_lib_path, check_existing=False, compress=False)
|
|
|
|
|
|
|
|
# Create a main library containing object etc., and linking material from indirect library.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Material")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMaterial")
|
|
|
|
ma = bpy.data.materials[0]
|
|
|
|
|
|
|
|
me = bpy.data.meshes.new("LibMesh")
|
|
|
|
me.materials.append(ma)
|
|
|
|
ob = bpy.data.objects.new("LibMesh", me)
|
|
|
|
coll = bpy.data.collections.new("LibMesh")
|
|
|
|
coll.objects.link(ob)
|
|
|
|
bpy.context.scene.collection.children.link(coll)
|
|
|
|
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
self.ensure_path(output_dir)
|
|
|
|
# Take care to keep the name unique so multiple test jobs can run at once.
|
|
|
|
output_lib_path = os.path.join(output_dir, self.unique_blendfile_name("blendlib_indirect_main"))
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_lib_path, check_existing=False, compress=False)
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
return output_lib_path
|
|
|
|
|
|
|
|
|
|
|
|
class TestBlendLibLinkSaveLoadBasic(TestBlendLibLinkHelper):
|
|
|
|
|
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
|
|
|
def test_link_save_load(self):
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
output_lib_path = self.init_lib_data_basic()
|
|
|
|
|
|
|
|
# Simple link of a single ObData.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_object_data=False)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 0
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
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)
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
read_data = self.blender_data_to_tuple(bpy.data, "read_data")
|
|
|
|
|
|
|
|
# Since there is no usage of linked mesh, it is lost during save/reload.
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 0
|
|
|
|
assert orig_data != read_data
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2021-11-19 11:44:27 +00:00
|
|
|
# Simple link of a single ObData with obdata instantiation.
|
2021-08-31 15:45:08 +00:00
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_object_data=True)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # Instance created for the mesh ObData.
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False)
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
|
|
|
|
|
|
|
read_data = self.blender_data_to_tuple(bpy.data, "read_data")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == read_data
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple link of a single Object.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Object")
|
2020-02-13 16:48:00 +00:00
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False)
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
|
|
|
|
|
|
|
read_data = self.blender_data_to_tuple(bpy.data, "read_data")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == read_data
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2021-11-19 11:44:27 +00:00
|
|
|
# Simple link of a single Collection, with Empty-instantiation.
|
2021-08-31 15:45:08 +00:00
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Collection")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_collections=True)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 2 # linked object and local empty instancing the collection
|
|
|
|
assert len(bpy.data.collections) == 1 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False)
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
|
|
|
|
|
|
|
read_data = self.blender_data_to_tuple(bpy.data, "read_data")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == read_data
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2021-11-19 11:44:27 +00:00
|
|
|
# Simple link of a single Collection, with ViewLayer-instantiation.
|
2021-08-31 15:45:08 +00:00
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Collection")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_collections=False)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert len(bpy.data.collections) == 1 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
# Linked collection should have been added to the scene's master collection children.
|
2022-09-14 06:18:59 +00:00
|
|
|
assert bpy.data.collections[0] in set(bpy.data.scenes[0].collection.children)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2020-02-14 10:02:22 +00:00
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False)
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
2020-02-13 16:48:00 +00:00
|
|
|
|
2020-02-14 10:02:22 +00:00
|
|
|
read_data = self.blender_data_to_tuple(bpy.data, "read_data")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == read_data
|
2020-02-13 16:48:00 +00:00
|
|
|
|
|
|
|
|
2022-11-24 09:50:58 +00:00
|
|
|
class TestBlendLibLinkIndirect(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_indirect_lib()
|
|
|
|
|
|
|
|
# Simple link of a single ObData.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh", instance_object_data=False)
|
|
|
|
|
|
|
|
assert len(bpy.data.materials) == 1
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 0
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
|
|
|
|
|
|
|
mesh = bpy.data.meshes[0]
|
|
|
|
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.
|
2022-12-05 01:54:00 +00:00
|
|
|
assert material.is_library_indirect
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
assert mesh.library is not None
|
|
|
|
assert mesh.use_fake_user is False
|
|
|
|
assert mesh.users == 0
|
2022-12-05 01:54:00 +00:00
|
|
|
# IDs explicitely linked by the user are forcefully considered directly linked.
|
2023-04-14 10:10:21 +00:00
|
|
|
assert mesh.is_library_indirect is False
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
ob = bpy.data.objects.new("LocalMesh", mesh)
|
|
|
|
coll = bpy.data.collections.new("LocalMesh")
|
|
|
|
coll.objects.link(ob)
|
|
|
|
bpy.context.scene.collection.children.link(coll)
|
|
|
|
|
|
|
|
assert material.users == 2
|
2022-12-05 01:54:00 +00:00
|
|
|
assert material.is_library_indirect
|
2022-11-24 09:50:58 +00:00
|
|
|
assert mesh.users == 1
|
2023-04-14 10:10:21 +00:00
|
|
|
assert mesh.is_library_indirect is False
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
ob.material_slots[0].link = 'OBJECT'
|
|
|
|
ob.material_slots[0].material = material
|
|
|
|
|
|
|
|
assert material.users == 3
|
2023-04-14 10:10:21 +00:00
|
|
|
assert material.is_library_indirect is False
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
ob.material_slots[0].material = None
|
|
|
|
|
|
|
|
assert material.users == 2
|
2022-12-05 01:54:00 +00:00
|
|
|
# This is not properly updated whene removing a local user of linked data.
|
2023-04-14 10:10:21 +00:00
|
|
|
assert material.is_library_indirect is False
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
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
|
Address #105786: How to handle linked data with 'fake user' set.
133dde41bb changed how 'fake user' flag is handled with linked data.
Previous behavior was a bug/inconsistency, in that the 'directly linked'
tag would be 'over-set' and never cleared, forcing saving references to
a lot of unused linked data.
Note that ideally, 'Fake user' flag should be ignored, and the only way
to decide whether to keep or not a linked ID should be whether it's
actually used by some local data.
However, #103867 and #105687 show that this is causing issues in some cases,
where users wrongly relied on the linked data's pre-defined 'Fake user' flag
to keep their linked data in their production files, even if said data had no
real user.
While not ideal, for now we should consider 'fake user' flag for linked data
as a real usage case. A better handling of this edge-case is related to
wider designs aboud handling of 'non used' data on file save, whether
linked IDs should keep track of being explicitly or implicitly linked by
the user, etc.
2023-03-20 14:01:53 +00:00
|
|
|
# Currently linked data with 'fake user' set are considered as directly linked data.
|
|
|
|
assert not material.is_library_indirect
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False)
|
|
|
|
|
|
|
|
assert len(bpy.data.materials) == 1
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert len(bpy.data.collections) == 1 # Scene's master collection is not listed here
|
|
|
|
|
|
|
|
mesh = bpy.data.meshes[0]
|
|
|
|
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.
|
Address #105786: How to handle linked data with 'fake user' set.
133dde41bb changed how 'fake user' flag is handled with linked data.
Previous behavior was a bug/inconsistency, in that the 'directly linked'
tag would be 'over-set' and never cleared, forcing saving references to
a lot of unused linked data.
Note that ideally, 'Fake user' flag should be ignored, and the only way
to decide whether to keep or not a linked ID should be whether it's
actually used by some local data.
However, #103867 and #105687 show that this is causing issues in some cases,
where users wrongly relied on the linked data's pre-defined 'Fake user' flag
to keep their linked data in their production files, even if said data had no
real user.
While not ideal, for now we should consider 'fake user' flag for linked data
as a real usage case. A better handling of this edge-case is related to
wider designs aboud handling of 'non used' data on file save, whether
linked IDs should keep track of being explicitly or implicitly linked by
the user, etc.
2023-03-20 14:01:53 +00:00
|
|
|
# Currently linked data with 'fake user' set are considered as directly linked data.
|
|
|
|
assert not material.is_library_indirect
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
assert mesh.library is not None
|
|
|
|
assert mesh.use_fake_user is False
|
|
|
|
assert mesh.users == 1
|
2023-04-14 10:10:21 +00:00
|
|
|
assert mesh.is_library_indirect is False
|
2022-11-24 09:50:58 +00:00
|
|
|
|
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
class TestBlendLibAppendBasic(TestBlendLibLinkHelper):
|
|
|
|
|
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
|
|
|
def test_append(self):
|
|
|
|
output_dir = self.args.output_dir
|
2021-10-20 09:56:04 +00:00
|
|
|
output_lib_path = self.init_lib_data_indirect_lib()
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple append of a single ObData.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=False, set_fake=False, use_recursive=False, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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 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 == 0
|
|
|
|
assert len(bpy.data.objects) == 0
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2021-11-19 11:44:27 +00:00
|
|
|
# Simple append of a single ObData with obdata instantiation.
|
2021-08-31 15:45:08 +00:00
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=True, set_fake=False, use_recursive=False, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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 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 len(bpy.data.objects) == 1 # Instance created for the mesh ObData.
|
|
|
|
assert bpy.data.objects[0].library is None
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple append of a single ObData with fake user.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Mesh")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=False, set_fake=True, use_recursive=False, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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 len(bpy.data.meshes) == 1
|
|
|
|
assert bpy.data.meshes[0].library is None
|
|
|
|
assert bpy.data.meshes[0].use_fake_user is True
|
|
|
|
assert bpy.data.meshes[0].users == 1
|
|
|
|
assert len(bpy.data.objects) == 0
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple append of a single Object.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Object")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=False, set_fake=False, use_recursive=False, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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 len(bpy.data.meshes) == 1
|
|
|
|
assert bpy.data.meshes[0].library is None
|
|
|
|
assert bpy.data.meshes[0].users == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert bpy.data.objects[0].library is None
|
|
|
|
assert bpy.data.objects[0].users == 1
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple recursive append of a single Object.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Object")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.materials) == 1
|
|
|
|
assert bpy.data.materials[0].library is None
|
|
|
|
assert bpy.data.materials[0].users == 1 # Fake user is cleared when appending.
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert bpy.data.meshes[0].library is None
|
|
|
|
assert bpy.data.meshes[0].users == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert bpy.data.objects[0].library is None
|
|
|
|
assert bpy.data.objects[0].users == 1
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
# Simple recursive append of a single Collection.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Collection")
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
2021-09-23 10:56:05 +00:00
|
|
|
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
|
2021-08-31 15:45:08 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.materials) == 1
|
|
|
|
assert bpy.data.materials[0].library is None
|
|
|
|
assert bpy.data.materials[0].users == 1 # Fake user is cleared when appending.
|
|
|
|
assert bpy.data.meshes[0].library is None
|
|
|
|
assert bpy.data.meshes[0].users == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert bpy.data.objects[0].library is None
|
|
|
|
assert bpy.data.objects[0].users == 1
|
|
|
|
assert len(bpy.data.collections) == 1 # Scene's master collection is not listed here
|
|
|
|
assert bpy.data.collections[0].library is None
|
|
|
|
assert bpy.data.collections[0].users == 1
|
2021-08-31 15:45:08 +00:00
|
|
|
|
|
|
|
|
2021-09-23 10:56:05 +00:00
|
|
|
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)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
for ob in bpy.data.objects:
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
|
|
|
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=True)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
for ob in bpy.data.objects:
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
|
|
|
|
bpy.ops.wm.append(directory=link_dir, filename="LibMesh",
|
|
|
|
instance_object_data=False, set_fake=False, use_recursive=True, do_reuse_local_id=False)
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
for ob in bpy.data.objects:
|
2022-09-14 06:18:59 +00:00
|
|
|
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
|
2021-09-23 10:56:05 +00:00
|
|
|
|
|
|
|
|
2021-11-04 10:25:30 +00:00
|
|
|
class TestBlendLibLibraryReload(TestBlendLibLinkHelper):
|
2021-11-02 14:33:30 +00:00
|
|
|
|
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
|
|
|
def test_link_reload(self):
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
output_lib_path = self.init_lib_data_basic()
|
|
|
|
|
|
|
|
# Simple link of a single Object, and reload.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Object")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-11-02 14:33:30 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
bpy.ops.wm.lib_reload(library=bpy.data.objects[0].name)
|
|
|
|
|
|
|
|
reload_data = self.blender_data_to_tuple(bpy.data, "reload_data")
|
|
|
|
|
|
|
|
print(orig_data)
|
|
|
|
print(reload_data)
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == reload_data
|
2021-11-02 14:33:30 +00:00
|
|
|
|
2021-11-04 10:25:30 +00:00
|
|
|
|
|
|
|
class TestBlendLibLibraryRelocate(TestBlendLibLinkHelper):
|
|
|
|
|
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
2021-11-02 14:33:30 +00:00
|
|
|
def test_link_relocate(self):
|
|
|
|
output_dir = self.args.output_dir
|
|
|
|
output_lib_path = self.init_lib_data_basic()
|
|
|
|
|
|
|
|
# Simple link of a single Object, and reload.
|
|
|
|
self.reset_blender()
|
|
|
|
|
|
|
|
link_dir = os.path.join(output_lib_path, "Object")
|
|
|
|
bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1
|
|
|
|
assert len(bpy.data.collections) == 0 # Scene's master collection is not listed here
|
2021-11-02 14:33:30 +00:00
|
|
|
|
|
|
|
orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
|
|
|
|
|
|
|
|
lib_path, lib_ext = os.path.splitext(output_lib_path)
|
|
|
|
new_lib_path = lib_path + "_relocate" + lib_ext
|
2021-11-04 14:03:55 +00:00
|
|
|
os.replace(output_lib_path, new_lib_path)
|
2021-11-02 14:33:30 +00:00
|
|
|
|
|
|
|
bpy.ops.wm.lib_relocate(library=bpy.data.objects[0].name, directory="", filename=new_lib_path)
|
|
|
|
|
|
|
|
relocate_data = self.blender_data_to_tuple(bpy.data, "relocate_data")
|
|
|
|
|
|
|
|
print(orig_data)
|
|
|
|
print(relocate_data)
|
2022-09-14 06:18:59 +00:00
|
|
|
assert orig_data == relocate_data
|
2021-11-02 14:33:30 +00:00
|
|
|
|
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
# Python library loader context manager.
|
2021-11-11 13:54:26 +00:00
|
|
|
class TestBlendLibDataLibrariesLoad(TestBlendLibLinkHelper):
|
|
|
|
|
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
def do_libload_init(self):
|
2021-11-11 13:54:26 +00:00
|
|
|
output_dir = self.args.output_dir
|
|
|
|
output_lib_path = self.init_lib_data_basic()
|
|
|
|
|
|
|
|
# Simple link of a single Object, and reload.
|
|
|
|
self.reset_blender()
|
2023-03-03 04:55:33 +00:00
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
return output_lib_path
|
2021-11-11 13:54:26 +00:00
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
def do_libload(self, **load_kwargs):
|
|
|
|
with bpy.data.libraries.load(**load_kwargs) as lib_ctx:
|
2021-11-11 13:54:26 +00:00
|
|
|
lib_src, lib_link = lib_ctx
|
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(lib_src.meshes) == 1
|
|
|
|
assert len(lib_src.objects) == 1
|
|
|
|
assert len(lib_src.collections) == 1
|
2021-11-11 13:54:26 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(lib_link.meshes) == 0
|
|
|
|
assert len(lib_link.objects) == 0
|
|
|
|
assert len(lib_link.collections) == 0
|
2021-11-11 13:54:26 +00:00
|
|
|
|
|
|
|
lib_link.collections.append(lib_src.collections[0])
|
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
# Linking/append/liboverride happens when living the context manager.
|
|
|
|
|
|
|
|
|
|
|
|
class TestBlendLibDataLibrariesLoadAppend(TestBlendLibDataLibrariesLoad):
|
|
|
|
|
|
|
|
def test_libload_append(self):
|
|
|
|
output_lib_path = self.do_libload_init()
|
|
|
|
self.do_libload(filepath=output_lib_path, link=False, create_liboverrides=False)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 1
|
|
|
|
|
|
|
|
# Append, so all data should have been made local.
|
|
|
|
assert bpy.data.meshes[0].library is None
|
|
|
|
assert bpy.data.objects[0].library is None
|
|
|
|
assert bpy.data.collections[0].library is None
|
|
|
|
|
|
|
|
|
|
|
|
class TestBlendLibDataLibrariesLoadLink(TestBlendLibDataLibrariesLoad):
|
|
|
|
|
|
|
|
def test_libload_link(self):
|
|
|
|
output_lib_path = self.do_libload_init()
|
|
|
|
self.do_libload(filepath=output_lib_path, link=True, create_liboverrides=False)
|
2021-11-11 13:54:26 +00:00
|
|
|
|
2022-09-14 06:18:59 +00:00
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 1
|
2021-11-11 13:54:26 +00:00
|
|
|
|
2023-02-14 14:17:53 +00:00
|
|
|
# Link, so all data should have remained linked.
|
|
|
|
assert bpy.data.meshes[0].library is not None
|
|
|
|
assert bpy.data.objects[0].library is not None
|
|
|
|
assert bpy.data.collections[0].library is not None
|
|
|
|
|
|
|
|
|
|
|
|
class TestBlendLibDataLibrariesLoadLibOverride(TestBlendLibDataLibrariesLoad):
|
|
|
|
|
|
|
|
def test_libload_liboverride(self):
|
|
|
|
output_lib_path = self.do_libload_init()
|
|
|
|
self.do_libload(filepath=output_lib_path, link=True, create_liboverrides=True)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 2 # The linked one and its local liboverride.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[0].library is None
|
2023-04-14 10:10:21 +00:00
|
|
|
assert bpy.data.collections[0].is_runtime_data is False
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[0].override_library is not None
|
|
|
|
assert bpy.data.collections[0].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
|
|
|
# Should create another liboverride for the linked collection.
|
|
|
|
self.do_libload(filepath=output_lib_path, link=True, create_liboverrides=True, reuse_liboverrides=False)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 3 # The linked one and its two local liboverrides.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[1].library is None
|
2023-04-14 10:10:21 +00:00
|
|
|
assert bpy.data.collections[1].is_runtime_data is False
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[1].override_library is not None
|
|
|
|
assert bpy.data.collections[1].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
|
|
|
# This call should not change anything, first liboverrides should be found and 'reused'.
|
|
|
|
self.do_libload(filepath=output_lib_path, link=True, create_liboverrides=True, reuse_liboverrides=True)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 3 # The linked one and its two local liboverrides.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[1].library is None
|
2023-04-14 10:10:21 +00:00
|
|
|
assert bpy.data.collections[1].is_runtime_data is False
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[1].override_library is not None
|
|
|
|
assert bpy.data.collections[1].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
|
|
|
def test_libload_liboverride_runtime(self):
|
|
|
|
output_lib_path = self.do_libload_init()
|
|
|
|
self.do_libload(filepath=output_lib_path, link=True,
|
|
|
|
create_liboverrides=True,
|
|
|
|
create_liboverrides_runtime=True)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 2 # The linked one and its local liboverride.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[0].library is None
|
2023-03-03 04:55:33 +00:00
|
|
|
assert bpy.data.collections[0].is_runtime_data is True
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[0].override_library is not None
|
|
|
|
assert bpy.data.collections[0].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
|
|
|
# This call should not change anything, first liboverrides should be found and 'reused'.
|
|
|
|
self.do_libload(filepath=output_lib_path,
|
|
|
|
link=True,
|
|
|
|
create_liboverrides=True,
|
|
|
|
create_liboverrides_runtime=True,
|
|
|
|
reuse_liboverrides=True)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 2 # The linked one and its local liboverride.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[0].library is None
|
2023-03-03 04:55:33 +00:00
|
|
|
assert bpy.data.collections[0].is_runtime_data is True
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[0].override_library is not None
|
|
|
|
assert bpy.data.collections[0].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
|
|
|
# Should create another liboverride for the linked collection, since this time we request a non-runtime one.
|
|
|
|
self.do_libload(filepath=output_lib_path,
|
|
|
|
link=True,
|
|
|
|
create_liboverrides=True,
|
|
|
|
create_liboverrides_runtime=False,
|
|
|
|
reuse_liboverrides=True)
|
|
|
|
|
|
|
|
assert len(bpy.data.meshes) == 1
|
|
|
|
assert len(bpy.data.objects) == 1 # This code does no instantiation.
|
|
|
|
assert len(bpy.data.collections) == 3 # The linked one and its two local liboverrides.
|
|
|
|
|
|
|
|
# Link + LibOverride, so linked data should have remained linked.
|
|
|
|
assert bpy.data.meshes[-1].library is not None
|
|
|
|
assert bpy.data.objects[-1].library is not None
|
|
|
|
assert bpy.data.collections[-1].library is not None
|
|
|
|
|
|
|
|
# Only explicitely linked data gets a liboverride, without any handling of hierarchy/dependencies.
|
|
|
|
assert bpy.data.collections[1].library is None
|
2023-04-14 10:10:21 +00:00
|
|
|
assert bpy.data.collections[1].is_runtime_data is False
|
2023-02-14 14:17:53 +00:00
|
|
|
assert bpy.data.collections[1].override_library is not None
|
|
|
|
assert bpy.data.collections[1].override_library.reference == bpy.data.collections[-1]
|
|
|
|
|
2021-11-11 13:54:26 +00:00
|
|
|
|
2020-02-13 16:48:00 +00:00
|
|
|
TESTS = (
|
|
|
|
TestBlendLibLinkSaveLoadBasic,
|
2022-11-24 09:50:58 +00:00
|
|
|
TestBlendLibLinkIndirect,
|
|
|
|
|
2021-08-31 15:45:08 +00:00
|
|
|
TestBlendLibAppendBasic,
|
2021-09-23 10:56:05 +00:00
|
|
|
TestBlendLibAppendReuseID,
|
2022-11-24 09:50:58 +00:00
|
|
|
|
2021-11-04 10:25:30 +00:00
|
|
|
TestBlendLibLibraryReload,
|
|
|
|
TestBlendLibLibraryRelocate,
|
2023-02-14 14:17:53 +00:00
|
|
|
|
|
|
|
TestBlendLibDataLibrariesLoadAppend,
|
|
|
|
TestBlendLibDataLibrariesLoadLink,
|
|
|
|
TestBlendLibDataLibrariesLoadLibOverride,
|
2020-02-13 16:48:00 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def argparse_create():
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
# When --help or no args are given, print this help
|
|
|
|
description = "Test basic IO of blend file."
|
|
|
|
parser = argparse.ArgumentParser(description=description)
|
|
|
|
parser.add_argument(
|
|
|
|
"--output-dir",
|
|
|
|
dest="output_dir",
|
|
|
|
default=".",
|
|
|
|
help="Where to output temp saved blendfiles",
|
|
|
|
required=False,
|
|
|
|
)
|
|
|
|
|
|
|
|
return parser
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
args = argparse_create().parse_args()
|
|
|
|
|
2021-03-04 06:43:12 +00:00
|
|
|
# Don't write thumbnails into the home directory.
|
2021-09-06 08:56:02 +00:00
|
|
|
bpy.context.preferences.filepaths.file_preview_type = 'NONE'
|
2021-03-04 06:43:12 +00:00
|
|
|
|
2020-02-13 16:48:00 +00:00
|
|
|
for Test in TESTS:
|
|
|
|
Test(args).run_all_tests()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import sys
|
|
|
|
sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
|
2020-04-27 15:43:47 +00:00
|
|
|
main()
|