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 8de832e508d9895a6270d5ed62cb9464a85e8f99..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"
@@ -82,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"
@@ -96,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"
 #include "GPU_material.h"
 
 /* Local function protos */
-static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul);
-
 float originmat[3][3];  /* after BKE_object_where_is_calc(), can be used in other functions (bad!) */
 
 void BKE_object_workob_clear(Object *workob)
@@ -197,34 +199,43 @@ 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?
+       /* TODO: smoke?, cloth? */
 }
 
 /* here we will collect all local displist stuff */
@@ -256,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);
 
@@ -294,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;
@@ -324,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);
@@ -377,7 +433,7 @@ void BKE_object_unlink(Object *ob)
        unlink_actuators(&ob->actuators);
        
        /* check all objects: parents en bevels and fields, also from libraries */
-       // FIXME: need to check all animation blocks (drivers)
+       /* FIXME: need to check all animation blocks (drivers) */
        obt = bmain->object.first;
        while (obt) {
                if (obt->proxy == ob)
@@ -416,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;
                                        
@@ -438,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;
@@ -447,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;
                        
@@ -673,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;
                                                }
                                        }
@@ -711,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;
@@ -730,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);
@@ -768,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;
@@ -835,13 +935,18 @@ Object *BKE_object_add_only_object(int type, const char *name)
        /* ob->pad3 == Contact Processing Threshold */
        ob->m_contactProcessingThreshold = 1.0f;
        ob->obstacleRad = 1.0f;
-       
+       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;
 
        ob->pc_ids.first = ob->pc_ids.last = NULL;
        
-       /* Animation Visualisation defaults */
+       /* Animation Visualization defaults */
        animviz_settings_init(&ob->avs);
 
        return ob;
@@ -856,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);
 
@@ -870,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);
@@ -959,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 */
@@ -1020,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)
@@ -1041,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;
                        
@@ -1060,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;
        }
@@ -1079,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;
@@ -1101,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);
@@ -1128,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);
@@ -1141,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;
@@ -1162,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);
        
@@ -1178,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;
@@ -1316,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);
@@ -1374,7 +1509,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
        BKE_object_copy_proxy_drivers(ob, target);
 
        /* skip constraints? */
-       // FIXME: this is considered by many as a bug
+       /* FIXME: this is considered by many as a bug */
        
        /* set object type and link to data */
        ob->type = target->type;
@@ -1431,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];
        
@@ -1453,12 +1588,12 @@ void BKE_object_rot_to_mat3(Object *ob, float mat[][3])
                eulO_to_mat3(dmat, ob->drot, ob->rotmode);
        }
        else if (ob->rotmode == ROT_MODE_AXISANGLE) {
-               /* axis-angle -  not really that great for 3D-changing orientations */
+               /* axis-angle - not really that great for 3D-changing orientations */
                axis_angle_to_mat3(rmat, ob->rotAxis, ob->rotAngle);
                axis_angle_to_mat3(dmat, ob->drotAxis, ob->drotAngle);
        }
        else {
-               /* quats are normalised before use to eliminate scaling issues */
+               /* quats are normalized before use to eliminate scaling issues */
                float tquat[4];
                
                normalize_qt_qt(tquat, ob->quat);
@@ -1469,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:
@@ -1504,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);
                }
        }
 }
@@ -1575,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];
 
@@ -1604,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];
@@ -1614,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];
        
@@ -1632,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;
@@ -1665,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;
                
@@ -1686,16 +1824,16 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
 
                if (cu->flag & CU_FOLLOW) {
 #if 0
-                       float x1, q[4];
+                       float si, q[4];
                        vec_to_quat(quat, dir, ob->trackflag, ob->upflag);
                        
                        /* the tilt */
                        normalize_v3(dir);
                        q[0] = (float)cos(0.5 * vec[3]);
-                       x1 = (float)sin(0.5 * vec[3]);
-                       q[1] = -x1 * dir[0];
-                       q[2] = -x1 * dir[1];
-                       q[3] = -x1 * dir[2];
+                       si = (float)sin(0.5 * vec[3]);
+                       q[1] = -si * dir[0];
+                       q[2] = -si * dir[1];
+                       q[3] = -si * dir[2];
                        mul_qt_qtqt(quat, q, quat);
 #else
                        quat_apply_track(quat, ob->trackflag, ob->upflag);
@@ -1716,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];
@@ -1728,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;
@@ -1775,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++;
+                                       }
                                }
                        }
 
