code cleanup: change order of args in void BKE_object_where_is_calc_time_ex() so...
[blender.git] / source / blender / blenkernel / intern / object.c
index fa394d4a95119895aa32c3e11caf19b17d84ac8c..ef3c98ee3f4ee7b13e8f60789c7d8b3b5e382ed9 100644 (file)
 #include "DNA_view3d_types.h"
 #include "DNA_world_types.h"
 #include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_bpath.h"
 #include "BLI_math.h"
-#include "BLI_pbvh.h"
 #include "BLI_utildefines.h"
 #include "BLI_linklist.h"
 
+#include "BKE_pbvh.h"
 #include "BKE_main.h"
 #include "BKE_global.h"
 #include "BKE_idprop.h"
@@ -83,6 +84,7 @@
 #include "BKE_fcurve.h"
 #include "BKE_group.h"
 #include "BKE_icons.h"
+#include "BKE_image.h"
 #include "BKE_key.h"
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
@@ -97,6 +99,7 @@
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
 #include "BKE_property.h"
+#include "BKE_rigidbody.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
 #include "BKE_sequencer.h"
@@ -196,32 +199,41 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
        return TRUE;
 }
 
-void BKE_object_link_modifiers(struct Object *ob, struct Object *from)
+void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
 {
        ModifierData *md;
-       BKE_object_free_modifiers(ob);
+       BKE_object_free_modifiers(ob_dst);
 
-       if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+       if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
                /* only objects listed above can have modifiers and linking them to objects
                 * which doesn't have modifiers stack is quite silly */
                return;
        }
 
-       for (md = from->modifiers.first; md; md = md->next) {
+       for (md = ob_src->modifiers.first; md; md = md->next) {
                ModifierData *nmd = NULL;
 
-               if (ELEM4(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance, eModifierType_Collision)) continue;
+               if (ELEM4(md->type,
+                         eModifierType_Hook,
+                         eModifierType_Softbody,
+                         eModifierType_ParticleInstance,
+                         eModifierType_Collision))
+               {
+                       continue;
+               }
 
-               if (!BKE_object_support_modifier_type_check(ob, md->type))
+               if (!BKE_object_support_modifier_type_check(ob_dst, md->type))
                        continue;
 
                nmd = modifier_new(md->type);
+               BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
                modifier_copyData(md, nmd);
-               BLI_addtail(&ob->modifiers, nmd);
+               BLI_addtail(&ob_dst->modifiers, nmd);
+               modifier_unique_name(&ob_dst->modifiers, nmd);
        }
 
-       BKE_object_copy_particlesystems(ob, from);
-       BKE_object_copy_softbody(ob, from);
+       BKE_object_copy_particlesystems(ob_dst, ob_src);
+       BKE_object_copy_softbody(ob_dst, ob_src);
 
        /* TODO: smoke?, cloth? */
 }
@@ -255,20 +267,53 @@ void free_sculptsession_deformMats(SculptSession *ss)
        ss->deform_imats = NULL;
 }
 
