diff options
-rw-r--r-- | source/blender/blenkernel/BKE_rigidbody.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_scene.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/group.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/rigidbody.c | 37 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 10 | ||||
-rw-r--r-- | source/blender/editors/include/ED_object.h | 4 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 3 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 55 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 4 |
9 files changed, 99 insertions, 21 deletions
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 75647876419..ef5b8349d60 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -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); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 9bf0991272a..1171e42cad7 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -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); diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index b1d0e8df754..ad0aed4691a 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -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; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index ca7bb542598..879ba6651c2 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -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; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 29396a7edfe..d140dfa6a2d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -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) { diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 108d666c3aa..00b8fc4535d 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -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); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 7d968b30bac..3c0160ce5ba 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -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 { diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 9838c99a81b..2e96ffe8c21 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -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); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 86e26bf0681..310783e5199 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -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); } } |