@@ -1801,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];
 
@@ -1896,7 +2014,85 @@ 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][4], float slowmat[4][4], int simul)
+{
+       float totmat[4][4];
+       float tmat[4][4];
+       float locmat[4][4];
+       float vec[3];
+       int ok;
+       
+       BKE_object_to_mat4(ob, locmat);
+       
+       if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat);
+
+       switch (ob->partype & PARTYPE) {
+               case PAROBJECT:
+                       ok = 0;
+                       if (par->type == OB_CURVE) {
+                               if (((Curve *)par->data)->flag & CU_PATH) {
+                                       ob_parcurve(scene, ob, par, tmat);
+                                       ok = 1;
+                               }
+                       }
+                       
+                       if (ok) mul_serie_m4(totmat, par->obmat, tmat,
+                                                NULL, NULL, NULL, NULL, NULL, NULL);
+                       else copy_m4_m4(totmat, par->obmat);
+                       
+                       break;
+               case PARBONE:
+                       ob_parbone(ob, par, tmat);
+                       mul_serie_m4(totmat, par->obmat, tmat,
+                                    NULL, NULL, NULL, NULL, NULL, NULL);
+                       break;
+               
+               case PARVERT1:
+                       unit_m4(totmat);
+                       if (simul) {
+                               copy_v3_v3(totmat[3], par->obmat[3]);
+                       }
+                       else {
+                               give_parvert(par, ob->par1, vec);
+                               mul_v3_m4v3(totmat[3], par->obmat, vec);
+                       }
+                       break;
+               case PARVERT3:
+                       ob_parvert3(ob, par, tmat);
+                       
+                       mul_serie_m4(totmat, par->obmat, tmat,
+                                    NULL, NULL, NULL, NULL, NULL, NULL);
+                       break;
+               
+               case PARSKEL:
+                       copy_m4_m4(totmat, par->obmat);
+                       break;
+       }
+       
+       /* total */
+       mul_serie_m4(tmat, totmat, ob->parentinv,
+                    NULL, NULL, NULL, NULL, NULL, NULL);
+       mul_serie_m4(obmat, tmat, locmat,         
+                    NULL, NULL, NULL, NULL, NULL, NULL);
+       
+       if (simul) {
+
+       }
+       else {
+               /* external usable originmat */
+               copy_m3_m4(originmat, tmat);
+               
+               /* origin, for help line */
+               if ((ob->partype & PARTYPE) == PARSKEL) {
+                       copy_v3_v3(ob->orig, par->obmat[3]);
+               }
+               else {
+                       copy_v3_v3(ob->orig, totmat[3]);
                }
        }
 }
@@ -1907,7 +2103,7 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[
        float fac1, fac2;
        int a;
 
-       // include framerate
+       /* include framerate */
        fac1 = (1.0f / (1.0f + fabsf(ob->sf)) );
        if (fac1 >= 1.0f) return 0;
        fac2 = 1.0f - fac1;
@@ -1921,15 +2117,10 @@ 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)
 {
-       float slowmat[4][4] = MAT4_UNITY;
-       float stime = ctime;
-       
-       /* new version: correct parent+vertexparent and track+parent */
-       /* this one only calculates direct attached parent and track */
-       /* is faster, but should keep track of timeoffs */
-       
        if (ob == NULL) return;
        
        /* execute drivers only, as animation has already been done */
@@ -1937,22 +2128,10 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
        
        if (ob->parent) {
                Object *par = ob->parent;
+               float slowmat[4][4] = MAT4_UNITY;
                
-               /* hurms, code below conflicts with depgraph... (ton) */
-               /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */
-               if (stime != par->ctime) {
-                       // only for ipo systems? 
-                       Object tmp = *par;
-                       
-                       if (par->proxy_from) ;  // was a copied matrix, no where_is! bad...
-                       else BKE_object_where_is_calc_time(scene, par, ctime);
-                       
-                       solve_parenting(scene, ob, par, ob->obmat, slowmat, 0);
-                       
-                       *par = tmp;
-               }
-               else
-                       solve_parenting(scene, ob, par, ob->obmat, slowmat, 0);
+               /* calculate parent matrix */
+               solve_parenting(scene, ob, par, ob->obmat, slowmat, 0);
                
                /* "slow parent" is definitely not threadsafe, and may also give bad results jumping around 
                 * An old-fashioned hack which probably doesn't really cut it anymore
@@ -1966,16 +2145,16 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
                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);
-               
-               /* constraints need ctime, not stime. Some call BKE_object_where_is_calc_time and bsystem_time */
-               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 */
@@ -1983,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.
@@ -1993,9 +2177,9 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
 
        if (ob->parent) {
                Object *par = ob->parent;
-
+               
                solve_parenting(scene, ob, par, obmat, slowmat, 1);
-
+               
                if (ob->partype & PARSLOW)
                        where_is_object_parslow(ob, obmat, slowmat);
        }
@@ -2004,95 +2188,19 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
        }
 }
 
