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:
Dalai Felinto 2018-03-13 16:10:20 -03:00
parent 59aa8d22ef
commit e7c3c46e89
3 changed files with 79 additions and 25 deletions

@ -1632,7 +1632,6 @@ 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));
@ -1657,8 +1656,6 @@ static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob,
id_us_min(&ob->id); id_us_min(&ob->id);
return obn; return obn;
}
return NULL;
} }
static void libblock_relink_scene_collection(SceneCollection *sc) static void libblock_relink_scene_collection(SceneCollection *sc)
@ -1678,9 +1675,11 @@ 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)) {
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
link->data = single_object_users_object(bmain, scene, link->data, copy_groups); link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
} }
} }
}
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups); single_object_users_scene_collection(bmain, scene, nsc, flag, 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)

@ -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()