+/* Write out the sculpt dynamic-topology BMesh to the Mesh */
+void sculptsession_bm_to_me(struct Object *ob, int reorder)
+{
+       if (ob && ob->sculpt) {
+               SculptSession *ss = ob->sculpt;
+
+               if (ss->bm) {
+                       if (ob->data) {
+                               BMIter iter;
+                               BMFace *efa;
+                               BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
+                                       BM_elem_flag_set(efa, BM_ELEM_SMOOTH,
+                                                        ss->bm_smooth_shading);
+                               }
+                               if (reorder)
+                                       BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
+                               BM_mesh_bm_to_me(ss->bm, ob->data, FALSE);
+                       }
+               }
+       }
+}
+
 void free_sculptsession(Object *ob)
 {
        if (ob && ob->sculpt) {
                SculptSession *ss = ob->sculpt;
                DerivedMesh *dm = ob->derivedFinal;
 
+               if (ss->bm) {
+                       sculptsession_bm_to_me(ob, TRUE);
+                       BM_mesh_free(ss->bm);
+               }
+
                if (ss->pbvh)
-                       BLI_pbvh_free(ss->pbvh);
+                       BKE_pbvh_free(ss->pbvh);
+               if (ss->bm_log)
+                       BM_log_free(ss->bm_log);
+
                if (dm && dm->getPBVH)
                        dm->getPBVH(NULL, dm);  /* signal to clear */
 
                if (ss->texcache)
                        MEM_freeN(ss->texcache);
 
+               if (ss->tex_pool)
+                       BKE_image_pool_free(ss->tex_pool);
+
                if (ss->layer_co)
                        MEM_freeN(ss->layer_co);
 
@@ -293,22 +338,32 @@ void BKE_object_free(Object *ob)
        
        BKE_object_free_display(ob);
        
-       /* disconnect specific data */
+       /* disconnect specific data, but not for lib data (might be indirect data, can get relinked) */
        if (ob->data) {
                ID *id = ob->data;
                id->us--;
-               if (id->us == 0) {
-                       if (ob->type == OB_MESH) BKE_mesh_unlink(ob->data);
-                       else if (ob->type == OB_CURVE) BKE_curve_unlink(ob->data);
-                       else if (ob->type == OB_MBALL) BKE_mball_unlink(ob->data);
+               if (id->us == 0 && id->lib == NULL) {
+                       switch (ob->type) {
+                               case OB_MESH:
+                                       BKE_mesh_unlink((Mesh *)id);
+                                       break;
+                               case OB_CURVE:
+                                       BKE_curve_unlink((Curve *)id);
+                                       break;
+                               case OB_MBALL:
+                                       BKE_mball_unlink((MetaBall *)id);
+                                       break;
+                       }
                }
                ob->data = NULL;
        }
-       
-       for (a = 0; a < ob->totcol; a++) {
-               if (ob->mat[a]) ob->mat[a]->id.us--;
+
+       if (ob->mat) {
+               for (a = 0; a < ob->totcol; a++) {
+                       if (ob->mat[a]) ob->mat[a]->id.us--;
+               }
+               MEM_freeN(ob->mat);
        }
-       if (ob->mat) MEM_freeN(ob->mat);
        if (ob->matbits) MEM_freeN(ob->matbits);
        ob->mat = NULL;
        ob->matbits = NULL;
@@ -323,16 +378,18 @@ void BKE_object_free(Object *ob)
                BKE_pose_free(ob->pose);
        if (ob->mpath)
                animviz_free_motionpath(ob->mpath);
-       free_properties(&ob->prop);
+       BKE_bproperty_free_list(&ob->prop);
        BKE_object_free_modifiers(ob);
        
        free_sensors(&ob->sensors);
        free_controllers(&ob->controllers);
        free_actuators(&ob->actuators);
        
-       free_constraints(&ob->constraints);
+       BKE_free_constraints(&ob->constraints);
        
        free_partdeflect(ob->pd);
+       BKE_rigidbody_free_object(ob);
+       BKE_rigidbody_free_constraint(ob);
 
        if (ob->soft) sbFree(ob->soft);
        if (ob->bsoft) bsbFree(ob->bsoft);
@@ -415,7 +472,7 @@ void BKE_object_unlink(Object *ob)
                        bPoseChannel *pchan;
                        for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) {
                                for (con = pchan->constraints.first; con; con = con->next) {
-                                       bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+                                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
                                        ListBase targets = {NULL, NULL};
                                        bConstraintTarget *ct;
                                        
@@ -437,7 +494,7 @@ void BKE_object_unlink(Object *ob)
                                if (pchan->custom == ob)
                                        pchan->custom = NULL;
                        }
-               } 
+               }
                else if (ELEM(OB_MBALL, ob->type, obt->type)) {
                        if (BKE_mball_is_basis_for(obt, ob))
                                obt->recalc |= OB_RECALC_DATA;
@@ -446,7 +503,7 @@ void BKE_object_unlink(Object *ob)
                sca_remove_ob_poin(obt, ob);
                
                for (con = obt->constraints.first; con; con = con->next) {
-                       bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
                        ListBase targets = {NULL, NULL};
                        bConstraintTarget *ct;
                        
@@ -672,8 +729,8 @@ void BKE_object_unlink(Object *ob)
 
                                        if (so->treestore) {
                                                TreeStoreElem *tselem = so->treestore->data;
-                                               int a;
-                                               for (a = 0; a < so->treestore->usedelem; a++, tselem++) {
+                                               int i;
+                                               for (i = 0; i < so->treestore->usedelem; i++, tselem++) {
                                                        if (tselem->id == (ID *)ob) tselem->id = NULL;
                                                }
                                        }
@@ -710,6 +767,50 @@ void BKE_object_unlink(Object *ob)
        }
 }
 
+/* actual check for internal data, not context or flags */
+int BKE_object_is_in_editmode(Object *ob)
+{
+       if (ob->data == NULL)
+               return 0;
+       
+       if (ob->type == OB_MESH) {
+               Mesh *me = ob->data;
+               if (me->edit_btmesh)
+                       return 1;
+       }
+       else if (ob->type == OB_ARMATURE) {
+               bArmature *arm = ob->data;
+               
+               if (arm->edbo)
+                       return 1;
+       }
+       else if (ob->type == OB_FONT) {
+               Curve *cu = ob->data;
+               
+               if (cu->editfont)
+                       return 1;
+       }
+       else if (ob->type == OB_MBALL) {
+               MetaBall *mb = ob->data;
+               
+               if (mb->editelems)
+                       return 1;
+       }
+       else if (ob->type == OB_LATTICE) {
+               Lattice *lt = ob->data;
+               
+               if (lt->editlatt)
+                       return 1;
+       }
+       else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
+               Curve *cu = ob->data;
+
+               if (cu->editnurb)
+                       return 1;
+       }
+       return 0;
+}
+
 int BKE_object_exists_check(Object *obtest)
 {
        Object *ob;
@@ -729,16 +830,16 @@ int BKE_object_exists_check(Object *obtest)
 void *BKE_object_obdata_add_from_type(int type)
 {
        switch (type) {
-               case OB_MESH:      return BKE_mesh_add("Mesh");
-               case OB_CURVE:     return BKE_curve_add("Curve", OB_CURVE);
-               case OB_SURF:      return BKE_curve_add("Surf", OB_SURF);
-               case OB_FONT:      return BKE_curve_add("Text", OB_FONT);
-               case OB_MBALL:     return BKE_mball_add("Meta");
-               case OB_CAMERA:    return BKE_camera_add("Camera");
-               case OB_LAMP:      return BKE_lamp_add("Lamp");
-               case OB_LATTICE:   return BKE_lattice_add("Lattice");
-               case OB_ARMATURE:  return BKE_armature_add("Armature");
-               case OB_SPEAKER:   return BKE_speaker_add("Speaker");
+               case OB_MESH:      return BKE_mesh_add(G.main, "Mesh");
+               case OB_CURVE:     return BKE_curve_add(G.main, "Curve", OB_CURVE);
+               case OB_SURF:      return BKE_curve_add(G.main, "Surf", OB_SURF);
+               case OB_FONT:      return BKE_curve_add(G.main, "Text", OB_FONT);
+               case OB_MBALL:     return BKE_mball_add(G.main, "Meta");
+               case OB_CAMERA:    return BKE_camera_add(G.main, "Camera");
+               case OB_LAMP:      return BKE_lamp_add(G.main, "Lamp");
+               case OB_LATTICE:   return BKE_lattice_add(G.main, "Lattice");
+               case OB_ARMATURE:  return BKE_armature_add(G.main, "Armature");
+               case OB_SPEAKER:   return BKE_speaker_add(G.main, "Speaker");
                case OB_EMPTY:     return NULL;
                default:
                        printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type);
@@ -767,14 +868,14 @@ static const char *get_obdata_defname(int type)
 }
 
 /* more general add: creates minimum required data, but without vertices etc. */
-Object *BKE_object_add_only_object(int type, const char *name)
+Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
 {
        Object *ob;
 
        if (!name)
                name = get_obdata_defname(type);
 
-       ob = BKE_libblock_alloc(&G.main->object, ID_OB, name);
+       ob = BKE_libblock_alloc(&bmain->object, ID_OB, name);
 
        /* default object vars */
        ob->type = type;
@@ -837,7 +938,9 @@ Object *BKE_object_add_only_object(int type, const char *name)
        ob->step_height = 0.15f;
        ob->jump_speed = 10.0f;
        ob->fall_speed = 55.0f;
-       
+       ob->col_group = 0x01;
+       ob->col_mask = 0xff;
+
        /* NT fluid sim defaults */
        ob->fluidsimSettings = NULL;
 
@@ -858,7 +961,7 @@ Object *BKE_object_add(struct Scene *scene, int type)
        char name[MAX_ID_NAME];
 
        BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
-       ob = BKE_object_add_only_object(type, name);
+       ob = BKE_object_add_only_object(G.main, type, name);
 
        ob->data = BKE_object_obdata_add_from_type(type);
 
@@ -872,23 +975,44 @@ Object *BKE_object_add(struct Scene *scene, int type)
        return ob;
 }
 
-SoftBody *copy_softbody(SoftBody *sb)
+SoftBody *copy_softbody(SoftBody *sb, int copy_caches)
 {
        SoftBody *sbn;
        
        if (sb == NULL) return(NULL);
        
        sbn = MEM_dupallocN(sb);
-       sbn->totspring = sbn->totpoint = 0;
-       sbn->bpoint = NULL;
-       sbn->bspring = NULL;
+
+       if (copy_caches == FALSE) {
+               sbn->totspring = sbn->totpoint = 0;
+               sbn->bpoint = NULL;
+               sbn->bspring = NULL;
+       }
+       else {
+               sbn->totspring = sb->totspring;
+               sbn->totpoint = sb->totpoint;
+
+               if (sbn->bpoint) {
+                       int i;
+
+                       sbn->bpoint = MEM_dupallocN(sbn->bpoint);
+
+                       for (i = 0; i < sbn->totpoint; i++) {
+                               if (sbn->bpoint[i].springs)
+                                       sbn->bpoint[i].springs = MEM_dupallocN(sbn->bpoint[i].springs);
+                       }
+               }
+
+               if (sb->bspring)
+                       sbn->bspring = MEM_dupallocN(sb->bspring);
+       }
        
        sbn->keys = NULL;
        sbn->totkey = sbn->totpointkey = 0;
        
        sbn->scratch = NULL;
 
-       sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches);
+       sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches);
 
        if (sb->effector_weights)
                sbn->effector_weights = MEM_dupallocN(sb->effector_weights);
@@ -961,7 +1085,7 @@ static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
        psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
        psysn->renderdata = NULL;
        
-       psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches);
+       psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, FALSE);
 
        /* XXX - from reading existing code this seems correct but intended usage of
         * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
@@ -1022,7 +1146,7 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob)
 void BKE_object_copy_softbody(Object *obn, Object *ob)
 {
        if (ob->soft)
-               obn->soft = copy_softbody(ob->soft);
+               obn->soft = copy_softbody(ob->soft, FALSE);
 }
 
 static void copy_object_pose(Object *obn, Object *ob)
@@ -1043,7 +1167,7 @@ static void copy_object_pose(Object *obn, Object *ob)
                }
                
                for (con = chan->constraints.first; con; con = con->next) {
-                       bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
                        ListBase targets = {NULL, NULL};
                        bConstraintTarget *ct;
                        
@@ -1062,12 +1186,12 @@ static void copy_object_pose(Object *obn, Object *ob)
        }
 }
 
-static int object_pose_context(Object *ob)
+int BKE_object_pose_context_check(Object *ob)
 {
-       if ( (ob) &&
-            (ob->type == OB_ARMATURE) &&
-            (ob->pose) &&
-            (ob->mode & OB_MODE_POSE))
+       if ((ob) &&
+           (ob->type == OB_ARMATURE) &&
+           (ob->pose) &&
+           (ob->mode & OB_MODE_POSE))
        {
                return 1;
        }
@@ -1081,12 +1205,12 @@ Object *BKE_object_pose_armature_get(Object *ob)
        if (ob == NULL)
                return NULL;
 
-       if (object_pose_context(ob))
+       if (BKE_object_pose_context_check(ob))
                return ob;
 
        ob = modifiers_isDeformedByArmature(ob);
 
-       if (object_pose_context(ob))
+       if (BKE_object_pose_context_check(ob))
                return ob;
 
        return NULL;
@@ -1103,13 +1227,13 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
        copy_v3_v3(ob_tar->size, ob_src->size);
 }
 
-Object *BKE_object_copy(Object *ob)
+Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
 {
        Object *obn;
        ModifierData *md;
        int a;
 
-       obn = BKE_libblock_copy(&ob->id);
+       obn = BKE_libblock_copy_ex(bmain, &ob->id);
        
        if (ob->totcol) {
                obn->mat = MEM_dupallocN(ob->mat);
@@ -1130,7 +1254,7 @@ Object *BKE_object_copy(Object *ob)
        }
 
        obn->prop.first = obn->prop.last = NULL;
-       copy_properties(&obn->prop, &ob->prop);
+       BKE_bproperty_copy_list(&obn->prop, &ob->prop);
        
        copy_sensors(&obn->sensors, &ob->sensors);
        copy_controllers(&obn->controllers, &ob->controllers);
@@ -1143,7 +1267,7 @@ Object *BKE_object_copy(Object *ob)
                        BKE_pose_rebuild(obn, obn->data);
        }
        defgroup_copy_list(&obn->defbase, &ob->defbase);
-       copy_constraints(&obn->constraints, &ob->constraints, TRUE);
+       BKE_copy_constraints(&obn->constraints, &ob->constraints, TRUE);
 
        obn->mode = 0;
        obn->sculpt = NULL;
@@ -1164,8 +1288,10 @@ Object *BKE_object_copy(Object *ob)
                if (obn->pd->rng)
                        obn->pd->rng = MEM_dupallocN(ob->pd->rng);
        }
-       obn->soft = copy_softbody(ob->soft);
+       obn->soft = copy_softbody(ob->soft, copy_caches);
        obn->bsoft = copy_bulletsoftbody(ob->bsoft);
+       obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
+       obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob);
 
        BKE_object_copy_particlesystems(obn, ob);
        
@@ -1180,6 +1306,12 @@ Object *BKE_object_copy(Object *ob)
        return obn;
 }
 
+/* copy objects, will re-initialize cached simulation data */
+Object *BKE_object_copy(Object *ob)
+{
+       return BKE_object_copy_ex(G.main, ob, FALSE);
+}
+
 static void extern_local_object(Object *ob)
 {
        ParticleSystem *psys;
@@ -1318,7 +1450,8 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
                                                if ((Object *)dtar->id == target)
                                                        dtar->id = (ID *)ob;
                                                else {
-                                                       /* only on local objects because this causes indirect links a -> b -> c, blend to point directly to a.blend
+                                                       /* only on local objects because this causes indirect links
+                                                        * 'a -> b -> c', blend to point directly to a.blend
                                                         * when a.blend has a proxy thats linked into c.blend  */
                                                        if (ob->id.lib == NULL)
                                                                id_lib_extern((ID *)dtar->id);
@@ -1433,14 +1566,14 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
 
 /* *************** CALC ****************** */
 
-void BKE_object_scale_to_mat3(Object *ob, float mat[][3])
+void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
 {
        float vec[3];
        mul_v3_v3v3(vec, ob->size, ob->dscale);
        size_to_mat3(mat, vec);
 }
 
-void BKE_object_rot_to_mat3(Object *ob, float mat[][3])
+void BKE_object_rot_to_mat3(Object *ob, float mat[3][3], short use_drot)
 {
        float rmat[3][3], dmat[3][3];
        
@@ -1471,10 +1604,13 @@ void BKE_object_rot_to_mat3(Object *ob, float mat[][3])
        }
        
        /* combine these rotations */
-       mul_m3_m3m3(mat, dmat, rmat);
+       if (use_drot)
+               mul_m3_m3m3(mat, dmat, rmat);
+       else
+               copy_m3_m3(mat, rmat);
 }
 
-void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
+void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], short use_compat)
 {
        switch (ob->rotmode) {
                case ROT_MODE_QUAT:
@@ -1506,7 +1642,7 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
                        /* end drot correction */
 
                        if (use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, tmat);
-                       else mat3_to_eulO(ob->rot, ob->rotmode, tmat);
+                       else            mat3_to_eulO(ob->rot, ob->rotmode, tmat);
                }
        }
 }