-static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul)
+void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob)
 {
-       float totmat[4][4];
-       float tmat[4][4];
-       float locmat[4][4];
-       float vec[3];
-       int ok;
-       
-       BKE_object_to_mat4(ob, locmat);
-       
-       if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat);
-
-       switch (ob->partype & PARTYPE) {
-               case PAROBJECT:
-                       ok = 0;
-                       if (par->type == OB_CURVE) {
-                               if (((Curve *)par->data)->flag & CU_PATH) {
-                                       ob_parcurve(scene, ob, par, tmat);
-                                       ok = 1;
-                               }
-                       }
-               
-                       if (ok) mul_serie_m4(totmat, par->obmat, tmat,
-                                                NULL, NULL, NULL, NULL, NULL, NULL);
-                       else copy_m4_m4(totmat, par->obmat);
-               
-                       break;
-               case PARBONE:
-                       ob_parbone(ob, par, tmat);
-                       mul_serie_m4(totmat, par->obmat, tmat,
-                                    NULL, NULL, NULL, NULL, NULL, NULL);
-                       break;
-               
-               case PARVERT1:
-                       unit_m4(totmat);
-                       if (simul) {
-                               copy_v3_v3(totmat[3], par->obmat[3]);
-                       }
-                       else {
-                               give_parvert(par, ob->par1, vec);
-                               mul_v3_m4v3(totmat[3], par->obmat, vec);
-                       }
-                       break;
-               case PARVERT3:
-                       ob_parvert3(ob, par, tmat);
-               
-                       mul_serie_m4(totmat, par->obmat, tmat,
-                                    NULL, NULL, NULL, NULL, NULL, NULL);
-                       break;
-               
-               case PARSKEL:
-                       copy_m4_m4(totmat, par->obmat);
-                       break;
-       }
-       
-       // total 
-       mul_serie_m4(tmat, totmat, ob->parentinv,         
-                    NULL, NULL, NULL, NULL, NULL, NULL);
-       mul_serie_m4(obmat, tmat, locmat,         
-                    NULL, NULL, NULL, NULL, NULL, NULL);
-       
-       if (simul) {
-
-       }
-       else {
-               // external usable originmat 
-               copy_m3_m4(originmat, tmat);
-               
-               // origin, voor help line
-               if ((ob->partype & PARTYPE) == PARSKEL) {
-                       copy_v3_v3(ob->orig, par->obmat[3]);
-               }
-               else {
-                       copy_v3_v3(ob->orig, totmat[3]);
-               }
-       }
-
+       BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw);
 }
-
-void BKE_object_where_is_calc(struct Scene *scene, Object *ob)
+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;
@@ -2124,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);
        }
 }
 
