forked from bartvdbraak/blender
Fix make single user crash
How to reproduce the crash: * Factory startup * 'u'key (make single user) It comes with a simple unittest to reproduce the original issue.
This commit is contained in:
parent
59aa8d22ef
commit
e7c3c46e89
@ -1632,33 +1632,30 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
|
|||||||
|
|
||||||
static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
|
static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
|
||||||
{
|
{
|
||||||
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
|
/* base gets copy of object */
|
||||||
/* base gets copy of object */
|
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
|
||||||
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
|
|
||||||
|
|
||||||
if (copy_groups) {
|
if (copy_groups) {
|
||||||
if (ob->flag & OB_FROMGROUP) {
|
if (ob->flag & OB_FROMGROUP) {
|
||||||
obn->flag |= OB_FROMGROUP;
|
obn->flag |= OB_FROMGROUP;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* copy already clears */
|
|
||||||
}
|
|
||||||
/* remap gpencil parenting */
|
|
||||||
|
|
||||||
if (scene->gpd) {
|
|
||||||
bGPdata *gpd = scene->gpd;
|
|
||||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
|
||||||
if (gpl->parent == ob) {
|
|
||||||
gpl->parent = obn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id_us_min(&ob->id);
|
|
||||||
return obn;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
else {
|
||||||
|
/* copy already clears */
|
||||||
|
}
|
||||||
|
/* remap gpencil parenting */
|
||||||
|
|
||||||
|
if (scene->gpd) {
|
||||||
|
bGPdata *gpd = scene->gpd;
|
||||||
|
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||||
|
if (gpl->parent == ob) {
|
||||||
|
gpl->parent = obn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id_us_min(&ob->id);
|
||||||
|
return obn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void libblock_relink_scene_collection(SceneCollection *sc)
|
static void libblock_relink_scene_collection(SceneCollection *sc)
|
||||||
@ -1678,7 +1675,9 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen
|
|||||||
Object *ob = link->data;
|
Object *ob = link->data;
|
||||||
/* an object may be in more than one collection */
|
/* an object may be in more than one collection */
|
||||||
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
|
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
|
||||||
link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
|
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
|
||||||
|
link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ VIEW_LAYER_TEST(object_link_a)
|
|||||||
VIEW_LAYER_TEST(object_link_b)
|
VIEW_LAYER_TEST(object_link_b)
|
||||||
VIEW_LAYER_TEST(object_link_c)
|
VIEW_LAYER_TEST(object_link_c)
|
||||||
VIEW_LAYER_TEST(operator_context)
|
VIEW_LAYER_TEST(operator_context)
|
||||||
|
VIEW_LAYER_TEST(make_single_user)
|
||||||
VIEW_LAYER_TEST(move_above_below_scene_collection_a)
|
VIEW_LAYER_TEST(move_above_below_scene_collection_a)
|
||||||
VIEW_LAYER_TEST(move_above_below_scene_collection_b)
|
VIEW_LAYER_TEST(move_above_below_scene_collection_b)
|
||||||
VIEW_LAYER_TEST(move_above_below_scene_collection_c)
|
VIEW_LAYER_TEST(move_above_below_scene_collection_c)
|
||||||
|
54
tests/python/view_layer/test_make_single_user.py
Normal file
54
tests/python/view_layer/test_make_single_user.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# ############################################################
|
||||||
|
# Importing - Same For All Render Layer Tests
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from view_layer_common import *
|
||||||
|
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
# Testing
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
class UnitTesting(ViewLayerTesting):
|
||||||
|
def test_make_single_user(self):
|
||||||
|
"""
|
||||||
|
Really basic test, just to check for crashes on basic files.
|
||||||
|
"""
|
||||||
|
import bpy
|
||||||
|
scene = bpy.context.scene
|
||||||
|
master_collection = scene.master_collection
|
||||||
|
view_layer = bpy.context.view_layer
|
||||||
|
ob = bpy.context.object
|
||||||
|
|
||||||
|
# clean up the scene a bit
|
||||||
|
for o in (o for o in view_layer.objects if o != ob):
|
||||||
|
view_layer.collections[0].collection.objects.unlink(o)
|
||||||
|
|
||||||
|
for v in (v for v in scene.view_layers if v != view_layer):
|
||||||
|
scene.view_layers.remove(v)
|
||||||
|
|
||||||
|
while master_collection.collections:
|
||||||
|
master_collection.collections.remove(
|
||||||
|
master_collection.collections[0])
|
||||||
|
|
||||||
|
view_layer.collections.link(master_collection)
|
||||||
|
ob.select_set('SELECT')
|
||||||
|
|
||||||
|
# update depsgraph
|
||||||
|
scene.update()
|
||||||
|
|
||||||
|
# test itself
|
||||||
|
bpy.ops.object.make_single_user(object=True)
|
||||||
|
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
# Main - Same For All Render Layer Tests
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
UnitTesting._extra_arguments = setup_extra_arguments(__file__)
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user