Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_animsys.h2
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c8
-rw-r--r--source/blender/blenkernel/intern/brush.c3
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c6
-rw-r--r--source/blender/blenkernel/intern/image.c1
-rw-r--r--source/blender/blenkernel/intern/library.c33
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c4
-rw-r--r--source/blender/blenkernel/intern/sca.c22
-rw-r--r--source/blender/blenkernel/intern/scene.c8
-rw-r--r--source/blender/blenkernel/intern/sequencer.c3
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/object/object_add.c107
-rw-r--r--source/blender/editors/object/object_relations.c98
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c7
-rw-r--r--source/blender/makesdna/DNA_ID.h6
-rw-r--r--source/blender/makesrna/intern/rna_ID.c4
20 files changed, 180 insertions, 145 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 00ea323f934..a67e903877a 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -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 {
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 855eb10976c..77ea7ecbefb 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index a5abc6beff8..21279392392 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -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);
}
}
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 8ef1fae1155..0d509ecea06 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 50f8423bbff..7361645ba2c 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -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)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c9bad2160ff..a2d94ccc478 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -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));
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 3411eae22e1..31c10c843da 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 4489ca907f6..c6666ec5ced 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index ebf9f017731..628222ed306 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -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);
}
/* ************************************** */
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index c7f406089d9..fa221348932 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 6e1f11cb526..a699427315e 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 65d751a8a72..1d2f5aee440 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -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)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 98c8a260993..af73410728b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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) {
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index bdad667f206..4db1c845c23 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -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);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 6647102acad..02dd3ed2df5 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -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);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index f448e925dd9..d670f4b8425 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -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);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 13200e92e7e..7739d241bd3 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -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);
+ }
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 20f7ca4db16..ec46c5df9a0 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -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);
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index feeb2d5e4d7..59fd0c7832c 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -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 {
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 87fb45a4419..896d4979089 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -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;
}