@@ -1577,7 +1713,7 @@ void BKE_object_tfm_protected_restore(Object *ob,
 }
 
 /* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
-void BKE_object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent)
+void BKE_object_apply_mat4(Object *ob, float mat[4][4], const short use_compat, const short use_parent)
 {
        float rot[3][3];
 
@@ -1606,7 +1742,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[][4], const short use_compat, c
        /* BKE_object_mat3_to_rot handles delta rotations */
 }
 
-void BKE_object_to_mat3(Object *ob, float mat[][3]) /* no parent */
+void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */
 {
        float smat[3][3];
        float rmat[3][3];
@@ -1616,11 +1752,11 @@ void BKE_object_to_mat3(Object *ob, float mat[][3]) /* no parent */
        BKE_object_scale_to_mat3(ob, smat);
 
        /* rot */
-       BKE_object_rot_to_mat3(ob, rmat);
+       BKE_object_rot_to_mat3(ob, rmat, TRUE);
        mul_m3_m3m3(mat, rmat, smat);
 }
 
-void BKE_object_to_mat4(Object *ob, float mat[][4])
+void BKE_object_to_mat4(Object *ob, float mat[4][4])
 {
        float tmat[3][3];
        
@@ -1634,7 +1770,7 @@ void BKE_object_to_mat4(Object *ob, float mat[][4])
 /* extern */
 int enable_cu_speed = 1;
 
-static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
+static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
 {
        Curve *cu;
        float vec[4], dir[3], quat[4], radius, ctime;
@@ -1667,7 +1803,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
                CLAMP(ctime, 0.0f, 1.0f);
        }
        else {
-               ctime = scene->r.cfra;
+               ctime = BKE_scene_frame_get(scene);
                if (IS_EQF(cu->pathlen, 0.0f) == 0)
                        ctime /= cu->pathlen;
                
@@ -1718,7 +1854,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
        }
 }
 
