Cleanup id->newid usage, initial work.
authorBastien Montagne <montagne29@wanadoo.fr>
Wed, 30 Nov 2016 14:25:54 +0000 (15:25 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Wed, 30 Nov 2016 14:27:59 +0000 (15:27 +0100)
This aims at always ensuring that ID.newid (and relevant LIB_TAG_NEW)
stay in clean (i.e. cleared) state by default.

To achieve this, instead of clearing after all id copy call (would be
horribly noisy, and bad for performances), we try to completely remove
the setting of id->newid by default when copying a new ID.

This implies that areas actually needing that info (mainly, object editing
area (make single user...) and make local area) have to ensure they set
it themselves as needed.

This is far from simple change, many complex code paths to consider, so
will need some serious testing. :/

20 files changed:
source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenkernel/intern/sca.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_relations.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/outliner_tree.c
source/blender/makesdna/DNA_ID.h
source/blender/makesrna/intern/rna_ID.c

index 00ea323f9343a554ec148ae7173198c27b86094b..a67e903877a6b230ddb17b05ab27a4ae8c57aa8b 100644 (file)
@@ -73,7 +73,7 @@ struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action);
 bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action);
 
 /* Copy AnimData Actions */
-void BKE_animdata_copy_id_action(struct ID *id);
+void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid);
 
 /* Merge copies of data from source AnimData block */
 typedef enum eAnimData_MergeCopy_Modes {
index 855eb10976c39842c8ead86194ec9bfb7a3ee70f..77ea7ecbefbbefaeb9b9219b91c49f95889baeb7 100644 (file)
@@ -80,6 +80,7 @@ void id_us_plus(struct ID *id);
 void id_us_min(struct ID *id);
 void id_fake_user_set(struct ID *id);
 void id_fake_user_clear(struct ID *id);
+void BKE_id_clear_newpoin(struct ID *id);
 
 void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local);
 bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
index a5abc6beff8ac4af918ed52e599caefc1bc2d16c..212793923927c4423fb6a7fe5d6f832cff9efdc8 100644 (file)
@@ -308,17 +308,19 @@ bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
        return true;
 }
 
-void BKE_animdata_copy_id_action(ID *id)
+void BKE_animdata_copy_id_action(ID *id, const bool set_newid)
 {
        AnimData *adt = BKE_animdata_from_id(id);
        if (adt) {
                if (adt->action) {
                        id_us_min((ID *)adt->action);
-                       adt->action = BKE_action_copy(G.main, adt->action);
+                       adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(G.main, adt->action)) :
+                                                 BKE_action_copy(G.main, adt->action);
                }
                if (adt->tmpact) {
                        id_us_min((ID *)adt->tmpact);
-                       adt->tmpact = BKE_action_copy(G.main, adt->tmpact);
+                       adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(G.main, adt->tmpact)) :
+                                                 BKE_action_copy(G.main, adt->tmpact);
                }
        }
 }
index 8ef1fae115590797c358c5bfccc69fb6de522bee..0d509ecea0635e91061895f0dd0ddc0ccda2a78a 100644 (file)
@@ -249,6 +249,9 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
 
                        brush_new->id.us = 0;
 
+                       /* setting newid is mandatory for complex make_lib_local logic... */
+                       ID_NEW_SET(brush, brush_new);
+
                        if (!lib_local) {
                                BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
                        }
index 50f8423bbff96add5aaabc7c92507ca77e8b6562..7361645ba2c014b567cb0292cb479892c72c7ab6 100644 (file)
@@ -1428,7 +1428,6 @@ static void scene_sort_groups(Main *bmain, Scene *sce)
        /* test; are group objects all in this scene? */
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                ob->id.tag &= ~LIB_TAG_DOIT;
-               ob->id.newid = NULL; /* newid abuse for GroupObject */
        }
        for (base = sce->base.first; base; base = base->next)
                base->object->id.tag |= LIB_TAG_DOIT;
@@ -1459,6 +1458,11 @@ static void scene_sort_groups(Main *bmain, Scene *sce)
                        group->gobject = listb;
                }
        }
+
+       /* newid abused for GroupObject, cleanup. */
+       for (ob = bmain->object.first; ob; ob = ob->id.next) {
+               ob->id.newid = NULL;
+       }
 }
 
 static void dag_scene_tag_rebuild(Scene *sce)
index c9bad2160ffd2b2b0c90b55eb3af70b4bed6a9c4..a2d94ccc478f72cc3f17af07ccceec6ed1137107 100644 (file)
@@ -436,7 +436,6 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
 Image *BKE_image_copy(Main *bmain, Image *ima)
 {
        Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type);
