Commit: 351a9d084f59a6d11be9148830cec86eacb85529
Author: Bastien Montagne
Date:   Wed Jan 4 10:25:27 2017 +0100
Branches: master
https://developer.blender.org/rB351a9d084f59a6d11be9148830cec86eacb85529

Fix T50369: Objects can't be deleted from scene when using "link group objects 
to scene"

Main issue here was that in old usercount system 'user_real' did simply
not allow that kind of thing to work. With new pait of 'USER_EXTRA'
tags, it becomes possible to handle the case correctly, by merely refining
checks about indirectly use objects whene removing them from a scene.

Incidently, found another related bug, 'link group objects to scene' was not
incrementing objects' usercount - bad, very very bad!

===================================================================

M       source/blender/blenkernel/intern/library_remap.c
M       source/blender/editors/object/object_add.c
M       source/blender/editors/space_outliner/outliner_tools.c
M       source/blender/makesdna/DNA_ID.h

===================================================================

diff --git a/source/blender/blenkernel/intern/library_remap.c 
b/source/blender/blenkernel/intern/library_remap.c
index 4f1f6d9..cc7de92 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -883,9 +883,10 @@ void BKE_libblock_free_us(Main *bmain, void *idv)      /* 
test users */
         *     Since only 'user_one' usage of objects is groups, and only 'real 
user' usage of objects is scenes,
         *     removing that 'user_one' tag when there is no more real (scene) 
users of an object ensures it gets
         *     fully unlinked.
+        *     But only for local objects, not linked ones!
         *     Otherwise, there is no real way to get rid of an object anymore 
- better handling of this is TODO.
         */
-       if ((GS(id->name) == ID_OB) && (id->us == 1)) {
+       if ((GS(id->name) == ID_OB) && (id->us == 1) && (id->lib == NULL)) {
                id_us_clear_real(id);
        }
 
diff --git a/source/blender/editors/object/object_add.c 
b/source/blender/editors/object/object_add.c
index f42dafd..02b2d84 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1111,7 +1111,9 @@ static void object_delete_check_glsl_update(Object *ob)
 /* note: now unlinks constraints as well */
 void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
 {
-       if (BKE_library_ID_is_indirectly_used(bmain, base->object) && 
ID_REAL_USERS(base->object) <= 1) {
+       if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
+           ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 
0)
+       {
                /* We cannot delete indirectly used object... */
                printf("WARNING, undeletable object '%s', should have been 
catched before reaching this function!",
                       base->object->id.name + 2);
@@ -1145,7 +1147,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
                        BKE_reportf(op->reports, RPT_WARNING, "Cannot delete 
indirectly linked object '%s'", base->object->id.name + 2);
                        continue;
                }
-               else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 
1) {
+               else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 
&& ID_EXTRA_USERS(base->object) == 0) {
                        BKE_reportf(op->reports, RPT_WARNING,
                                "Cannot delete object '%s' from scene '%s', 
indirectly used objects need at least one user",
                                base->object->id.name + 2, scene->id.name + 2);
@@ -1179,7 +1181,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
                                if (scene_iter != scene && 
!ID_IS_LINKED_DATABLOCK(scene_iter)) {
                                        base_other = 
BKE_scene_base_find(scene_iter, base->object);
                                        if (base_other) {
-                                               if (is_indirectly_used && 
ID_REAL_USERS(base->object) <= 1) {
+                                               if (is_indirectly_used && 
ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
                                                        
BKE_reportf(op->reports, RPT_WARNING,
                                                                    "Cannot 
delete object '%s' from scene '%s', indirectly used objects need at least one 
user",
                                                                    
base->object->id.name + 2, scene_iter->id.name + 2);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c 
b/source/blender/editors/space_outliner/outliner_tools.c
index 7739d24..4eda797 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -411,7 +411,9 @@ static void object_delete_cb(
                        BKE_reportf(reports, RPT_WARNING, "Cannot delete 
indirectly linked object '%s'", base->object->id.name + 2);
                        return;
                }
-               else if (BKE_library_ID_is_indirectly_used(bmain, base->object) 
&& ID_REAL_USERS(base->object) <= 1) {
+               else if (BKE_library_ID_is_indirectly_used(bmain, base->object) 
&&
+                        ID_REAL_USERS(base->object) <= 1 && 
ID_EXTRA_USERS(base->object) == 0)
+               {
                        BKE_reportf(reports, RPT_WARNING,
                                    "Cannot delete object '%s' from scene '%s', 
indirectly used objects need at least one user",
                                    base->object->id.name + 2, scene->id.name + 
2);
@@ -525,7 +527,7 @@ static void group_linkobs2scene_cb(
                if (!base) {
                        /* link to scene */
                        base = BKE_scene_base_add(scene, gob->ob);
-                       id_lib_extern((ID *)gob->ob); /* in case these are from 
a linked group */
+                       id_us_plus(&gob->ob->id);
                }
                base->object->flag |= SELECT;
                base->flag |= SELECT;
@@ -842,7 +844,9 @@ static Base *outline_delete_hierarchy(bContext *C, 
ReportList *reports, Scene *s
                BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly 
linked object '%s'", base->object->id.name + 2);
                return base_next;
        }
-       else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && 
ID_REAL_USERS(base->object) <= 1) {
+       else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
+                ID_REAL_USERS(base->object) <= 1 && 
ID_EXTRA_USERS(base->object) == 0)
+       {
                BKE_reportf(reports, RPT_WARNING,
                            "Cannot delete object '%s' from scene '%s', 
indirectly used objects need at least one user",
                            base->object->id.name + 2, scene->id.name + 2);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index ed719b6..2c6f3d2 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -277,6 +277,7 @@ typedef enum ID_Type {
 
 #define ID_FAKE_USERS(id) ((((ID *)id)->flag & LIB_FAKEUSER) ? 1 : 0)
 #define ID_REAL_USERS(id) (((ID *)id)->us - ID_FAKE_USERS(id))
+#define ID_EXTRA_USERS(id) (((ID *)id)->tag & LIB_TAG_EXTRAUSER ? 1 : 0)
 
 #define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != 
ID_WM))

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to