@@ -2244,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];
@@ -2258,8 +2366,15 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
                {
                        Curve *cu = ob->data;
 
-                       if (cu->bb == NULL) BKE_curve_texspace_calc(cu);
-                       bb = *(cu->bb);
+                       /* Use the object bounding box so that modifier output
+                        * gets taken into account */
+                       if (ob->bb)
+                               bb = *(ob->bb);
+                       else {
+                               if (cu->bb == NULL)
+                                       BKE_curve_texspace_calc(cu);
+                               bb = *(cu->bb);
+                       }
 
                        for (a = 0; a < 8; a++) {
                                mul_m4_v3(ob->obmat, bb.vec[a]);
@@ -2287,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:
@@ -2315,21 +2437,28 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3])
        }
 
        if (change == FALSE) {
+               float size[3];
+
+               copy_v3_v3(size, ob->size);
+               if (ob->type == OB_EMPTY) {
+                       mul_v3_fl(size, ob->empty_drawsize);
+               }
+
                minmax_v3v3_v3(min_r, max_r, ob->obmat[3]);
 
                copy_v3_v3(vec, ob->obmat[3]);
-               add_v3_v3(vec, ob->size);
+               add_v3_v3(vec, size);
                minmax_v3v3_v3(min_r, max_r, vec);
 
                copy_v3_v3(vec, ob->obmat[3]);
-               sub_v3_v3(vec, ob->size);
+               sub_v3_v3(vec, size);
                minmax_v3v3_v3(min_r, max_r, vec);
        }
 }
 
-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;
        }
@@ -2337,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) {
@@ -2350,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;
                                }
                        }
                }
@@ -2411,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);
@@ -2498,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 */
@@ -2518,7 +2651,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
 
                /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers, 
                 * which is only in BKE_object_where_is_calc now */
-               // XXX: should this case be OB_RECALC_OB instead?
+               /* XXX: should this case be OB_RECALC_OB instead? */
                if (ob->recalc & OB_RECALC_ALL) {
                        
                        if (G.debug & G_DEBUG)
@@ -2539,22 +2672,20 @@ 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);
 
                        if (adt) {
-                               /* evaluate drivers */
-                               // XXX: for mesh types, should we push this to derivedmesh instead?
+                               /* evaluate drivers - datalevel */
+                               /* XXX: for mesh types, should we push this to derivedmesh instead? */
                                BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
                        }
 
@@ -2588,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);
@@ -2610,8 +2743,28 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
                                        BKE_lattice_modifiers_calc(scene, ob);
                                        break;
                        }
-
-
+                       
+                       /* related materials */
+                       /* XXX: without depsgraph tagging, this will always need to be run, which will be slow! 
+                        * However, not doing anything (or trying to hack around this lack) is not an option 
+                        * anymore, especially due to Cycles [#31834] 
+                        */
+                       if (ob->totcol) {
+                               int a;
+                               
+                               for (a = 1; a <= ob->totcol; a++) {
+                                       Material *ma = give_current_material(ob, a);
+                                       
+                                       if (ma) {
+                                               /* recursively update drivers for this material */
+                                               material_drivers_update(scene, ma, ctime);
+                                       }
+                               }
+                       }
+                       else if (ob->type == OB_LAMP)
+                               lamp_drivers_update(scene, ob->data, ctime);
+                       
+                       /* particles */
                        if (ob->particlesystem.first) {
                                ParticleSystem *tpsys, *psys;
                                DerivedMesh *dm;
@@ -2621,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)))
                                                {
@@ -2641,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 */
@@ -2652,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 */
@@ -2691,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)
 {
@@ -2701,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;
                }
 
@@ -2711,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);
        }
@@ -2855,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;
@@ -2886,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;
        }
 
@@ -2924,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;
        }
 
@@ -2976,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 {
@@ -3030,10 +3177,12 @@ int BKE_object_is_animated(Scene *scene, Object *ob)
        ModifierData *md;
 
        for (md = modifiers_getVirtualModifierList(ob); md; md = md->next)
-               if(modifier_dependsOnTime(md) && 
-                       (modifier_isEnabled(scene, md, eModifierMode_Realtime) || 
-                       modifier_isEnabled(scene, md, eModifierMode_Render)))
+               if (modifier_dependsOnTime(md) &&
+                   (modifier_isEnabled(scene, md, eModifierMode_Realtime) ||
+                    modifier_isEnabled(scene, md, eModifierMode_Render)))
+               {
                        return 1;
+               }
        return 0;
 }
 
@@ -3048,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);
 
@@ -3090,3 +3242,165 @@ MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, int use_default)
 
        return clip;
 }