-       ima->id.newid = &nima->id;
 
        BLI_strncpy(nima->name, ima->name, sizeof(ima->name));
 
index 3411eae22e1c6184f1eeb5f0f2a4384bf68bec8f..31c10c843da3bc3f7598715e331cc1597215b914 100644 (file)
@@ -263,6 +263,14 @@ void id_fake_user_clear(ID *id)
        }
 }
 
+void BKE_id_clear_newpoin(ID *id)
+{
+       if (id->newid) {
+               id->newid->tag &= ~LIB_TAG_NEW;
+       }
+       id->newid = NULL;
+}
+
 static int id_expand_local_callback(
         void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag))
 {
@@ -326,6 +334,17 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
                        if (id_copy(bmain, id, &id_new, false)) {
                                id_new->us = 0;
 
+                               /* setting newid is mandatory for complex make_lib_local logic... */
+                               ID_NEW_SET(id, id_new);
+                               Key *key = BKE_key_from_id(id), *key_new = BKE_key_from_id(id);
+                               if (key && key_new) {
+                                       ID_NEW_SET(key, key_new);
+                               }
+                               bNodeTree *ntree = ntreeFromID(id), *ntree_new = ntreeFromID(id_new);
+                               if (ntree && ntree_new) {
+                                       ID_NEW_SET(ntree, ntree_new);
+                               }
+
                                if (!lib_local) {
                                        BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE);
                                }
@@ -337,6 +356,8 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
 /**
  * Calls the appropriate make_local method for the block, unless test is set.
  *
+ * \note Always set ID->newid pointer in case it gets duplicated...
+ *
  * \param lib_local Special flag used when making a whole library's content local, it needs specific handling.
  *
  * \return true if the block can be made local.
@@ -561,6 +582,7 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
        return false;
 }
 
+/** Does *not* set ID->newid pointer. */
 bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
 {
        ID *newid = NULL;
@@ -571,11 +593,11 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
                if (RNA_property_editable(ptr, prop)) {
                        if (id_copy(CTX_data_main(C), id, &newid, false) && newid) {
                                /* copy animation actions too */
-                               BKE_animdata_copy_id_action(id);
+                               BKE_animdata_copy_id_action(id, false);
                                /* us is 1 by convention, but RNA_property_pointer_set
                                 * will also increment it, so set it to zero */
                                newid->us = 0;
-                               
+
                                /* assign copy */
                                RNA_id_pointer_create(newid, &idptr);
                                RNA_property_pointer_set(ptr, prop, idptr);
@@ -1120,9 +1142,6 @@ void *BKE_libblock_copy(Main *bmain, ID *id)
 
                memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
        }
-       
-       id->newid = idn;
-       idn->tag |= LIB_TAG_NEW;
 
        BKE_libblock_copy_data(idn, id, false);
        
@@ -1147,8 +1166,6 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
                memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
        }
 
-       id->newid = idn;
-       idn->tag |= LIB_TAG_NEW;
        idn->us = 1;
 
        BKE_libblock_copy_data(idn, id, do_action);
@@ -1662,7 +1679,6 @@ void BKE_library_make_local(
                const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
 
                for (; id; id = id->next) {
-                       id->newid = NULL;
                        id->tag &= ~LIB_TAG_DOIT;
 
                        if (id->lib == NULL) {
@@ -1862,6 +1878,7 @@ void BKE_library_make_local(
                }
        }
 
+       BKE_main_id_clear_newpoins(bmain);
        BLI_memarena_free(linklist_mem);
 }
 
index 4489ca907f6b20536bf91a7bd1a51a5d4dc39633..c6666ec5ced77c113c30cc33b5b4a79fa66c3d8d 100644 (file)
@@ -1215,6 +1215,9 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con
                        ob_new->id.us = 0;
                        ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL;
 
+                       /* setting newid is mandatory for complex make_lib_local logic... */
+                       ID_NEW_SET(ob, ob_new);
+
                        if (!lib_local) {
                                BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE);
                        }
index ebf9f0177310c6db0d5892123efbca1720e31097..628222ed3068bfe1185f26511b4af2ae89f2ea26 100644 (file)
@@ -225,8 +225,8 @@ RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
 /* preserve relationships between constraints and rigid bodies after duplication */
 void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
 {
-       ID_NEW(rbc->ob1);
-       ID_NEW(rbc->ob2);
+       ID_NEW_REMAP(rbc->ob1);
+       ID_NEW_REMAP(rbc->ob2);
 }
 
 /* ************************************** */
index c7f406089d91697f5456553e87fac8e42e0ed012..fa2213489326693f9fa40ea30feaf992ddc9c936 100644 (file)
@@ -602,41 +602,41 @@ void set_sca_new_poins_ob(Object *ob)
                if (act->flag & ACT_NEW) {
                        if (act->type==ACT_EDIT_OBJECT) {
                                bEditObjectActuator *eoa= act->data;
-                               ID_NEW(eoa->ob);
+                               ID_NEW_REMAP(eoa->ob);
                        }
                        else if (act->type==ACT_SCENE) {
                                bSceneActuator *sca= act->data;
-                               ID_NEW(sca->camera);
+                               ID_NEW_REMAP(sca->camera);
                        }
                        else if (act->type==ACT_CAMERA) {
                                bCameraActuator *ca= act->data;
-                               ID_NEW(ca->ob);
+                               ID_NEW_REMAP(ca->ob);
                        }
                        else if (act->type==ACT_OBJECT) {
                                bObjectActuator *oa= act->data;
-                               ID_NEW(oa->reference);
+                               ID_NEW_REMAP(oa->reference);
                        }
                        else if (act->type==ACT_MESSAGE) {
                                bMessageActuator *ma= act->data;
-                               ID_NEW(ma->toObject);
+                               ID_NEW_REMAP(ma->toObject);
                        }
                        else if (act->type==ACT_PARENT) {
                                bParentActuator *para = act->data;
-                               ID_NEW(para->ob);
+                               ID_NEW_REMAP(para->ob);
                        }
                        else if (act->type==ACT_ARMATURE) {
                                bArmatureActuator *aa = act->data;
-                               ID_NEW(aa->target);
-                               ID_NEW(aa->subtarget);
+                               ID_NEW_REMAP(aa->target);
+                               ID_NEW_REMAP(aa->subtarget);
                        }
                        else if (act->type==ACT_PROPERTY) {
                                bPropertyActuator *pa= act->data;
-                               ID_NEW(pa->ob);
+                               ID_NEW_REMAP(pa->ob);
                        }
                        else if (act->type==ACT_STEERING) {
                                bSteeringActuator *sta = act->data;
-                               ID_NEW(sta->navmesh);
-                               ID_NEW(sta->target);
+                               ID_NEW_REMAP(sta->navmesh);
+                               ID_NEW_REMAP(sta->target);
                        }
                }
                act= act->next;
index 6e1f11cb526069e186385d9297104c42d6e50a5a..a699427315e8b29bd23274c0ca1cd2d743cbb17a 100644 (file)
@@ -186,8 +186,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
                scen = BKE_libblock_copy(bmain, &sce->id);
                BLI_duplicatelist(&(scen->base), &(sce->base));
                
-               BKE_main_id_clear_newpoins(bmain);
-               
                id_us_plus((ID *)scen->world);
                id_us_plus((ID *)scen->set);
                /* id_us_plus((ID *)scen->gm.dome.warptext); */  /* XXX Not refcounted? see readfile.c */
@@ -225,7 +223,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
                }
 
                /* copy action and remove animation used by sequencer */
-               BKE_animdata_copy_id_action(&scen->id);
+               BKE_animdata_copy_id_action(&scen->id, false);
 
                if (type != SCE_COPY_FULL)
                        remove_sequencer_fcurves(scen);
@@ -318,7 +316,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
 
        /*  camera */
        if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
-               ID_NEW(scen->camera);
+               ID_NEW_REMAP(scen->camera);
        }
        
        /* before scene copy */