-static void ob_parbone(Object *ob, Object *par, float mat[][4])
+static void ob_parbone(Object *ob, Object *par, float mat[4][4])
 {      
        bPoseChannel *pchan;
        float vec[3];
@@ -1730,27 +1866,33 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4])
        
        /* Make sure the bone is still valid */
        pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
-       if (!pchan) {
+       if (!pchan || !pchan->bone) {
                printf("Object %s with Bone parent: bone %s doesn't exist\n", ob->id.name + 2, ob->parsubstr);
                unit_m4(mat);
                return;
        }
 
        /* get bone transform */
-       copy_m4_m4(mat, pchan->pose_mat);
+       if (pchan->bone->flag & BONE_RELATIVE_PARENTING) {
+               /* the new option uses the root - expected bahaviour, but differs from old... */
+               /* XXX check on version patching? */
+               copy_m4_m4(mat, pchan->chan_mat);
+       }
+       else {
+               copy_m4_m4(mat, pchan->pose_mat);
 
-       /* but for backwards compatibility, the child has to move to the tail */
-       copy_v3_v3(vec, mat[1]);
-       mul_v3_fl(vec, pchan->bone->length);
-       add_v3_v3(mat[3], vec);
+               /* but for backwards compatibility, the child has to move to the tail */
+               copy_v3_v3(vec, mat[1]);
+               mul_v3_fl(vec, pchan->bone->length);
+               add_v3_v3(mat[3], vec);
+       }
 }
 
 static void give_parvert(Object *par, int nr, float vec[3])
 {
        BMEditMesh *em;
-       int a, count;
-       
-       vec[0] = vec[1] = vec[2] = 0.0f;
+
+       zero_v3(vec);
        
        if (par->type == OB_MESH) {
                Mesh *me = par->data;
@@ -1777,18 +1919,28 @@ static void give_parvert(Object *par, int nr, float vec[3])
                dm = (em) ? em->derivedFinal : par->derivedFinal;
                        
                if (dm) {
-                       MVert *mvert = dm->getVertArray(dm);
-                       int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
-                       int i, vindex, numVerts = dm->getNumVerts(dm);
-
-                       /* get the average of all verts with (original index == nr) */
-                       count = 0;
-                       for (i = 0; i < numVerts; i++) {
-                               vindex = (index) ? index[i] : i;
-
-                               if (vindex == nr) {
-                                       add_v3_v3(vec, mvert[i].co);
-                                       count++;
+                       int count = 0;
+                       int numVerts = dm->getNumVerts(dm);
+
+                       if (nr < numVerts) {
+                               MVert *mvert = dm->getVertArray(dm);
+                               int   *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
+                               int i;
+
+                               /* get the average of all verts with (original index == nr) */
+                               if (index) {
+                                       for (i = 0; i < numVerts; i++) {
+                                               if (index[i] == nr) {
+                                                       add_v3_v3(vec, mvert[i].co);
+                                                       count++;
+                                               }
+                                       }
+                               }
+                               else {
+                                       if (nr < numVerts) {
+                                               add_v3_v3(vec, mvert[nr].co);
+                                               count++;
+                                       }
                                }
                        }
 
@@ -1803,79 +1955,43 @@ static void give_parvert(Object *par, int nr, float vec[3])
                                dm->getVertCo(dm, 0, vec);
                        }
                }
-               else fprintf(stderr, "%s: DerivedMesh is needed to solve parenting, object position can be wrong now\n", __func__);
+               else {
+                       fprintf(stderr,
+                               "%s: DerivedMesh is needed to solve parenting, "
+                               "object position can be wrong now\n", __func__);
+               }
        }
        else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
-               Nurb *nu;
-               Curve *cu;
-               BPoint *bp;
-               BezTriple *bezt;
-               int found = 0;
-               ListBase *nurbs;
-
-               cu = par->data;
-               nurbs = BKE_curve_nurbs_get(cu);
-               nu = nurbs->first;
-
-               count = 0;
-               while (nu && !found) {
-                       if (nu->type == CU_BEZIER) {
-                               bezt = nu->bezt;
-                               a = nu->pntsu;
-                               while (a--) {
-                                       if (count == nr) {
-                                               found = 1;
-                                               copy_v3_v3(vec, bezt->vec[1]);
-                                               break;
-                                       }
-                                       count++;
-                                       bezt++;
-                               }
-                       }
-                       else {
-                               bp = nu->bp;
-                               a = nu->pntsu * nu->pntsv;
-                               while (a--) {
-                                       if (count == nr) {
-                                               found = 1;
-                                               memcpy(vec, bp->vec, sizeof(float) * 3);
-                                               break;
-                                       }
-                                       count++;
-                                       bp++;
-                               }
-                       }
-                       nu = nu->next;
-               }
+               Curve *cu       = par->data;
+               ListBase *nurb  = BKE_curve_nurbs_get(cu);
 
+               BKE_nurbList_index_get_co(nurb, nr, vec);
        }
        else if (par->type == OB_LATTICE) {
-               Lattice *latt = par->data;
-               BPoint *bp;
-               DispList *dl = BKE_displist_find(&par->disp, DL_VERTS);
-               float *co = dl ? dl->verts : NULL;
-               
+               Lattice *latt  = par->data;
+               DispList *dl   = BKE_displist_find(&par->disp, DL_VERTS);
+               float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
+               int tot;
+
                if (latt->editlatt) latt = latt->editlatt->latt;
-               
-               a = latt->pntsu * latt->pntsv * latt->pntsw;
-               count = 0;
-               bp = latt->def;
-               while (a--) {
-                       if (count == nr) {
-                               if (co)
-                                       memcpy(vec, co, 3 * sizeof(float));
-                               else
-                                       memcpy(vec, bp->vec, 3 * sizeof(float));
-                               break;
+
+               tot = latt->pntsu * latt->pntsv * latt->pntsw;
+
+               /* ensure dl is correct size */
+               BLI_assert(dl == NULL || dl->nr == tot);
+
+               if (nr < tot) {
+                       if (co) {
+                               copy_v3_v3(vec, co[nr]);
+                       }
+                       else {
+                               copy_v3_v3(vec, latt->def[nr].vec);
                        }
-                       count++;
-                       if (co) co += 3;
-                       else bp++;
                }
        }
 }
 
-static void ob_parvert3(Object *ob, Object *par, float mat[][4])
+static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
 {
        float cmat[3][3], v1[3], v2[3], v3[3], q[4];
 
@@ -1898,12 +2014,12 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4])
                else {
                        add_v3_v3v3(mat[3], v1, v2);
                        add_v3_v3(mat[3], v3);
-                       mul_v3_fl(mat[3], 0.3333333f);
+                       mul_v3_fl(mat[3], 1.0f / 3.0f);
                }
        }
 }
 