+
+
+/*
+ * Find an associated Armature object
+ */
+static Object *obrel_armature_find(Object *ob)
+{
+       Object *ob_arm = NULL;
+
+       if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
+               ob_arm = ob->parent;
+       }
+       else {
+               ModifierData *mod;
+               for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
+                       if (mod->type == eModifierType_Armature) {
+                               ob_arm = ((ArmatureModifierData *)mod)->object;
+                       }
+               }
+       }
+
+       return ob_arm;
+}
+
+static int obrel_is_recursive_child(Object *ob, Object *child)
+{
+       Object *par;
+       for (par = child->parent; par; par = par->parent) {
+               if (par == ob) {
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+
+static int obrel_list_test(Object *ob)
+{
+       return ob && !(ob->id.flag & LIB_DOIT);
+}
+
+static void obrel_list_add(LinkNode **links, Object *ob)
+{
+       BLI_linklist_prepend(links, ob);
+       ob->id.flag |= LIB_DOIT;
+}
+
+/*
+ * Iterates over all objects of the given scene.
+ * Depending on the eObjectSet flag:
+ * collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects.
+ * If OB_SET_VISIBLE or OB_SET_SELECTED are collected, 
+ * then also add related objects according to the given includeFilters.
+ */
+LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+{
+       LinkNode *links = NULL;
+
+       Base *base;
+
+       /* Remove markers from all objects */
+       for (base = scene->base.first; base; base = base->next) {
+               base->object->id.flag &= ~LIB_DOIT;
+       }
+
+       /* iterate over all selected and visible objects */
+       for (base = scene->base.first; base; base = base->next) {
+               if (objectSet == OB_SET_ALL) {
+                       /* as we get all anyways just add it */
+                       Object *ob = base->object;
+                       obrel_list_add(&links, ob);
+               }
+               else {
+                       if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) ||
+                           (objectSet == OB_SET_VISIBLE  && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base)))
+                       {
+                               Object *ob = base->object;
+
+                               if (obrel_list_test(ob))
+                                       obrel_list_add(&links, ob);
+
+                               /* parent relationship */
+                               if (includeFilter & (OB_REL_PARENT | OB_REL_PARENT_RECURSIVE)) {
+                                       Object *parent = ob->parent;
+                                       if (obrel_list_test(parent)) {
+
+                                               obrel_list_add(&links, parent);
+
+                                               /* recursive parent relationship */
+                                               if (includeFilter & OB_REL_PARENT_RECURSIVE) {
+                                                       parent = parent->parent;
+                                                       while (obrel_list_test(parent)) {
+
+                                                               obrel_list_add(&links, parent);
+                                                               parent = parent->parent;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               /* child relationship */
+                               if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
+                                       Base *local_base;
+                                       for (local_base = scene->base.first; local_base; local_base = local_base->next) {
+                                               if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
+
+                                                       Object *child = local_base->object;
+                                                       if (obrel_list_test(child)) {
+                                                               if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && obrel_is_recursive_child(ob, child)) ||
+                                                                   (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob))
+                                                               {
+                                                                       obrel_list_add(&links, child);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+
+                               /* include related armatures */
+                               if (includeFilter & OB_REL_MOD_ARMATURE) {
+                                       Object *arm = obrel_armature_find(ob);
+                                       if (obrel_list_test(arm)) {
+                                               obrel_list_add(&links, arm);
+                                       }
+                               }
+
+                       }
+               }
+       }
+
+       return links;
+}
+
+/**
+ * return all groups this object is apart of, caller must free.
+ */
+struct LinkNode *BKE_object_groups(Object *ob)
+{
+       LinkNode *group_linknode = NULL;
+       Group *group = NULL;
+       while ((group = find_group(ob, group))) {
+               BLI_linklist_prepend(&group_linknode, group);
+       }
+
+       return group_linknode;
+}
+
+void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+{
+       Group *group = NULL;
+
+       BLI_assert((base == NULL) || (base->object == object));
+
+       if (scene && base == NULL) {
+               base = BKE_scene_base_find(scene, object);
+       }
+
+       while ((group = find_group(base->object, group))) {
+               rem_from_group(group, object, scene, base);
+       }
+}