@@ -329,7 +327,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
                if (scen->world) {
                        id_us_plus((ID *)scen->world);
                        scen->world = BKE_world_copy(bmain, scen->world);
-                       BKE_animdata_copy_id_action((ID *)scen->world);
+                       BKE_animdata_copy_id_action((ID *)scen->world, false);
                }
 
                if (sce->ed) {
index 65d751a8a72c7b23a812f2b8b9ac7862567b0b04..1d2f5aee44062a9780cc7517628bc3fc84ddd7fa 100644 (file)
@@ -320,7 +320,8 @@ void BKE_sequencer_free_clipboard(void)
 /* Manage pointers in the clipboard.
  * note that these pointers should _never_ be access in the sequencer,
  * they are only for storage while in the clipboard
- * notice 'newid' is used for temp pointer storage here, validate on access.
+ * notice 'newid' is used for temp pointer storage here, validate on access (this is safe usage,
+ * since those datablocks are fully out of Main lists).
  */
 #define ID_PT (*id_pt)
 static void seqclipboard_ptr_free(ID **id_pt)
index 98c8a260993ec1c19a7b8ca300e1e390cb6f672d..af73410728b3c0d7a0b3a1c083ec9766ef301301 100644 (file)
@@ -8102,6 +8102,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
        id->lib = main->curlib;
        id->us = ID_FAKE_USERS(id);
        id->icon_id = 0;
+       id->newid = NULL;  /* Needed because .blend may have been saved with crap value here... */
        
        /* this case cannot be direct_linked: it's just the ID part */
        if (bhead->code == ID_ID) {
index bdad667f20684f5f411dc3f61d4a7012587f0265..4db1c845c2331e8a7651bd89014eea85d015ec65 100644 (file)
@@ -303,7 +303,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
                        break;
                case UI_ID_LOCAL:
                        if (id) {
-                               if (id_make_local(CTX_data_main(C), id, false, false)) {
+                               Main *bmain = CTX_data_main(C);
+                               if (id_make_local(bmain, id, false, false)) {
+                                       BKE_main_id_clear_newpoins(bmain);
+
                                        /* reassign to get get proper updates/notifiers */
                                        idptr = RNA_property_pointer_get(&template->ptr, template->prop);
                                        RNA_property_pointer_set(&template->ptr, template->prop, idptr);
index 6647102acadf1cba2e9fd41799766927df98c9bd..02dd3ed2df5914e8f0819e7e5757e1e731e8e396 100644 (file)
@@ -1350,7 +1350,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
 
        for (dob = lb->first; dob; dob = dob->next) {
                Base *basen;
-               Object *ob = BKE_object_copy(bmain, dob->ob);
+               Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
 
                /* font duplis can have a totcol without material, we get them from parent
                 * should be implemented better...
@@ -1394,6 +1394,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                        }
                }
 
+               /* Remap new object to itself, and clear again newid pointer of orig object. */
+               BKE_libblock_relink(&ob->id);
+               set_sca_new_poins_ob(ob);
+               BKE_id_clear_newpoin(&dob->ob->id);
+
                DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
 
@@ -1484,8 +1489,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
        if (parent_gh)
                BLI_ghash_free(parent_gh, NULL, NULL);
 
-       copy_object_set_idnew(C);
-
        free_object_duplilist(lb);
 
        base->object->transflag &= ~OB_DUPLI;
@@ -1960,8 +1963,12 @@ void OBJECT_OT_convert(wmOperatorType *ot)
 
 /* used below, assumes id.new is correct */
 /* leaves selection of base/object unaltered */
+/* Does set ID->newid pointers. */
 static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
 {
+#define ID_NEW_REMAP_US(a)     if (      (a)->id.newid) { (a) = (void *)(a)->id.newid;       (a)->id.us++; }
+#define ID_NEW_REMAP_US2(a)    if (((ID *)a)->newid)    { (a) = ((ID  *)a)->newid;     ((ID *)a)->us++;    }
+
        Base *basen = NULL;
        Material ***matarar;
        Object *ob, *obn;
@@ -1973,7 +1980,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                ; /* nothing? */
        }
        else {
-               obn = BKE_object_copy(bmain, ob);
+               obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
                DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
 
                basen = MEM_mallocN(sizeof(Base), "duplibase");
@@ -1995,20 +2002,21 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
 
                /* duplicates using userflags */
                if (dupflag & USER_DUP_ACT) {
-                       BKE_animdata_copy_id_action(&obn->id);
+                       BKE_animdata_copy_id_action(&obn->id, true);
                }
 
                if (dupflag & USER_DUP_MAT) {
                        for (a = 0; a < obn->totcol; a++) {
                                id = (ID *)obn->mat[a];
                                if (id) {
-                                       ID_NEW_US(obn->mat[a])
-                                       else
-                                               obn->mat[a] = BKE_material_copy(bmain, obn->mat[a]);
+                                       ID_NEW_REMAP_US(obn->mat[a])
+                                       else {
+                                               obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+                                       }
                                        id_us_min(id);
 
                                        if (dupflag & USER_DUP_ACT) {
-                                               BKE_animdata_copy_id_action(&obn->mat[a]->id);
+                                               BKE_animdata_copy_id_action(&obn->mat[a]->id, true);
                                        }
                                }
                        }
@@ -2018,12 +2026,13 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                        for (psys = obn->particlesystem.first; psys; psys = psys->next) {
                                id = (ID *) psys->part;
                                if (id) {
-                                       ID_NEW_US(psys->part)
-                                       else
-                                               psys->part = BKE_particlesettings_copy(bmain, psys->part);
+                                       ID_NEW_REMAP_US(psys->part)
+                                       else {
+                                               psys->part = ID_NEW_SET(psys->part, BKE_particlesettings_copy(bmain, psys->part));
+                                       }
 
                                        if (dupflag & USER_DUP_ACT) {
-                                               BKE_animdata_copy_id_action(&psys->part->id);
+                                               BKE_animdata_copy_id_action(&psys->part->id, true);
                                        }
 
                                        id_us_min(id);
@@ -2037,9 +2046,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                switch (obn->type) {
                        case OB_MESH:
                                if (dupflag & USER_DUP_MESH) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_mesh_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2047,9 +2056,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_CURVE:
                                if (dupflag & USER_DUP_CURVE) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_curve_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2057,9 +2066,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_SURF:
                                if (dupflag & USER_DUP_SURF) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_curve_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2067,9 +2076,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_FONT:
                                if (dupflag & USER_DUP_FONT) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_curve_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2077,9 +2086,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_MBALL:
                                if (dupflag & USER_DUP_MBALL) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_mball_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2087,9 +2096,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_LAMP:
                                if (dupflag & USER_DUP_LAMP) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_lamp_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_lamp_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2100,9 +2109,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                if (obn->pose)
                                        BKE_pose_tag_recalc(bmain, obn->pose);
                                if (dupflag & USER_DUP_ARM) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_armature_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
                                                BKE_pose_rebuild(obn, obn->data);
                                                didit = 1;
                                        }
@@ -2111,9 +2120,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_LATTICE:
                                if (dupflag != 0) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_lattice_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2121,9 +2130,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_CAMERA:
                                if (dupflag != 0) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_camera_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2131,9 +2140,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                break;
                        case OB_SPEAKER:
                                if (dupflag != 0) {
-                                       ID_NEW_US2(obn->data)
+                                       ID_NEW_REMAP_US2(obn->data)
                                        else {
-                                               obn->data = BKE_speaker_copy(bmain, obn->data);
+                                               obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data));
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2148,12 +2157,15 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                        if (dupflag & USER_DUP_ACT) {
                                bActuator *act;
 
-                               BKE_animdata_copy_id_action((ID *)obn->data);
+                               BKE_animdata_copy_id_action((ID *)obn->data, true);
                                if (key) {
-                                       BKE_animdata_copy_id_action((ID *)key);
+                                       BKE_animdata_copy_id_action((ID *)key, true);
                                }
 
                                /* Update the duplicated action in the action actuators */
+                               /* XXX TODO this code is all wrong! actact->act is user-refcounted (see readfile.c),
+                                * and what about other ID pointers of other BGE logic bricks,
+                                * and since this is object-level, why is it only ran if obdata was duplicated??? -mont29 */
                                for (act = obn->actuators.first; act; act = act->next) {
                                        if (act->type == ACT_ACTION) {
                                                bActionActuator *actact = (bActionActuator *) act->data;
@@ -2170,9 +2182,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                        for (a = 0; a < obn->totcol; a++) {
                                                id = (ID *)(*matarar)[a];
                                                if (id) {
-                                                       ID_NEW_US((*matarar)[a])
-                                                       else
-                                                               (*matarar)[a] = BKE_material_copy(bmain, (*matarar)[a]);
+                                                       ID_NEW_REMAP_US((*matarar)[a])
+                                                       else {
+                                                               (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a]));
+                                                       }
                                                        id_us_min(id);
                                                }
                                        }
@@ -2181,6 +2194,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                }
        }
        return basen;
+
+#undef ID_NEW_REMAP_US
+#undef ID_NEW_REMAP_US2
 }
 
 /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
@@ -2193,8 +2209,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
        Base *basen;
        Object *ob;
 
-       BKE_main_id_clear_newpoins(bmain);
-       clear_sca_new_poins();  /* sensor/contr/act */
+       clear_sca_new_poins();  /* BGE logic */
 
        basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
        if (basen == NULL) {
@@ -2213,6 +2228,8 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
                ED_render_id_flush_update(bmain, ob->data);
        }
 
+       BKE_main_id_clear_newpoins(bmain);
+
        return basen;
 }
 
@@ -2224,8 +2241,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
        const bool linked = RNA_boolean_get(op->ptr, "linked");
        int dupflag = (linked) ? 0 : U.dupflag;
 
-       BKE_main_id_clear_newpoins(bmain);
-       clear_sca_new_poins();  /* sensor/contr/act */
+       clear_sca_new_poins();  /* BGE logic */
 
        CTX_DATA_BEGIN (C, Base *, base, selected_bases)
        {
@@ -2251,6 +2267,8 @@ static int duplicate_exec(bContext *C, wmOperator *op)
 
        copy_object_set_idnew(C);
 
+       BKE_main_id_clear_newpoins(bmain);
+
        DAG_relations_tag_update(bmain);
 
        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2309,8 +2327,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
        base->flag = ob->flag;
 
        /* prepare dupli */
-       BKE_main_id_clear_newpoins(bmain);
-       clear_sca_new_poins();  /* sensor/contr/act */
+       clear_sca_new_poins();  /* BGE logic */
 
        basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
 
@@ -2336,6 +2353,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
 
        copy_object_set_idnew(C);
 
+       BKE_main_id_clear_newpoins(bmain);
+
        DAG_relations_tag_update(bmain);
 
        MEM_freeN(base);
index f448e925dd951f4f48d1e7b97e323339f5466878..d670f4b8425404f7e9ba2926a62c6bc28fce1cfd 100644 (file)
@@ -1731,6 +1731,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
 
 /**************************** Make Single User ********************************/
 
+/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
 static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
 {
        Base *base;
@@ -1738,18 +1739,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
        Group *group, *groupn;
        GroupObject *go;
 
-       clear_sca_new_poins();  /* sensor/contr/act */
-
-       /* newid may still have some trash from Outliner tree building, so clear that first to avoid errors, see T26002.
-        * We have to clear whole datablocks, not only Object one may be accessed here, see T49905. */
-       ListBase *lbarray[MAX_LIBARRAY];
-       int a = set_listbasepointers(bmain, lbarray);
-       while (a--) {
-               ListBase *lb = lbarray[a];
-               for (ID *id = lb->first; id; id = id->next) {
-                       id->newid = NULL;
-               }
-       }
+       clear_sca_new_poins();  /* BGE logic */
 
        /* duplicate (must set newid) */
        for (base = FIRSTBASE; base; base = base->next) {
@@ -1758,8 +1748,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
                if ((base->flag & flag) == flag) {
                        if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
                                /* base gets copy of object */
-                               obn = BKE_object_copy(bmain, ob);
-                               base->object = obn;
+                               base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
 
                                if (copy_groups) {
                                        if (ob->flag & OB_FROMGROUP) {
@@ -1789,8 +1778,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
 
        /* duplicate groups that consist entirely of duplicated objects */
        for (group = bmain->group.first; group; group = group->id.next) {
-               group->id.newid = NULL;
-
                if (copy_groups && group->gobject.first) {
                        bool all_duplicated = true;
 
@@ -1802,10 +1789,11 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
                        }
 
                        if (all_duplicated) {
-                               groupn = BKE_group_copy(bmain, group);
+                               groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
 
-                               for (go = groupn->gobject.first; go; go = go->next)
+                               for (go = groupn->gobject.first; go; go = go->next) {
                                        go->ob = (Object *)go->ob->id.newid;
+                               }
                        }
                }
        }
@@ -1813,8 +1801,8 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
        /* group pointers in scene */
        BKE_scene_groups_relink(scene);
 
-       ID_NEW(scene->camera);
-       if (v3d) ID_NEW(v3d->camera);
+       ID_NEW_REMAP(scene->camera);
+       if (v3d) ID_NEW_REMAP(v3d->camera);
 
        /* object and group pointers */
        for (base = FIRSTBASE; base; base = base->next) {
@@ -1837,6 +1825,8 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
        }
 
        single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
+
+       BKE_main_id_clear_newpoins(bmain);
 }
 
 static void new_id_matar(Main *bmain, Material **matar, const int totcol)
@@ -1853,9 +1843,8 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol)
                                id_us_min(id);
                        }
                        else if (id->us > 1) {
-                               matar[a] = BKE_material_copy(bmain, matar[a]);
+                               matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
                                id_us_min(id);
-                               id->newid = (ID *)matar[a];
                        }
                }
        }
@@ -1883,45 +1872,46 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
 
                                switch (ob->type) {
                                        case OB_LAMP:
-                                               ob->data = la = BKE_lamp_copy(bmain, ob->data);
+                                               ob->data = la = ID_NEW_SET(ob->data, BKE_lamp_copy(bmain, ob->data));
                                                for (a = 0; a < MAX_MTEX; a++) {
                                                        if (la->mtex[a]) {
-                                                               ID_NEW(la->mtex[a]->object);
+                                                               ID_NEW_REMAP(la->mtex[a]->object);
                                                        }
                                                }
                                                break;
                                        case OB_CAMERA:
-                                               ob->data = BKE_camera_copy(bmain, ob->data);
+                                               ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
                                                break;
                                        case OB_MESH:
-                                               ob->data = me = BKE_mesh_copy(bmain, ob->data);
-                                               if (me->key)
-                                                       BKE_animdata_copy_id_action((ID *)me->key);
+                                               /* Needed to remap texcomesh below. */
+                                               me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
+                                               if (me->key)  /* We do not need to set me->key->id.newid here... */
+                                                       BKE_animdata_copy_id_action((ID *)me->key, false);
                                                break;
                                        case OB_MBALL:
-                                               ob->data = BKE_mball_copy(bmain, ob->data);
+                                               ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
                                                break;
                                        case OB_CURVE:
                                        case OB_SURF:
                                        case OB_FONT:
-                                               ob->data = cu = BKE_curve_copy(bmain, ob->data);
-                                               ID_NEW(cu->bevobj);
-                                               ID_NEW(cu->taperobj);
-                                               if (cu->key)
-                                                       BKE_animdata_copy_id_action((ID *)cu->key);
+                                               ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
+                                               ID_NEW_REMAP(cu->bevobj);
+                                               ID_NEW_REMAP(cu->taperobj);
+                                               if (cu->key)  /* We do not need to set cu->key->id.newid here... */
+                                                       BKE_animdata_copy_id_action((ID *)cu->key, false);
                                                break;
                                        case OB_LATTICE:
-                                               ob->data = lat = BKE_lattice_copy(bmain, ob->data);
-                                               if (lat->key)
-                                                       BKE_animdata_copy_id_action((ID *)lat->key);
+                                               ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
+                                               if (lat->key)  /* We do not need to set lat->key->id.newid here... */
+                                                       BKE_animdata_copy_id_action((ID *)lat->key, false);
                                                break;
                                        case OB_ARMATURE:
                                                DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-                                               ob->data = BKE_armature_copy(bmain, ob->data);
+                                               ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
                                                BKE_pose_rebuild(ob, ob->data);
                                                break;
                                        case OB_SPEAKER:
-                                               ob->data = BKE_speaker_copy(bmain, ob->data);
+                                               ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
                                                break;
                                        default:
                                                if (G.debug & G_DEBUG)
@@ -1934,17 +1924,16 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
                                 * AnimData structure, which is not what we want.
                                 *                                             (sergey)
                                 */
-                               BKE_animdata_copy_id_action((ID *)ob->data);
+                               BKE_animdata_copy_id_action((ID *)ob->data, false);
 
                                id_us_min(id);
-                               id->newid = ob->data;
                        }
                }
        }
 
        me = bmain->mesh.first;
        while (me) {
-               ID_NEW(me->texcomesh);
+               ID_NEW_REMAP(me->texcomesh);
                me = me->id.next;
        }
 }
@@ -1958,7 +1947,7 @@ static void single_object_action_users(Scene *scene, const int flag)
                ob = base->object;
                if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
                        DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-                       BKE_animdata_copy_id_action(&ob->id);
+                       BKE_animdata_copy_id_action(&ob->id, false);
                }
        }
 }
@@ -1977,11 +1966,11 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
                        for (a = 1; a <= ob->totcol; a++) {
                                ma = give_current_material(ob, a);
                                if (ma) {
-                                       /* do not test for LIB_TAG_NEW: this functions guaranteed delivers single_users! */
+                                       /* do not test for LIB_TAG_NEW or use newid: this functions guaranteed delivers single_users! */
 
                                        if (ma->id.us > 1) {
                                                man = BKE_material_copy(bmain, ma);
-                                               BKE_animdata_copy_id_action(&man->id);
+                                               BKE_animdata_copy_id_action(&man->id, false);
 
                                                man->id.us = 0;
                                                assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -1992,7 +1981,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
                                                                        if (tex->id.us > 1) {
                                                                                id_us_min(&tex->id);
                                                                                tex = BKE_texture_copy(bmain, tex);
-                                                                               BKE_animdata_copy_id_action(&tex->id);
+                                                                               BKE_animdata_copy_id_action(&tex->id, false);
                                                                                man->mtex[b]->tex = tex;
                                                                        }
                                                                }
@@ -2018,8 +2007,8 @@ static void do_single_tex_user(Main *bmain, Tex **from)
                id_us_min(&tex->id);
        }
        else if (tex->id.us > 1) {
-               texn = BKE_texture_copy(bmain, tex);
-               BKE_animdata_copy_id_action(&texn->id);
+               texn = ID_NEW_SET(tex, BKE_texture_copy(bmain, tex));
+               BKE_animdata_copy_id_action(&texn->id, false);
                tex->id.newid = (ID *)texn;
                id_us_min(&tex->id);
                *from = texn;
@@ -2096,7 +2085,7 @@ static void single_mat_users_expand(Main *bmain)
                if (ma->id.tag & LIB_TAG_NEW)
                        for (a = 0; a < MAX_MTEX; a++)
                                if (ma->mtex[a])
-                                       ID_NEW(ma->mtex[a]->object);
+                                       ID_NEW_REMAP(ma->mtex[a]->object);
 }
 
 /* used for copying scenes */
@@ -2247,7 +2236,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
        }
 
        tag_localizable_objects(C, mode);
-       BKE_main_id_clear_newpoins(bmain);
 
        CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
        {
@@ -2264,7 +2252,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
        CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
        {
                if (ob->id.lib == NULL) {
-                       ID_NEW(ob->parent);
+                       ID_NEW_REMAP(ob->parent);
                }
        }
        CTX_DATA_END;
@@ -2335,6 +2323,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
                CTX_DATA_END;
        }
 
+       BKE_main_id_clear_newpoins(bmain);
        WM_event_add_notifier(C, NC_WINDOW, NULL);
 
        return OPERATOR_FINISHED;
@@ -2381,8 +2370,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
        const bool copy_groups = false;
        bool update_deps = false;
 
-       BKE_main_id_clear_newpoins(bmain);
-
        if (RNA_boolean_get(op->ptr, "object")) {
                single_object_users(bmain, scene, v3d, flag, copy_groups);
 
@@ -2406,11 +2393,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
                single_object_action_users(scene, flag);
        }
 
-       /* TODO(sergey): This should not be needed, however some tool still could rely
-        *               on the fact, that id->newid is kept NULL by default.
-        *               Need to make sure all the guys are learing newid before they're
-        *               using it, not after.
-        */
        BKE_main_id_clear_newpoins(bmain);
 
        WM_event_add_notifier(C, NC_WINDOW, NULL);
index 13200e92e7e37929a79cdfc5c0a0ce2120f8bce6..7739d241bd35d664ac264f921b576f9ba62cb799 100644 (file)
@@ -442,6 +442,9 @@ static void id_local_cb(
                if (id_make_local(bmain, tselem->id, false, false) == false) {
                        id_clear_lib_data(bmain, tselem->id);
                }
+               else {
+                       BKE_main_id_clear_newpoins(bmain);
+               }
        }
 }
 