-static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul)
+static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[4][4], float slowmat[4][4], int simul)
 {
        float totmat[4][4];
        float tmat[4][4];
@@ -2001,7 +2117,9 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[
        return 1;
 }
 
-void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+/* note, scene is the active scene while actual_scene is the scene the object resides in */
+void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
+                                      RigidBodyWorld *rbw)
 {
        if (ob == NULL) return;
        
@@ -2026,14 +2144,17 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
        else {
                BKE_object_to_mat4(ob, ob->obmat);
        }
+
+       /* read values pushed into RBO from sim/cache... */
+       BKE_rigidbody_sync_transforms(rbw, ob, ctime);
        
        /* solve constraints */
        if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
                bConstraintOb *cob;
                
-               cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
-               solve_constraints(&ob->constraints, cob, ctime);
-               constraints_clear_evalob(cob);
+               cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+               BKE_solve_constraints(&ob->constraints, cob, ctime);
+               BKE_constraints_clear_evalob(cob);
        }
        
        /* set negative scale flag in object */
@@ -2041,6 +2162,11 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
        else ob->transflag &= ~OB_NEG_SCALE;
 }
 
+void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+{
+       BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL);
+}
+
 /* get object transformation matrix without recalculating dependencies and
  * constraints -- assume dependencies are already solved by depsgraph.
  * no changes to object and it's parent would be done.
@@ -2062,15 +2188,19 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
        }
 }
 
-void BKE_object_where_is_calc(struct Scene *scene, Object *ob)
+void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob)
+{
+       BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw);
+}
+void BKE_object_where_is_calc(Scene *scene, Object *ob)
 {
-       BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+       BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL);
 }
 
-void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
 /* was written for the old game engine (until 2.04) */
 /* It seems that this function is only called
  * for a lamp that is the child of another object */
