Fix T90246: Full Copy'ing a scene confuses physics in the original scene.
Handling of RigidBody data in duplicate of scenes/collections was very wrong. This commit: - Add handling of duplication of RB collections when fully duplicating a scene. - Fix Object duplication trying to add duplicated RB objects to matching RBW collections. While the later behavior is desired when only duplicated objects, when duplicating their collections and/or scenes it is actually very bad, as it would add back new object duplicates to old (RBW) collections.
This commit is contained in:
parent
779ea49af7
commit
1a72744ddc
Notes:
blender-bot
2023-02-14 10:11:54 +01:00
Referenced by issue #90246, Full Copy'ing a scene confuses physics in the original scene
|
@ -133,6 +133,9 @@ enum {
|
|||
LIB_ID_COPY_SHAPEKEY = 1 << 26,
|
||||
/** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */
|
||||
LIB_ID_COPY_NODETREE_LOCALIZE = 1 << 27,
|
||||
/** EXCEPTION! Specific handling of RB objects regarding collections differs depending whether we
|
||||
duplicate scene/collections, or objects. */
|
||||
LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING = 1 << 28,
|
||||
|
||||
/* *** Helper 'defines' gathering most common flag sets. *** */
|
||||
/** Shapekeys are not real ID's, more like local data to geometry IDs... */
|
||||
|
@ -261,7 +264,8 @@ struct ID *BKE_id_copy_ex(struct Main *bmain,
|
|||
const int flag);
|
||||
struct ID *BKE_id_copy_for_duplicate(struct Main *bmain,
|
||||
struct ID *id,
|
||||
const uint duplicate_flags);
|
||||
const uint duplicate_flags,
|
||||
const int copy_flags);
|
||||
|
||||
void BKE_lib_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
|
||||
void BKE_lib_id_swap_full(struct Main *bmain, struct ID *id_a, struct ID *id_b);
|
||||
|
|
|
@ -597,7 +597,7 @@ static Collection *collection_duplicate_recursive(Main *bmain,
|
|||
}
|
||||
else if (collection_old->id.newid == NULL) {
|
||||
collection_new = (Collection *)BKE_id_copy_for_duplicate(
|
||||
bmain, (ID *)collection_old, duplicate_flags);
|
||||
bmain, (ID *)collection_old, duplicate_flags, LIB_ID_COPY_DEFAULT);
|
||||
|
||||
if (collection_new == collection_old) {
|
||||
return collection_new;
|
||||
|
|
|
@ -674,7 +674,10 @@ ID *BKE_id_copy(Main *bmain, const ID *id)
|
|||
* Invokes the appropriate copy method for the block and returns the result in
|
||||
* newid, unless test. Returns true if the block can be copied.
|
||||
*/
|
||||
ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags)
|
||||
ID *BKE_id_copy_for_duplicate(Main *bmain,
|
||||
ID *id,
|
||||
const eDupli_ID_Flags duplicate_flags,
|
||||
const int copy_flags)
|
||||
{
|
||||
if (id == NULL) {
|
||||
return id;
|
||||
|
@ -685,7 +688,7 @@ ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplica
|
|||
return id;
|
||||
}
|
||||
|
||||
ID *id_new = BKE_id_copy(bmain, id);
|
||||
ID *id_new = BKE_id_copy_ex(bmain, id, NULL, copy_flags);
|
||||
/* Copying add one user by default, need to get rid of that one. */
|
||||
id_us_min(id_new);
|
||||
ID_NEW_SET(id, id_new);
|
||||
|
|
|
@ -2634,10 +2634,16 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
{
|
||||
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
|
||||
const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
|
||||
int copy_flags = LIB_ID_COPY_DEFAULT;
|
||||
|
||||
if (!is_subprocess) {
|
||||
BKE_main_id_newptr_and_tag_clear(bmain);
|
||||
}
|
||||
else {
|
||||
/* In case copying object is a sub-process of collection (or scene) copying, do not try to
|
||||
* re-assign RB objects to existing RBW collections. */
|
||||
copy_flags |= LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING;
|
||||
}
|
||||
if (is_root_id) {
|
||||
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
|
||||
* all expected linked data. */
|
||||
|
@ -2649,7 +2655,7 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
|
||||
Material ***matarar;
|
||||
|
||||
Object *obn = (Object *)BKE_id_copy_for_duplicate(bmain, &ob->id, dupflag);
|
||||
Object *obn = (Object *)BKE_id_copy_for_duplicate(bmain, &ob->id, dupflag, copy_flags);
|
||||
|
||||
/* 0 == full linked. */
|
||||
if (dupflag == 0) {
|
||||
|
@ -2658,13 +2664,13 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
|
||||
if (dupflag & USER_DUP_MAT) {
|
||||
for (int i = 0; i < obn->totcol; i++) {
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag, copy_flags);
|
||||
}
|
||||
}
|
||||
if (dupflag & USER_DUP_PSYS) {
|
||||
ParticleSystem *psys;
|
||||
for (psys = obn->particlesystem.first; psys; psys = psys->next) {
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag, copy_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2675,77 +2681,77 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
switch (obn->type) {
|
||||
case OB_MESH:
|
||||
if (dupflag & USER_DUP_MESH) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
if (dupflag & USER_DUP_CURVE) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_SURF:
|
||||
if (dupflag & USER_DUP_SURF) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_FONT:
|
||||
if (dupflag & USER_DUP_FONT) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_MBALL:
|
||||
if (dupflag & USER_DUP_MBALL) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_LAMP:
|
||||
if (dupflag & USER_DUP_LAMP) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if (dupflag & USER_DUP_ARM) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if (dupflag != 0) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_CAMERA:
|
||||
if (dupflag != 0) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_LIGHTPROBE:
|
||||
if (dupflag & USER_DUP_LIGHTPROBE) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_SPEAKER:
|
||||
if (dupflag != 0) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
if (dupflag & USER_DUP_GPENCIL) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_HAIR:
|
||||
if (dupflag & USER_DUP_HAIR) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_POINTCLOUD:
|
||||
if (dupflag & USER_DUP_POINTCLOUD) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_VOLUME:
|
||||
if (dupflag & USER_DUP_VOLUME) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag);
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2756,7 +2762,7 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
matarar = BKE_object_material_array_p(obn);
|
||||
if (matarar) {
|
||||
for (int i = 0; i < obn->totcol; i++) {
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag, copy_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src
|
|||
ob_dst->rigidbody_object = rigidbody_copy_object(ob_src, flag);
|
||||
ob_dst->rigidbody_constraint = rigidbody_copy_constraint(ob_src, flag);
|
||||
|
||||
if (flag & LIB_ID_CREATE_NO_MAIN) {
|
||||
if ((flag & (LIB_ID_CREATE_NO_MAIN | LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING)) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1801,6 +1801,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
|
|||
/* Scene duplication is always root of duplication currently. */
|
||||
const bool is_subprocess = false;
|
||||
const bool is_root_id = true;
|
||||
const int copy_flags = LIB_ID_COPY_DEFAULT;
|
||||
|
||||
if (!is_subprocess) {
|
||||
BKE_main_id_newptr_and_tag_clear(bmain);
|
||||
|
@ -1816,21 +1817,40 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
|
|||
/* Copy Freestyle LineStyle datablocks. */
|
||||
LISTBASE_FOREACH (ViewLayer *, view_layer_dst, &sce_copy->view_layers) {
|
||||
LISTBASE_FOREACH (FreestyleLineSet *, lineset, &view_layer_dst->freestyle_config.linesets) {
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)lineset->linestyle, duplicate_flags);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)lineset->linestyle, duplicate_flags, copy_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* Full copy of world (included animations) */
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)sce->world, duplicate_flags);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)sce->world, duplicate_flags, copy_flags);
|
||||
|
||||
/* Full copy of GreasePencil. */
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)sce->gpd, duplicate_flags);
|
||||
BKE_id_copy_for_duplicate(bmain, (ID *)sce->gpd, duplicate_flags, copy_flags);
|
||||
|
||||
/* Deep-duplicate collections and objects (using preferences' settings for which sub-data to
|
||||
* duplicate along the object itself). */
|
||||
BKE_collection_duplicate(
|
||||
bmain, NULL, sce_copy->master_collection, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS);
|
||||
|
||||
/* Rigid body world collections may not be instantiated as scene's collections, ensure they
|
||||
* also get properly duplicated. */
|
||||
if (sce_copy->rigidbody_world != NULL) {
|
||||
if (sce_copy->rigidbody_world->group != NULL) {
|
||||
BKE_collection_duplicate(bmain,
|
||||
NULL,
|
||||
sce_copy->rigidbody_world->group,
|
||||
duplicate_flags,
|
||||
LIB_ID_DUPLICATE_IS_SUBPROCESS);
|
||||
}
|
||||
if (sce_copy->rigidbody_world->constraints != NULL) {
|
||||
BKE_collection_duplicate(bmain,
|
||||
NULL,
|
||||
sce_copy->rigidbody_world->constraints,
|
||||
duplicate_flags,
|
||||
LIB_ID_DUPLICATE_IS_SUBPROCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_subprocess) {
|
||||
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
|
||||
BKE_libblock_relink_to_newid(&sce_copy->id);
|
||||
|
|
Loading…
Reference in New Issue