index 20f7ca4db168dcf76e1f562e0ecb35aa9e0b4699..ec46c5df9a0c7d114611ef9b155dad8220f4a542 100644 (file)
@@ -1645,11 +1645,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
        outliner_free_tree(&soops->tree);
        outliner_storage_cleanup(soops);
        
-       /* clear ob id.new flags */
-       for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) {
-               ob->id.newid = NULL;
-       }
-       
        /* options */
        if (soops->outlinevis == SO_LIBRARIES) {
                Library *lib;
@@ -1835,6 +1830,8 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
                outliner_sort(&soops->tree);
        }
        outliner_filter_tree(soops, &soops->tree);
+
+       BKE_main_id_clear_newpoins(mainvar);
 }
 
 
index feeb2d5e4d7a94ba637e841c6b5d91889af0321e..59fd0c7832cd0c06d20ee15f2ed80818f456fa01 100644 (file)
@@ -290,9 +290,9 @@ typedef enum ID_Type {
 #endif
 #define GS(a)  (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (*((const short *)(a))))
 
-#define ID_NEW(a)              if (      (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
-#define ID_NEW_US(a)   if (      (a)->id.newid)       { (a) = (void *)(a)->id.newid;       (a)->id.us++; }
-#define ID_NEW_US2(a)  if (((ID *)a)->newid)          { (a) = ((ID  *)a)->newid;     ((ID *)a)->us++;    }
+#define ID_NEW_SET(_id, _idn) \
+       (((ID *)(_id))->newid = (ID *)(_idn), ((ID *)(_id))->newid->tag |= LIB_TAG_NEW, (void *)((ID *)(_id))->newid)
+#define ID_NEW_REMAP(a) if ((a) && (a)->id.newid) (a) = (void *)(a)->id.newid
 
 /* id->flag (persitent). */
 enum {
index 87fb45a4419f71bdb55d90c7a10a8aeb9454b1f0..896d4979089d8cc987294769d71a248fd7ff2b6b 100644 (file)
@@ -358,7 +358,9 @@ static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, int clear_prox
                id_make_local(bmain, self, false, false);
        }
 
-       return self->newid ? self->newid : self;
+       ID *ret_id = self->newid ? self->newid : self;
+       BKE_id_clear_newpoin(self);
+       return ret_id;
 }