+void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
 {
        Object *par;
        float *fp1, *fp2;
@@ -2102,9 +2232,9 @@ void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
        if (ob->constraints.first) {
                bConstraintOb *cob;
                
-               cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
-               solve_constraints(&ob->constraints, cob, (float)scene->r.cfra);
-               constraints_clear_evalob(cob);
+               cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+               BKE_solve_constraints(&ob->constraints, cob, BKE_scene_frame_get(scene));
+               BKE_constraints_clear_evalob(cob);
        }
 }
 
@@ -2222,7 +2352,7 @@ void BKE_object_dimensions_set(Object *ob, const float *value)
        }
 }
 
-void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
+void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short use_hidden)
 {
        BoundBox bb;
        float vec[3];
@@ -2237,7 +2367,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
                        Curve *cu = ob->data;
 
                        /* Use the object bounding box so that modifier output
-                          gets taken into account */
+                        * gets taken into account */
                        if (ob->bb)
                                bb = *(ob->bb);
                        else {
@@ -2272,14 +2402,21 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
                break;
                case OB_ARMATURE:
                        if (ob->pose) {
+                               bArmature *arm = ob->data;
                                bPoseChannel *pchan;
+
                                for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-                                       mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
-                                       minmax_v3v3_v3(min_r, max_r, vec);
-                                       mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
-                                       minmax_v3v3_v3(min_r, max_r, vec);
+                                       /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
+                                        *     (editarmature.c:2592)... Skip in this case too! */
+                                       if (pchan->bone && !((use_hidden == FALSE) && (PBONE_VISIBLE(arm, pchan->bone) == FALSE))) {
+                                               mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
+                                               minmax_v3v3_v3(min_r, max_r, vec);
+                                               mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
+                                               minmax_v3v3_v3(min_r, max_r, vec);
+
+                                               change = TRUE;
+                                       }
                                }
-                               change = TRUE;
                        }
                        break;
                case OB_MESH:
@@ -2319,9 +2456,9 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
        }
 }
 
