Fix #111488: Copying object crashes Blender after recent refactor.

Caused by 8bb5916183.

Trivial mistake, would have been caught by a basic test, so also added
said test for the 'write partial' feature.
This commit is contained in:
Bastien Montagne 2023-08-25 11:01:46 +02:00
parent 4462100cee
commit e20a284cb9
3 changed files with 51 additions and 2 deletions

View File

@ -497,7 +497,7 @@ void BLO_main_expander(BLOExpandDoitCallback expand_doit_func);
* Loop over all ID data in Main to mark relations.
* Set (id->tag & LIB_TAG_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
*
* \param fdhandle: usually file-data, or own handle.
* \param fdhandle: usually file-data, or own handle. May be nullptr.
* \param mainvar: the Main database to expand.
*/
void BLO_expand_main(void *fdhandle, struct Main *mainvar);

View File

@ -4148,7 +4148,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
* Expanding should never modify ID pointers themselves.
* Handling of DNA deprecated data should never be needed in undo case. */
const int flag = IDWALK_READONLY | IDWALK_NO_ORIG_POINTERS_ACCESS |
((fd->flags & FD_FLAGS_IS_MEMFILE) ? 0 : IDWALK_DO_DEPRECATED_POINTERS);
((!fd || (fd->flags & FD_FLAGS_IS_MEMFILE)) ?
0 :
IDWALK_DO_DEPRECATED_POINTERS);
BKE_library_foreach_ID_link(nullptr, id_iter, expand_cb, &expander, flag);
do_it = true;

View File

@ -49,6 +49,52 @@ class TestBlendFileSaveLoadBasic(TestHelper):
assert orig_data == read_data
class TestBlendFileSavePartial(TestHelper):
OBJECT_MESH_NAME = "ObjectMesh"
OBJECT_MATERIAL_NAME = "ObjectMaterial"
OBJECT_NAME = "Object"
UNUSED_MESH_NAME = "UnusedMesh"
def __init__(self, args):
self.args = args
def test_save_load(self):
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
ob_mesh = bpy.data.meshes.new(self.OBJECT_MESH_NAME)
ob_material = bpy.data.materials.new(self.OBJECT_MATERIAL_NAME)
ob_mesh.materials.append(ob_material)
ob = bpy.data.objects.new(self.OBJECT_NAME, object_data=ob_mesh)
bpy.context.collection.objects.link(ob)
unused_mesh = bpy.data.meshes.new(self.UNUSED_MESH_NAME)
unused_mesh.materials.append(ob_material)
assert ob_mesh.users == 1
assert ob_material.users == 2
assert ob.users == 1
assert unused_mesh.users == 0
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_path = os.path.join(output_dir, "blendfile_io_partial.blend")
bpy.data.libraries.write(filepath=output_path, datablocks={ob, unused_mesh}, fake_user=False)
bpy.ops.wm.open_mainfile(filepath=output_path, load_ui=False)
assert self.OBJECT_MESH_NAME in bpy.data.meshes
assert self.OBJECT_MATERIAL_NAME in bpy.data.materials
assert self.OBJECT_NAME in bpy.data.objects
assert self.UNUSED_MESH_NAME in bpy.data.meshes
assert bpy.data.meshes[self.OBJECT_MESH_NAME].users == 1
assert bpy.data.materials[self.OBJECT_MATERIAL_NAME].users == 2
assert bpy.data.objects[self.OBJECT_NAME].users == 0
assert bpy.data.meshes[self.UNUSED_MESH_NAME].users == 0
# NOTE: Technically this should rather be in `bl_id_management.py` test, but that file uses `unittest` module,
# which makes mixing it with tests system used here and passing extra parameters complicated.
# Since the main effect of 'RUNTIME' ID tag is on file save, it can as well be here for now.
@ -145,6 +191,7 @@ class TestIdRuntimeTag(TestHelper):
TESTS = (
TestBlendFileSaveLoadBasic,
TestBlendFileSavePartial,
TestIdRuntimeTag,
)