Fix #34806: rigid body world settings were not copied with a full scene copy.

Now copying a scene will also duplicate groups that consist entirely of objects
that are duplicated with the scene. The rigid body world will then also pointers
to these new groups.
This commit is contained in:
Brecht Van Lommel 2013-04-24 23:09:25 +00:00
parent 11c6abe53b
commit 2043d801e8
9 changed files with 99 additions and 21 deletions

View File

@ -62,6 +62,10 @@ struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene);
struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type);
struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
/* copy */
struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw);
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, short rebuild);
void BKE_rigidbody_validate_sim_object(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild);

View File

@ -84,6 +84,7 @@ void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
struct Scene *BKE_scene_copy(struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_unlink(struct Main *bmain, struct Scene *sce, struct Scene *newsce);
struct Object *BKE_scene_camera_find(struct Scene *sc);

View File

@ -148,7 +148,7 @@ Group *BKE_group_copy(Group *group)
{
Group *groupn;
groupn = MEM_dupallocN(group);
groupn = BKE_libblock_copy(&group->id);
BLI_duplicatelist(&groupn->gobject, &group->gobject);
return groupn;

View File

@ -58,12 +58,13 @@
#include "BKE_animsys.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_object.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "RNA_access.h"
@ -724,6 +725,36 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
return rbw;
}
RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw)
{
RigidBodyWorld *rbwn = MEM_dupallocN(rbw);
if (rbw->effector_weights)
rbwn->effector_weights = MEM_dupallocN(rbw->effector_weights);
if (rbwn->group)
id_us_plus(&rbwn->group->id);
if (rbwn->constraints)
id_us_plus(&rbwn->constraints->id);
rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, FALSE);
rbwn->objects = NULL;
rbwn->physics_world = NULL;
rbwn->numbodies = 0;
return rbwn;
}
void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
{
if (rbw->group && rbw->group->id.newid)
rbw->group = (Group*)rbw->group->id.newid;
if (rbw->constraints && rbw->constraints->id.newid)
rbw->constraints = (Group*)rbw->constraints->id.newid;
if (rbw->effector_weights->group && rbw->effector_weights->group->id.newid)
rbw->effector_weights->group = (Group*)rbw->effector_weights->group->id.newid;
}
/* Add rigid body settings to the specified object */
RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
{
@ -1332,6 +1363,8 @@ void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short re
void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) {}
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) {}
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; }
struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; }

View File

@ -176,7 +176,9 @@ Scene *BKE_scene_copy(Scene *sce, int type)
scen->obedit = NULL;
scen->stats = NULL;
scen->fps_info = NULL;
scen->rigidbody_world = NULL; /* RB_TODO figure out a way of copying the rigid body world */
if(sce->rigidbody_world)
scen->rigidbody_world = BKE_rigidbody_world_copy(sce->rigidbody_world);
BLI_duplicatelist(&(scen->markers), &(sce->markers));
BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
@ -295,6 +297,12 @@ Scene *BKE_scene_copy(Scene *sce, int type)
return scen;
}
void BKE_scene_groups_relink(Scene *sce)
{
if (sce->rigidbody_world)
BKE_rigidbody_world_groups_relink(sce->rigidbody_world);
}
/* do not free scene itself */
void BKE_scene_free(Scene *sce)
{

View File

@ -146,8 +146,8 @@ int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, f
struct Object *ED_object_add_type(struct bContext *C, int type, const float loc[3], const float rot[3],
int enter_editmode, unsigned int layer);
void ED_object_single_users(struct Main *bmain, struct Scene *scene, int full);
void ED_object_single_user(struct Scene *scene, struct Object *ob);
void ED_object_single_users(struct Main *bmain, struct Scene *scene, bool full, bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* object motion paths */
void ED_objects_clear_paths(struct bContext *C);

View File

@ -304,8 +304,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
/* make copy */
if (do_scene_obj) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ED_object_single_user(scene, (struct Object *)id);
ED_object_single_user(bmain, scene, (struct Object *)id);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else {

View File

@ -44,6 +44,7 @@
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_speaker_types.h"
#include "DNA_world_types.h"
@ -1601,22 +1602,24 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
static void single_object_users(Scene *scene, View3D *v3d, int flag)
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, int flag, bool copy_groups)
{
Base *base;
Object *ob, *obn;
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 [#26002] */
for (ob = bmain->object.first; ob; ob = ob->id.next)
ob->id.newid = NULL;
/* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
/* newid may still have some trash from Outliner tree building,
* so clear that first to avoid errors [#26002]
*/
ob->id.newid = NULL;
if ((base->flag & flag) == flag) {
if (ob->id.lib == NULL && ob->id.us > 1) {
/* base gets copy of object */
@ -1626,11 +1629,37 @@ static void single_object_users(Scene *scene, View3D *v3d, int flag)
}
}
}
/* 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;
for (go = group->gobject.first; go; go = go->next) {
if (!(go->ob && (go->ob->id.newid))) {
all_duplicated = false;
break;
}
}
if (all_duplicated) {
groupn = BKE_group_copy(group);
for (go = groupn->gobject.first; go; go = go->next)
go->ob = (Object*)go->ob->id.newid;
}
}
}
/* group pointers in scene */
BKE_scene_groups_relink(scene);
ID_NEW(scene->camera);
if (v3d) ID_NEW(v3d->camera);
/* object pointers */
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
BKE_object_relink(base->object);
}
@ -1640,16 +1669,17 @@ static void single_object_users(Scene *scene, View3D *v3d, int flag)
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Scene *scene, Object *ob)
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
Base *base;
bool copy_groups = false;
for (base = FIRSTBASE; base; base = base->next) {
if (base->object == ob) base->flag |= OB_DONE;
else base->flag &= ~OB_DONE;
}
single_object_users(scene, NULL, OB_DONE);
single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
}
static void new_id_matar(Material **matar, int totcol)
@ -1907,9 +1937,9 @@ static void single_mat_users_expand(Main *bmain)
}
/* used for copying scenes */
void ED_object_single_users(Main *bmain, Scene *scene, int full)
void ED_object_single_users(Main *bmain, Scene *scene, bool full, bool copy_groups)
{
single_object_users(scene, NULL, 0);
single_object_users(bmain, scene, NULL, 0, copy_groups);
if (full) {
single_obdata_users(bmain, scene, 0);
@ -2078,9 +2108,10 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
int flag = RNA_enum_get(op->ptr, "type"); /* 0==ALL, SELECTED==selected objecs */
bool copy_groups = false;
if (RNA_boolean_get(op->ptr, "object"))
single_object_users(scene, v3d, flag);
single_object_users(bmain, scene, v3d, flag, copy_groups);
if (RNA_boolean_get(op->ptr, "obdata"))
single_obdata_users(bmain, scene, flag);

View File

@ -3537,10 +3537,10 @@ static int scene_new_exec(bContext *C, wmOperator *op)
/* these can't be handled in blenkernel curently, so do them here */
if (type == SCE_COPY_LINK_DATA) {
ED_object_single_users(bmain, newscene, 0);
ED_object_single_users(bmain, newscene, false, true);
}
else if (type == SCE_COPY_FULL) {
ED_object_single_users(bmain, newscene, 1);
ED_object_single_users(bmain, newscene, true, true);
}
}