-int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3])
+int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const short use_hidden)
 {
-       int ok = 0;
+       int ok = FALSE;
        if ((ob->transflag & OB_DUPLI) == 0) {
                return ok;
        }
@@ -2329,9 +2466,12 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma
                ListBase *lb;
                DupliObject *dob;
                
-               lb = object_duplilist(scene, ob);
+               lb = object_duplilist(scene, ob, FALSE);
                for (dob = lb->first; dob; dob = dob->next) {
-                       if (dob->no_draw == 0) {
+                       if ((use_hidden == FALSE) && (dob->no_draw != 0)) {
+                               /* pass */
+                       }
+                       else {
                                BoundBox *bb = BKE_object_boundbox_get(dob->ob);
 
                                if (bb) {
@@ -2342,7 +2482,7 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma
                                                minmax_v3v3_v3(r_min, r_max, vec);
                                        }
 
-                                       ok = 1;
+                                       ok = TRUE;
                                }
                        }
                }
@@ -2403,7 +2543,7 @@ void BKE_scene_foreach_display_point(
                                ListBase *lb;
                                DupliObject *dob;
 
-                               lb = object_duplilist(scene, ob);
+                               lb = object_duplilist(scene, ob, FALSE);
                                for (dob = lb->first; dob; dob = dob->next) {
                                        if (dob->no_draw == 0) {
                                                BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data);
@@ -2490,7 +2630,8 @@ int BKE_object_parent_loop_check(const Object *par, const Object *ob)
 
 /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
 /* requires flags to be set! */
-void BKE_object_handle_update(Scene *scene, Object *ob)
+/* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */
+void BKE_object_handle_update_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob)
 {
        if (ob->recalc & OB_RECALC_ALL) {
                /* speed optimization for animation lookups */
@@ -2531,15 +2672,13 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                        copy_m4_m4(ob->obmat, ob->proxy_from->obmat);
                        }
                        else
-                               BKE_object_where_is_calc(scene, ob);
+                               BKE_object_where_is_calc_ex(scene, rbw, ob);
                }
                
                if (ob->recalc & OB_RECALC_DATA) {
                        ID *data_id = (ID *)ob->data;
                        AnimData *adt = BKE_animdata_from_id(data_id);
-                       float ctime = (float)scene->r.cfra; // XXX this is bad...
-                       ListBase pidlist;
-                       PTCacheID *pid;
+                       float ctime = BKE_scene_frame_get(scene);
                        
                        if (G.debug & G_DEBUG)
                                printf("recalcdata %s\n", ob->id.name + 2);
@@ -2580,8 +2719,10 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
 
                                case OB_ARMATURE:
                                        if (ob->id.lib && ob->proxy_from) {
-                                               // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
-                                               BKE_pose_copy_result(ob->pose, ob->proxy_from->pose);
+                                               if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
+                                                       printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
+                                                              ob->id.name + 2, ob->proxy_from->id.name + 2);
+                                               }
                                        }
                                        else {
                                                BKE_pose_where_is(scene, ob);
@@ -2620,6 +2761,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                        }
                                }
                        }
+                       else if (ob->type == OB_LAMP)
+                               lamp_drivers_update(scene, ob->data, ctime);
                        
                        /* particles */
                        if (ob->particlesystem.first) {
@@ -2631,7 +2774,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                while (psys) {
                                        if (psys_check_enabled(ob, psys)) {
                                                /* check use of dupli objects here */
-                                               if (psys->part && (psys->part->draw_as == PART_DRAW_REND || G.rendering) &&
+                                               if (psys->part && (psys->part->draw_as == PART_DRAW_REND || G.is_rendering) &&
                                                    ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
                                                     (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
                                                {
@@ -2651,7 +2794,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                                psys = psys->next;
                                }
 
-                               if (G.rendering && ob->transflag & OB_DUPLIPARTS) {
+                               if (G.is_rendering && ob->transflag & OB_DUPLIPARTS) {
                                        /* this is to make sure we get render level duplis in groups:
                                         * the derivedmesh must be created before init_render_mesh,
                                         * since object_duplilist does dupliparticles before that */
@@ -2662,26 +2805,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                                psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
                                }
                        }
-
-                       /* check if quick cache is needed */
-                       BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
-
-                       for (pid = pidlist.first; pid; pid = pid->next) {
-                               if ((pid->cache->flag & PTCACHE_BAKED) ||
-                                   (pid->cache->flag & PTCACHE_QUICK_CACHE) == 0)
-                               {
-                                       continue;
-                               }
-
-                               if (pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID) == 0) {
-                                       scene->physics_settings.quick_cache_step =
-                                               scene->physics_settings.quick_cache_step ?
-                                               MIN2(scene->physics_settings.quick_cache_step, pid->cache->step) :
-                                               pid->cache->step;
-                               }
-                       }
-
-                       BLI_freelistN(&pidlist);
+                       
+                       /* quick cache removed */
                }
 
                /* the no-group proxy case, we call update */
@@ -2701,6 +2826,15 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                // printf("set proxy pointer for later group stuff %s\n", ob->id.name);
        }
 }
+/* WARNING: "scene" here may not be the scene object actually resides in. 
+ * When dealing with background-sets, "scene" is actually the active scene.
+ * e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
+ * rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world
+ */
+void BKE_object_handle_update(Scene *scene, Object *ob)
+{
+       BKE_object_handle_update_ex(scene, NULL, ob);
+}
 
 void BKE_object_sculpt_modifiers_changed(Object *ob)
 {
@@ -2711,7 +2845,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
                 * changing PVBH node organization, we hope topology does not change in
                 * the meantime .. weak */
                if (ss->pbvh) {
-                       BLI_pbvh_free(ss->pbvh);
+                       BKE_pbvh_free(ss->pbvh);
                        ss->pbvh = NULL;
                }
 
@@ -2721,10 +2855,10 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
                PBVHNode **nodes;
                int n, totnode;
 
-               BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+               BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
                for (n = 0; n < totnode; n++)
-                       BLI_pbvh_node_mark_update(nodes[n]);
+                       BKE_pbvh_node_mark_update(nodes[n]);
 
                MEM_freeN(nodes);
        }
@@ -2865,24 +2999,25 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int
        int newkey = 0;
 
        if (key == NULL) {
-               key = me->key = add_key((ID *)me);
+               key = me->key = BKE_key_add((ID *)me);
                key->type = KEY_RELATIVE;
                newkey = 1;
        }
 
        if (newkey || from_mix == FALSE) {
                /* create from mesh */
-               kb = add_keyblock_ctime(key, name, FALSE);
-               mesh_to_key(me, kb);
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
+               BKE_key_convert_from_mesh(me, kb);
        }
        else {
                /* copy from current values */
-               float *data = do_ob_key(scene, ob);
+               int totelem;
+               float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
                /* create new block with prepared data */
-               kb = add_keyblock_ctime(key, name, FALSE);
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
                kb->data = data;
-               kb->totelem = me->totvert;
+               kb->totelem = totelem;
        }
 
        return kb;
@@ -2896,29 +3031,30 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int
        int newkey = 0;
 
        if (key == NULL) {
-               key = lt->key = add_key((ID *)lt);
+               key = lt->key = BKE_key_add((ID *)lt);
                key->type = KEY_RELATIVE;
                newkey = 1;
        }
 
        if (newkey || from_mix == FALSE) {
-               kb = add_keyblock_ctime(key, name, FALSE);
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
                if (!newkey) {
                        KeyBlock *basekb = (KeyBlock *)key->block.first;
                        kb->data = MEM_dupallocN(basekb->data);
                        kb->totelem = basekb->totelem;
                }
                else {
-                       latt_to_key(lt, kb);
+                       BKE_key_convert_from_lattice(lt, kb);
                }
        }
        else {
                /* copy from current values */
-               float *data = do_ob_key(scene, ob);
+               int totelem;
+               float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
                /* create new block with prepared data */
-               kb = add_keyblock_ctime(key, name, FALSE);
-               kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw;
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
+               kb->totelem = totelem;
                kb->data = data;
        }
 
@@ -2934,30 +3070,31 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int
        int newkey = 0;
 
        if (key == NULL) {
-               key = cu->key = add_key((ID *)cu);
+               key = cu->key = BKE_key_add((ID *)cu);
                key->type = KEY_RELATIVE;
                newkey = 1;
        }
 
        if (newkey || from_mix == FALSE) {
                /* create from curve */
-               kb = add_keyblock_ctime(key, name, FALSE);
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
                if (!newkey) {
                        KeyBlock *basekb = (KeyBlock *)key->block.first;
                        kb->data = MEM_dupallocN(basekb->data);
                        kb->totelem = basekb->totelem;
                }
                else {
-                       curve_to_key(cu, kb, lb);
+                       BKE_key_convert_from_curve(cu, kb, lb);
                }
        }
        else {
                /* copy from current values */
-               float *data = do_ob_key(scene, ob);
+               int totelem;
+               float *data = BKE_key_evaluate_object(scene, ob, &totelem);
 
                /* create new block with prepared data */
-               kb = add_keyblock_ctime(key, name, FALSE);
-               kb->totelem = BKE_nurbList_verts_count(lb);
+               kb = BKE_keyblock_add_ctime(key, name, FALSE);
+               kb->totelem = totelem;
                kb->data = data;
        }
 
@@ -2986,7 +3123,7 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
 {
        int flag = 0;
 
-       if (ob_get_key(ob)) {
+       if (BKE_key_from_object(ob)) {
                flag |= eModifierMode_Render;
        }
        else {
@@ -3060,17 +3197,20 @@ void BKE_object_relink(Object *ob)
        if (ob->id.lib)
                return;
 
-       relink_constraints(&ob->constraints);
+       BKE_relink_constraints(&ob->constraints);
        if (ob->pose) {
                bPoseChannel *chan;
                for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
-                       relink_constraints(&chan->constraints);
+                       BKE_relink_constraints(&chan->constraints);
                }
        }
        modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
 
        if (ob->adt)
                BKE_relink_animdata(ob->adt);
+       
+       if (ob->rigidbody_constraint)
+               BKE_rigidbody_relink_constraint(ob->rigidbody_constraint);
 
        ID_NEW(ob->parent);
 
@@ -3254,7 +3394,7 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
 {
        Group *group = NULL;
 
-       BLI_assert(base->object == object);
+       BLI_assert((base == NULL) || (base->object == object));
 
        if (scene && base == NULL) {
                base = BKE_scene_base_find(scene, object);