doxygen: blender/blenkernel tagged.
[blender.git] / source / blender / blenkernel / intern / object.c
index bb7c77408ac2c733d63622b32007e657c8c28ea7..0b3d6dd4390039742b2bcd99ccaebd50d1ef7d0d 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/object.c
+ *  \ingroup bke
+ */
+
+
 #include <string.h>
 #include <math.h>
 #include <stdio.h>                     
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include "MEM_guardedalloc.h"
 
 #include "DNA_anim_types.h"
 #include "BLI_editVert.h"
 #include "BLI_math.h"
 #include "BLI_pbvh.h"
-
-#include "BKE_utildefines.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_main.h"
 #include "BKE_global.h"
-
+#include "BKE_idprop.h"
 #include "BKE_armature.h"
 #include "BKE_action.h"
 #include "BKE_bullet.h"
 
 #include "LBM_fluidsim.h"
 
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
 #include "BPY_extern.h"
 #endif
 
@@ -249,6 +249,13 @@ void free_sculptsession(Object *ob)
                if(ss->layer_co)
                        MEM_freeN(ss->layer_co);
 
+               if(ss->orig_cos)
+                       MEM_freeN(ss->orig_cos);
+               if(ss->deform_cos)
+                       MEM_freeN(ss->deform_cos);
+               if(ss->deform_imats)
+                       MEM_freeN(ss->deform_imats);
+
                MEM_freeN(ss);
 
                ob->sculpt = NULL;
@@ -271,7 +278,7 @@ void free_object(Object *ob)
                        else if(ob->type==OB_CURVE) unlink_curve(ob->data);
                        else if(ob->type==OB_MBALL) unlink_mball(ob->data);
                }
-               ob->data= 0;
+               ob->data= NULL;
        }
        
        for(a=0; a<ob->totcol; a++) {
@@ -279,16 +286,15 @@ void free_object(Object *ob)
        }
        if(ob->mat) MEM_freeN(ob->mat);
        if(ob->matbits) MEM_freeN(ob->matbits);
-       ob->mat= 0;
-       ob->matbits= 0;
+       ob->mat= NULL;
+       ob->matbits= NULL;
        if(ob->bb) MEM_freeN(ob->bb); 
-       ob->bb= 0;
+       ob->bb= NULL;
        if(ob->path) free_path(ob->path); 
-       ob->path= 0;
+       ob->path= NULL;
        if(ob->adt) BKE_free_animdata((ID *)ob);
        if(ob->poselib) ob->poselib->id.us--;
-       if(ob->dup_group) ob->dup_group->id.us--;
-       if(ob->gpd) ob->gpd->id.us--;
+       if(ob->gpd) ((ID *)ob->gpd)->us--;
        if(ob->defbase.first)
                BLI_freelistN(&ob->defbase);
        if(ob->pose)
@@ -321,11 +327,13 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec
 
        if (*obpoin==unlinkOb) {
                *obpoin = NULL;
-               ob->recalc |= OB_RECALC;
+               ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA?
        }
 }
-void unlink_object(Scene *scene, Object *ob)
+
+void unlink_object(Object *ob)
 {
+       Main *bmain= G.main;
        Object *obt;
        Material *mat;
        World *wrld;
@@ -338,14 +346,16 @@ void unlink_object(Scene *scene, Object *ob)
        bConstraint *con;
        //bActionStrip *strip; // XXX animsys 
        ModifierData *md;
-       int a;
+       ARegion *ar;
+       RegionView3D *rv3d;
+       int a, found;
        
        unlink_controllers(&ob->controllers);
        unlink_actuators(&ob->actuators);
        
        /* check all objects: parents en bevels and fields, also from libraries */
        // FIXME: need to check all animation blocks (drivers)
-       obt= G.main->object.first;
+       obt= bmain->object.first;
        while(obt) {
                if(obt->proxy==ob)
                        obt->proxy= NULL;
@@ -358,7 +368,7 @@ void unlink_object(Scene *scene, Object *ob)
                
                if(obt->parent==ob) {
                        obt->parent= NULL;
-                       obt->recalc |= OB_RECALC;
+                       obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                }
                
                modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob);
@@ -368,15 +378,15 @@ void unlink_object(Scene *scene, Object *ob)
 
                        if(cu->bevobj==ob) {
                                cu->bevobj= NULL;
-                               obt->recalc |= OB_RECALC;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                        if(cu->taperobj==ob) {
                                cu->taperobj= NULL;
-                               obt->recalc |= OB_RECALC;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                        if(cu->textoncurve==ob) {
                                cu->textoncurve= NULL;
-                               obt->recalc |= OB_RECALC;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                }
                else if(obt->type==OB_ARMATURE && obt->pose) {
@@ -405,6 +415,9 @@ void unlink_object(Scene *scene, Object *ob)
                                if(pchan->custom==ob)
                                        pchan->custom= NULL;
                        }
+               } else if(ELEM(OB_MBALL, ob->type, obt->type)) {
+                       if(is_mball_basis_for(obt, ob))
+                               obt->recalc|= OB_RECALC_DATA;
                }
                
                sca_remove_ob_poin(obt, ob);
@@ -516,7 +529,7 @@ void unlink_object(Scene *scene, Object *ob)
        }
        
        /* materials */
-       mat= G.main->mat.first;
+       mat= bmain->mat.first;
        while(mat) {
        
                for(a=0; a<MAX_MTEX; a++) {
@@ -530,22 +543,14 @@ void unlink_object(Scene *scene, Object *ob)
        }
        
        /* textures */
-       tex= G.main->tex.first;
-       while(tex) {
-               if(tex->env) {
-                       if(tex->env->object == ob) tex->env->object= NULL;
-               }
-               tex= tex->id.next;
+       for(tex= bmain->tex.first; tex; tex= tex->id.next) {
+               if(tex->env && (ob==tex->env->object)) tex->env->object= NULL;
+               if(tex->pd  && (ob==tex->pd->object))  tex->pd->object= NULL;
+               if(tex->vd  && (ob==tex->vd->object))  tex->vd->object= NULL;
        }
-       
-       /* mballs (scene==NULL when called from library.c) */
-       if(scene && ob->type==OB_MBALL) {
-               obt= find_basis_mball(scene, ob);
-               if(obt) freedisplist(&obt->disp);
-       }
-       
+
        /* worlds */
-       wrld= G.main->world.first;
+       wrld= bmain->world.first;
        while(wrld) {
                if(wrld->id.lib==NULL) {
                        for(a=0; a<MAX_MTEX; a++) {
@@ -558,7 +563,7 @@ void unlink_object(Scene *scene, Object *ob)
        }
                
        /* scenes */
-       sce= G.main->scene.first;
+       sce= bmain->scene.first;
        while(sce) {
                if(sce->id.lib==NULL) {
                        if(sce->camera==ob) sce->camera= NULL;
@@ -590,7 +595,7 @@ void unlink_object(Scene *scene, Object *ob)
        
 #if 0 // XXX old animation system
        /* ipos */
-       ipo= G.main->ipo.first;
+       ipo= bmain->ipo.first;
        while(ipo) {
                if(ipo->id.lib==NULL) {
                        IpoCurve *icu;
@@ -604,7 +609,7 @@ void unlink_object(Scene *scene, Object *ob)
 #endif // XXX old animation system
        
        /* screens */
-       sc= G.main->screen.first;
+       sc= bmain->screen.first;
        while(sc) {
                ScrArea *sa= sc->areabase.first;
                while(sa) {
@@ -614,13 +619,32 @@ void unlink_object(Scene *scene, Object *ob)
                                if(sl->spacetype==SPACE_VIEW3D) {
                                        View3D *v3d= (View3D*) sl;
 
+                                       found= 0;
                                        if(v3d->camera==ob) {
                                                v3d->camera= NULL;
-                                               // XXX if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
+                                               found= 1;
                                        }
                                        if(v3d->localvd && v3d->localvd->camera==ob ) {
                                                v3d->localvd->camera= NULL;
-                                               // XXX if(v3d->localvd->persp==V3D_CAMOB) v3d->localvd->persp= V3D_PERSP;
+                                               found += 2;
+                                       }
+
+                                       if (found) {
+                                               if (sa->spacetype == SPACE_VIEW3D) {
+                                                       for (ar= sa->regionbase.first; ar; ar= ar->next) {
+                                                               if (ar->regiontype==RGN_TYPE_WINDOW) {
+                                                                       rv3d= (RegionView3D *)ar->regiondata;
+                                                                       if (found == 1 || found == 3) {
+                                                                               if (rv3d->persp == RV3D_CAMOB)
+                                                                                       rv3d->persp= RV3D_PERSP;
+                                                                       }
+                                                                       if (found == 2 || found == 3) {
+                                                                               if (rv3d->localvd && rv3d->localvd->persp == RV3D_CAMOB)
+                                                                                       rv3d->localvd->persp= RV3D_PERSP;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
                                        }
                                }
                                else if(sl->spacetype==SPACE_OUTLINER) {
@@ -634,6 +658,14 @@ void unlink_object(Scene *scene, Object *ob)
                                                }
                                        }
                                }
+                               else if(sl->spacetype==SPACE_BUTS) {
+                                       SpaceButs *sbuts= (SpaceButs *)sl;
+
+                                       if(sbuts->pinid==(ID *)ob) {
+                                               sbuts->flag&= ~SB_PIN_CONTEXT;
+                                               sbuts->pinid= NULL;
+                                       }
+                               }
                        }
 
                        sa= sa->next;
@@ -642,14 +674,14 @@ void unlink_object(Scene *scene, Object *ob)
        }
 
        /* groups */
-       group= G.main->group.first;
+       group= bmain->group.first;
        while(group) {
                rem_from_group(group, ob, NULL, NULL);
                group= group->id.next;
        }
        
        /* cameras */
-       camera= G.main->camera.first;
+       camera= bmain->camera.first;
        while(camera) {
                if (camera->dof_ob==ob) {
                        camera->dof_ob = NULL;
@@ -672,20 +704,19 @@ int exist_object(Object *obtest)
        return 0;
 }
 
-void *add_camera(char *name)
+void *add_camera(const char *name)
 {
        Camera *cam;
        
        cam=  alloc_libblock(&G.main->camera, ID_CA, name);
 
        cam->lens= 35.0f;
-       cam->angle= 49.14f;
        cam->clipsta= 0.1f;
        cam->clipend= 100.0f;
        cam->drawsize= 0.5f;
        cam->ortho_scale= 6.0;
-       cam->flag |= CAM_SHOWTITLESAFE;
-       cam->passepartalpha = 0.2f;
+       cam->flag |= CAM_SHOWPASSEPARTOUT;
+       cam->passepartalpha = 0.5f;
        
        return cam;
 }
@@ -695,7 +726,6 @@ Camera *copy_camera(Camera *cam)
        Camera *camn;
        
        camn= copy_libblock(cam);
-       camn->adt= BKE_copy_animdata(cam->adt);
        
        return camn;
 }
@@ -704,6 +734,7 @@ Camera *copy_camera(Camera *cam)
 
 void make_local_camera(Camera *cam)
 {
+       Main *bmain= G.main;
        Object *ob;
        Camera *camn;
        int local=0, lib=0;
@@ -713,15 +744,15 @@ void make_local_camera(Camera *cam)
                * - mixed: make copy
                */
        
-       if(cam->id.lib==0) return;
+       if(cam->id.lib==NULL) return;
        if(cam->id.us==1) {
-               cam->id.lib= 0;
+               cam->id.lib= NULL;
                cam->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)cam, 0);
+               new_id(NULL, (ID *)cam, NULL);
                return;
        }
        
-       ob= G.main->object.first;
+       ob= bmain->object.first;
        while(ob) {
                if(ob->data==cam) {
                        if(ob->id.lib) lib= 1;
@@ -731,19 +762,19 @@ void make_local_camera(Camera *cam)
        }
        
        if(local && lib==0) {
-               cam->id.lib= 0;
+               cam->id.lib= NULL;
                cam->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)cam, 0);
+               new_id(NULL, (ID *)cam, NULL);
        }
        else if(local && lib) {
                camn= copy_camera(cam);
                camn->id.us= 0;
                
-               ob= G.main->object.first;
+               ob= bmain->object.first;
                while(ob) {
                        if(ob->data==cam) {
                                
-                               if(ob->id.lib==0) {
+                               if(ob->id.lib==NULL) {
                                        ob->data= camn;
                                        camn->id.us++;
                                        cam->id.us--;
@@ -774,7 +805,7 @@ float dof_camera(Object *ob)
        return cam->YF_dofdist;
 }
 
-void *add_lamp(char *name)
+void *add_lamp(const char *name)
 {
        Lamp *la;
        
@@ -852,6 +883,7 @@ Lamp *copy_lamp(Lamp *la)
 
 void make_local_lamp(Lamp *la)
 {
+       Main *bmain= G.main;
        Object *ob;
        Lamp *lan;
        int local=0, lib=0;
@@ -861,15 +893,15 @@ void make_local_lamp(Lamp *la)
                * - mixed: make copy
                */
        
-       if(la->id.lib==0) return;
+       if(la->id.lib==NULL) return;
        if(la->id.us==1) {
-               la->id.lib= 0;
+               la->id.lib= NULL;
                la->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)la, 0);
+               new_id(NULL, (ID *)la, NULL);
                return;
        }
        
-       ob= G.main->object.first;
+       ob= bmain->object.first;
        while(ob) {
                if(ob->data==la) {
                        if(ob->id.lib) lib= 1;
@@ -879,19 +911,19 @@ void make_local_lamp(Lamp *la)
        }
        
        if(local && lib==0) {
-               la->id.lib= 0;
+               la->id.lib= NULL;
                la->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)la, 0);
+               new_id(NULL, (ID *)la, NULL);
        }
        else if(local && lib) {
                lan= copy_lamp(la);
                lan->id.us= 0;
                
-               ob= G.main->object.first;
+               ob= bmain->object.first;
                while(ob) {
                        if(ob->data==la) {
                                
-                               if(ob->id.lib==0) {
+                               if(ob->id.lib==NULL) {
                                        ob->data= lan;
                                        lan->id.us++;
                                        la->id.us--;
@@ -927,12 +959,6 @@ void free_lamp(Lamp *la)
        la->id.icon_id = 0;
 }
 
-void *add_wave()
-{
-       return 0;
-}
-
-
 /* *************************************************** */
 
 static void *add_obdata_from_type(int type)
@@ -946,7 +972,6 @@ static void *add_obdata_from_type(int type)
        case OB_CAMERA: return add_camera("Camera");
        case OB_LAMP: return add_lamp("Lamp");
        case OB_LATTICE: return add_lattice("Lattice");
-       case OB_WAVE: return add_wave();
        case OB_ARMATURE: return add_armature("Armature");
        case OB_EMPTY: return NULL;
        default:
@@ -955,18 +980,17 @@ static void *add_obdata_from_type(int type)
        }
 }
 
-static char *get_obdata_defname(int type)
+static const char *get_obdata_defname(int type)
 {
        switch (type) {
        case OB_MESH: return "Mesh";
        case OB_CURVE: return "Curve";
        case OB_SURF: return "Surf";
-       case OB_FONT: return "Font";
+       case OB_FONT: return "Text";
        case OB_MBALL: return "Mball";
        case OB_CAMERA: return "Camera";
        case OB_LAMP: return "Lamp";
        case OB_LATTICE: return "Lattice";
-       case OB_WAVE: return "Wave";
        case OB_ARMATURE: return "Armature";
        case OB_EMPTY: return "Empty";
        default:
@@ -976,7 +1000,7 @@ static char *get_obdata_defname(int type)
 }
 
 /* more general add: creates minimum required data, but without vertices etc. */
-Object *add_only_object(int type, char *name)
+Object *add_only_object(int type, const char *name)
 {
        Object *ob;
 
@@ -994,10 +1018,13 @@ Object *add_only_object(int type, char *name)
         * but rotations default to quaternions 
         */
        ob->rotmode= ROT_MODE_EUL;
-       /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */
-       ob->rotAxis[1]= ob->drotAxis[1]= 1.0f;
-       /* quaternions should be 1,0,0,0 by default.... */
-       ob->quat[0]= ob->dquat[0]= 1.0f;
+
+       unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+       unit_axis_angle(ob->drotAxis, &ob->drotAngle);
+
+       unit_qt(ob->quat);
+       unit_qt(ob->dquat);
+
        /* rotation locks should be 4D for 4 component rotations by default... */
        ob->protectflag = OB_LOCK_ROT4D;
        
@@ -1005,7 +1032,7 @@ Object *add_only_object(int type, char *name)
        unit_m4(ob->parentinv);
        unit_m4(ob->obmat);
        ob->dt= OB_TEXTURE;
-       ob->empty_drawtype= OB_ARROWS;
+       ob->empty_drawtype= OB_PLAINAXES;
        ob->empty_drawsize= 1.0;
 
        if(type==OB_CAMERA || type==OB_LAMP) {
@@ -1031,6 +1058,8 @@ Object *add_only_object(int type, char *name)
        ob->anisotropicFriction[2] = 1.0f;
        ob->gameflag= OB_PROP|OB_COLLISION;
        ob->margin = 0.0;
+       ob->init_state=1;
+       ob->state=1;
        /* ob->pad3 == Contact Processing Threshold */
        ob->m_contactProcessingThreshold = 1.;
        
@@ -1054,7 +1083,7 @@ Object *add_object(struct Scene *scene, int type)
        Base *base;
        char name[32];
 
-       strcpy(name, get_obdata_defname(type));
+       BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
        ob = add_only_object(type, name);
 
        ob->data= add_obdata_from_type(type);
@@ -1063,7 +1092,7 @@ Object *add_object(struct Scene *scene, int type)
        
        base= scene_add_base(scene, ob);
        scene_select_base(scene, base);
-       ob->recalc |= OB_RECALC;
+       ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
 
        return ob;
 }
@@ -1103,7 +1132,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
        return bsbn;
 }
 
-ParticleSystem *copy_particlesystem(ParticleSystem *psys)
+static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
 {
        ParticleSystem *psysn;
        ParticleData *pa;
@@ -1145,12 +1174,13 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
        }
 
        BLI_duplicatelist(&psysn->targets, &psys->targets);
-       
+
        psysn->pathcache= NULL;
        psysn->childcache= NULL;
        psysn->edit= NULL;
        psysn->frand= NULL;
        psysn->pdd= NULL;
+       psysn->effectors= NULL;
        
        psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
        psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
@@ -1247,6 +1277,17 @@ static void copy_object_pose(Object *obn, Object *ob)
        }
 }
 
+static void copy_object_transform(Object *ob_tar, Object *ob_src)
+{
+       copy_v3_v3(ob_tar->loc, ob_src->loc);
+       copy_v3_v3(ob_tar->rot, ob_src->rot);
+       copy_v3_v3(ob_tar->quat, ob_src->quat);
+       copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
+       ob_tar->rotAngle= ob_src->rotAngle;
+       ob_tar->rotmode= ob_src->rotmode;
+       copy_v3_v3(ob_tar->size, ob_src->size);
+}
+
 Object *copy_object(Object *ob)
 {
        Object *obn;
@@ -1269,6 +1310,7 @@ Object *copy_object(Object *ob)
        
        for (md=ob->modifiers.first; md; md=md->next) {
                ModifierData *nmd = modifier_new(md->type);
+               BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
                modifier_copyData(md, nmd);
                BLI_addtail(&obn->modifiers, nmd);
        }
@@ -1287,15 +1329,15 @@ Object *copy_object(Object *ob)
                        armature_rebuild_pose(obn, obn->data);
        }
        defgroup_copy_list(&obn->defbase, &ob->defbase);
-       copy_constraints(&obn->constraints, &ob->constraints);
+       copy_constraints(&obn->constraints, &ob->constraints, TRUE);
 
        obn->mode = 0;
        obn->sculpt = NULL;
 
        /* increase user numbers */
        id_us_plus((ID *)obn->data);
-       id_us_plus((ID *)obn->dup_group);
-       
+       id_us_plus((ID *)obn->gpd);
+       id_lib_extern((ID *)obn->dup_group);
 
        for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
        
@@ -1318,6 +1360,8 @@ Object *copy_object(Object *ob)
 
        obn->gpulamp.first = obn->gpulamp.last = NULL;
        obn->pc_ids.first = obn->pc_ids.last = NULL;
+
+       obn->mpath= NULL;
        
        return obn;
 }
@@ -1349,6 +1393,7 @@ void expand_local_object(Object *ob)
 
 void make_local_object(Object *ob)
 {
+       Main *bmain= G.main;
        Object *obn;
        Scene *sce;
        Base *base;
@@ -1370,7 +1415,7 @@ void make_local_object(Object *ob)
 
        }
        else {
-               sce= G.main->scene.first;
+               sce= bmain->scene.first;
                while(sce) {
                        base= sce->base.first;
                        while(base) {
@@ -1393,7 +1438,7 @@ void make_local_object(Object *ob)
                        obn= copy_object(ob);
                        obn->id.us= 0;
                        
-                       sce= G.main->scene.first;
+                       sce= bmain->scene.first;
                        while(sce) {
                                if(sce->id.lib==0) {
                                        base= sce->base.first;
@@ -1444,7 +1489,7 @@ static void armature_set_id_extern(Object *ob)
 {
        bArmature *arm= ob->data;
        bPoseChannel *pchan;
-       int lay= arm->layer_protected;
+       unsigned int lay= arm->layer_protected;
        
        for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
                if(!(pchan->bone->layer & lay))
@@ -1474,10 +1519,16 @@ void object_copy_proxy_drivers(Object *ob, Object *target)
                                /* all drivers */
                                DRIVER_TARGETS_LOOPER(dvar) 
                                {
-                                       if ((Object *)dtar->id == target)
-                                               dtar->id= (ID *)ob;
-                                       else
-                                               id_lib_extern((ID *)dtar->id);
+                                       if(dtar->id) {
+                                               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
+                                                        * when a.blend has a proxy thats linked into c.blend  */
+                                                       if(ob->id.lib==NULL)
+                                                               id_lib_extern((ID *)dtar->id);
+                                               }
+                                       }
                                }
                                DRIVER_TARGETS_LOOPER_END
                        }
@@ -1501,25 +1552,25 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
        ob->proxy_group= gob;
        id_lib_extern(&target->id);
        
-       ob->recalc= target->recalc= OB_RECALC;
+       ob->recalc= target->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
        
-       /* copy transform */
+       /* copy transform
+        * - gob means this proxy comes from a group, just apply the matrix
+        *   so the object wont move from its dupli-transform.
+        *
+        * - no gob means this is being made from a linked object,
+        *   this is closer to making a copy of the object - in-place. */
        if(gob) {
-               VECCOPY(ob->loc, gob->loc);
-               VECCOPY(ob->rot, gob->rot);
-               VECCOPY(ob->size, gob->size);
-               
-               group_tag_recalc(gob->dup_group);
+               ob->rotmode= target->rotmode;
+               mul_m4_m4m4(ob->obmat, target->obmat, gob->obmat);
+               object_apply_mat4(ob, ob->obmat, FALSE, TRUE);
        }
        else {
-               VECCOPY(ob->loc, target->loc);
-               VECCOPY(ob->rot, target->rot);
-               VECCOPY(ob->size, target->size);
+               copy_object_transform(ob, target);
+               ob->parent= target->parent;     /* libdata */
+               copy_m4_m4(ob->parentinv, target->parentinv);
        }
        
-       ob->parent= target->parent;     /* libdata */
-       copy_m4_m4(ob->parentinv, target->parentinv);
-       
        /* copy animdata stuff - drivers only for now... */
        object_copy_proxy_drivers(ob, target);
 
@@ -1560,7 +1611,17 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
                
                armature_set_id_extern(ob);
        }
-       
+
+       /* copy IDProperties */
+       if(ob->id.properties) {
+               IDP_FreeProperty(ob->id.properties);
+               MEM_freeN(ob->id.properties);
+               ob->id.properties= NULL;
+       }
+       if(target->id.properties) {
+               ob->id.properties= IDP_CopyProperty(target->id.properties);
+       }
+
        /* copy drawtype info */
        ob->dt= target->dt;
 }
@@ -1570,19 +1631,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
 
 /* there is also a timing calculation in drawobject() */
 
-float bluroffs= 0.0f, fieldoffs= 0.0f;
-int no_speed_curve= 0;
-
-/* ugly calls from render */
-void set_mblur_offs(float blur)
-{
-       bluroffs= blur;
-}
-
-void set_field_offs(float field)
-{
-       fieldoffs= field;
-}
+static int no_speed_curve= 0;
 
 void disable_speed_curve(int val)
 {
@@ -1591,13 +1640,11 @@ void disable_speed_curve(int val)
 
 // XXX THIS CRUFT NEEDS SERIOUS RECODING ASAP!
 /* ob can be NULL */
-float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs)
+float bsystem_time(struct Scene *scene, Object *UNUSED(ob), float cfra, float ofs)
 {
-       /* returns float ( see frame_to_float in ipo.c) */
+       /* returns float ( see BKE_curframe in scene.c) */
+       cfra += scene->r.subframe;
        
-       /* bluroffs and fieldoffs are ugly globals that are set by render */
-       cfra+= bluroffs+fieldoffs;
-
        /* global time */
        if (scene)
                cfra*= scene->r.framelen;       
@@ -1618,14 +1665,11 @@ float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs)
 void object_scale_to_mat3(Object *ob, float mat[][3])
 {
        float vec[3];
-       
-       vec[0]= ob->size[0]+ob->dsize[0];
-       vec[1]= ob->size[1]+ob->dsize[1];
-       vec[2]= ob->size[2]+ob->dsize[2];
+       add_v3_v3v3(vec, ob->size, ob->dsize);
        size_to_mat3( mat,vec);
 }
 
-// TODO: this should take rotation orders into account later...
+
 void object_rot_to_mat3(Object *ob, float mat[][3])
 {
        float rmat[3][3], dmat[3][3];
@@ -1648,41 +1692,67 @@ void object_rot_to_mat3(Object *ob, float mat[][3])
        }
        else {
                /* quats are normalised before use to eliminate scaling issues */
-               normalize_qt(ob->quat);
-               quat_to_mat3( rmat,ob->quat);
-               quat_to_mat3( dmat,ob->dquat);
+               float tquat[4];
+               
+               normalize_qt_qt(tquat, ob->quat);
+               quat_to_mat3(rmat, tquat);
+               
+               normalize_qt_qt(tquat, ob->dquat);
+               quat_to_mat3(dmat, tquat);
        }
        
        /* combine these rotations */
-       // XXX is this correct? if errors, change the order of multiplication...
        mul_m3_m3m3(mat, dmat, rmat);
 }
 
-void object_mat3_to_rot(Object *ob, float mat[][3], int use_compat)
+void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
 {
-       if (ob->rotmode == ROT_MODE_QUAT)
-               mat3_to_quat(ob->quat, mat);
-       else if (ob->rotmode == ROT_MODE_AXISANGLE)
-               mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat);
-       else {
-               if(use_compat) {
-                       float eul[3];
-                       VECCOPY(eul, ob->rot);
-                       mat3_to_compatible_eulO(ob->rot, eul, ob->rotmode, mat);
+       switch(ob->rotmode) {
+       case ROT_MODE_QUAT:
+               {
+                       float dquat[4];
+                       mat3_to_quat(ob->quat, mat);
+                       normalize_qt_qt(dquat, ob->dquat);
+                       invert_qt(dquat);
+                       mul_qt_qtqt(ob->quat, dquat, ob->quat);
                }
-               else
-                       mat3_to_eulO(ob->rot, ob->rotmode, mat);
+               break;
+       case ROT_MODE_AXISANGLE:
+               mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat);
+               sub_v3_v3(ob->rotAxis, ob->drotAxis);
+               ob->rotAngle -= ob->drotAngle;
+               break;
+       default: /* euler */
+               if(use_compat)  mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, mat);
+               else                    mat3_to_eulO(ob->rot, ob->rotmode, mat);
+               sub_v3_v3(ob->rot, ob->drot);
        }
 }
 
 /* see pchan_apply_mat4() for the equivalent 'pchan' function */
-void object_apply_mat4(Object *ob, float mat[][4])
+void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent)
 {
-       float mat3[3][3];
-       VECCOPY(ob->loc, mat[3]);
-       mat4_to_size(ob->size, mat);
-       copy_m3_m4(mat3, mat);
-       object_mat3_to_rot(ob, mat3, 0);
+       float rot[3][3];
+
+       if(use_parent && ob->parent) {
+               float rmat[4][4], diff_mat[4][4], imat[4][4];
+               mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
+               invert_m4_m4(imat, diff_mat);
+               mul_m4_m4m4(rmat, mat, imat); /* get the parent relative matrix */
+               object_apply_mat4(ob, rmat, use_compat, FALSE);
+               
+               /* same as below, use rmat rather then mat */
+               mat4_to_loc_rot_size(ob->loc, rot, ob->size, rmat);
+               object_mat3_to_rot(ob, rot, use_compat);
+       }
+       else {
+               mat4_to_loc_rot_size(ob->loc, rot, ob->size, mat);
+               object_mat3_to_rot(ob, rot, use_compat);
+       }
+       
+       sub_v3_v3(ob->loc, ob->dloc);
+       sub_v3_v3(ob->size, ob->dsize);
+       /* object_mat3_to_rot handles delta rotations */
 }
 
 void object_to_mat3(Object *ob, float mat[][3])        /* no parent */
@@ -1706,18 +1776,17 @@ void object_to_mat4(Object *ob, float mat[][4])
        object_to_mat3(ob, tmat);
        
        copy_m4_m3(mat, tmat);
-       
-       mat[3][0]= ob->loc[0] + ob->dloc[0];
-       mat[3][1]= ob->loc[1] + ob->dloc[1];
-       mat[3][2]= ob->loc[2] + ob->dloc[2];
+
+       add_v3_v3v3(mat[3], ob->loc, ob->dloc);
 }
 
+/* extern */
 int enable_cu_speed= 1;
 
 static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
 {
        Curve *cu;
-       float q[4], vec[4], dir[3], quat[4], radius, x1, ctime;
+       float vec[4], dir[3], quat[4], radius, ctime;
        float timeoffs = 0.0, sf_orig = 0.0;
        
        unit_m4(mat);
@@ -1745,12 +1814,17 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
                 * we divide the curvetime calculated in the previous step by the length of the path, to get a time
                 * factor, which then gets clamped to lie within 0.0 - 1.0 range
                 */
-               ctime= cu->ctime / cu->pathlen;
+               if (IS_EQ(cu->pathlen, 0.0f) == 0)
+                       ctime= cu->ctime / cu->pathlen;
+               else
+                       ctime= cu->ctime;
+               
                CLAMP(ctime, 0.0, 1.0);
        }
        else {
                ctime= scene->r.cfra - give_timeoffset(ob);
-               ctime /= cu->pathlen;
+               if (IS_EQ(cu->pathlen, 0.0f) == 0)
+                       ctime /= cu->pathlen;
                
                CLAMP(ctime, 0.0, 1.0);
        }
@@ -1765,9 +1839,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
        
        
        /* vec: 4 items! */
-        if( where_on_path(par, ctime, vec, dir, NULL, &radius) ) {
+       if( where_on_path(par, ctime, vec, dir, cu->flag & CU_FOLLOW ? quat:NULL, &radius, NULL) ) {
 
                if(cu->flag & CU_FOLLOW) {
+#if 0
+                       float x1, q[4];
                        vec_to_quat( quat,dir, ob->trackflag, ob->upflag);
                        
                        /* the tilt */
@@ -1778,8 +1854,11 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
                        q[2]= -x1*dir[1];
                        q[3]= -x1*dir[2];
                        mul_qt_qtqt(quat, q, quat);
-                       
-                       quat_to_mat4( mat,quat);
+#else
+                       quat_apply_track(quat, ob->trackflag, ob->upflag);
+#endif
+                       normalize_qt(quat);
+                       quat_to_mat4(mat, quat);
                }
                
                if(cu->flag & CU_PATH_RADIUS) {
@@ -1789,7 +1868,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
                        copy_m4_m4(mat, rmat);
                }
 
-               VECCOPY(mat[3], vec);
+               copy_v3_v3(mat[3], vec);
                
        }
 }
@@ -1816,9 +1895,9 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4])
        copy_m4_m4(mat, pchan->pose_mat);
 
        /* but for backwards compatibility, the child has to move to the tail */
-       VECCOPY(vec, mat[1]);
+       copy_v3_v3(vec, mat[1]);
        mul_v3_fl(vec, pchan->bone->length);
-       add_v3_v3v3(mat[3], mat[3], vec);
+       add_v3_v3(mat[3], vec);
 }
 
 static void give_parvert(Object *par, int nr, float *vec)
@@ -1830,47 +1909,38 @@ static void give_parvert(Object *par, int nr, float *vec)
        
        if(par->type==OB_MESH) {
                Mesh *me= par->data;
-               em = BKE_mesh_get_editmesh(me);
+               DerivedMesh *dm;
 
-               if(em) {
-                       EditVert *eve;
+               em = BKE_mesh_get_editmesh(me);
+               dm = (em)? em->derivedFinal: par->derivedFinal;
                        
-                       for(eve= em->verts.first; eve; eve= eve->next) {
-                               if(eve->keyindex==nr) {
-                                       memcpy(vec, eve->co, sizeof(float)*3);
-                                       break;
+               if(dm) {
+                       MVert *mvert= dm->getVertArray(dm);
+                       int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
+                       int i, count = 0, vindex, numVerts = dm->getNumVerts(dm);
+
+                       /* get the average of all verts with (original index == nr) */
+                       for(i = 0; i < numVerts; i++) {
+                               vindex= (index)? index[i]: i;
+
+                               if(vindex == nr) {
+                                       add_v3_v3(vec, mvert[i].co);
+                                       count++;
                                }
                        }
-                       BKE_mesh_end_editmesh(me, em);
-               }
-               else {
-                       DerivedMesh *dm = par->derivedFinal;
-                       
-                       if(dm) {
-                               MVert *mvert= dm->getVertArray(dm);
-                               int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
-                               int i, count = 0, vindex, numVerts = dm->getNumVerts(dm);
-
-                               /* get the average of all verts with (original index == nr) */
-                               for(i = 0; i < numVerts; i++) {
-                                       vindex= (index)? index[i]: i;
-
-                                       if(vindex == nr) {
-                                               add_v3_v3v3(vec, vec, mvert[i].co);
-                                               count++;
-                                       }
-                               }
 
-                               if (count==0) {
-                                       /* keep as 0,0,0 */
-                               } else if(count > 0) {
-                                       mul_v3_fl(vec, 1.0f / count);
-                               } else {
-                                       /* use first index if its out of range */
-                                       dm->getVertCo(dm, 0, vec);
-                               }
+                       if (count==0) {
+                               /* keep as 0,0,0 */
+                       } else if(count > 0) {
+                               mul_v3_fl(vec, 1.0f / count);
+                       } else {
+                               /* use first index if its out of range */
+                               dm->getVertCo(dm, 0, vec);
                        }
                }
+
+               if(em)
+                       BKE_mesh_end_editmesh(me, em);
        }
        else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
                Nurb *nu;
@@ -1878,13 +1948,12 @@ static void give_parvert(Object *par, int nr, float *vec)
                BPoint *bp;
                BezTriple *bezt;
                int found= 0;
-               
+               ListBase *nurbs;
+
                cu= par->data;
-               if(cu->editnurb)
-                       nu= cu->editnurb->first;
-               else
-                       nu= cu->nurb.first;
-               
+               nurbs= BKE_curve_nurbs(cu);
+               nu= nurbs->first;
+
                count= 0;
                while(nu && !found) {
                        if(nu->type == CU_BEZIER) {
@@ -1923,7 +1992,7 @@ static void give_parvert(Object *par, int nr, float *vec)
                DispList *dl = find_displist(&par->disp, DL_VERTS);
                float *co = dl?dl->verts:NULL;
                
-               if(latt->editlatt) latt= latt->editlatt;
+               if(latt->editlatt) latt= latt->editlatt->latt;
                
                a= latt->pntsu*latt->pntsv*latt->pntsw;
                count= 0;
@@ -1965,7 +2034,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4])
                }
                else {
                        add_v3_v3v3(mat[3], v1, v2);
-                       add_v3_v3v3(mat[3], mat[3], v3);
+                       add_v3_v3(mat[3], v3);
                        mul_v3_fl(mat[3], 0.3333333f);
                }
        }
@@ -2033,7 +2102,7 @@ void where_is_object_time(Scene *scene, Object *ob, float ctime)
        }
 
        /* solve constraints */
-       if (ob->constraints.first && !(ob->flag & OB_NO_CONSTRAINTS)) {
+       if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
                bConstraintOb *cob;
                
                cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
@@ -2118,7 +2187,7 @@ static void solve_parenting (Scene *scene, Object *ob, Object *par, float obmat[
                copy_m3_m4(originmat, tmat);
                
                // origin, voor help line
-               if( (ob->partype & 15)==PARSKEL ) {
+               if( (ob->partype & PARTYPE)==PARSKEL ) {
                        VECCOPY(ob->orig, par->obmat[3]);
                }
                else {
@@ -2204,7 +2273,7 @@ void what_does_parent(Scene *scene, Object *ob, Object *workob)
        where_is_object(scene, workob);
 }
 
-BoundBox *unit_boundbox()
+BoundBox *unit_boundbox(void)
 {
        BoundBox *bb;
        float min[3] = {-1.0f,-1.0f,-1.0f}, max[3] = {-1.0f,-1.0f,-1.0f};
@@ -2318,11 +2387,9 @@ void minmax_object(Object *ob, float *min, float *max)
                if(ob->pose) {
                        bPoseChannel *pchan;
                        for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                               VECCOPY(vec, pchan->pose_head);
-                               mul_m4_v3(ob->obmat, vec);
+                               mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
                                DO_MINMAX(vec, min, max);
-                               VECCOPY(vec, pchan->pose_tail);
-                               mul_m4_v3(ob->obmat, vec);
+                               mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
                                DO_MINMAX(vec, min, max);
                        }
                        break;
@@ -2346,12 +2413,12 @@ void minmax_object(Object *ob, float *min, float *max)
        default:
                DO_MINMAX(ob->obmat[3], min, max);
 
-               VECCOPY(vec, ob->obmat[3]);
-               add_v3_v3v3(vec, vec, ob->size);
+               copy_v3_v3(vec, ob->obmat[3]);
+               add_v3_v3(vec, ob->size);
                DO_MINMAX(vec, min, max);
 
-               VECCOPY(vec, ob->obmat[3]);
-               sub_v3_v3v3(vec, vec, ob->size);
+               copy_v3_v3(vec, ob->obmat[3]);
+               sub_v3_v3(vec, ob->size);
                DO_MINMAX(vec, min, max);
                break;
        }
@@ -2458,14 +2525,26 @@ void object_tfm_restore(Object *ob, void *obtfm_pt)
 /* requires flags to be set! */
 void object_handle_update(Scene *scene, Object *ob)
 {
-       if(ob->recalc & OB_RECALC) {
+       if(ob->recalc & OB_RECALC_ALL) {
                /* speed optimization for animation lookups */
                if(ob->pose)
                        make_pose_channels_hash(ob->pose);
 
+               if(ob->recalc & OB_RECALC_DATA) {
+                       if(ob->type==OB_ARMATURE) {
+                               /* this happens for reading old files and to match library armatures
+                                  with poses we do it ahead of where_is_object to ensure animation
+                                  is evaluated on the rebuilt pose, otherwise we get incorrect poses
+                                  on file load */
+                               if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
+                                       armature_rebuild_pose(ob, ob->data);
+                       }
+               }
+
                /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers, 
                   which is only in where_is_object now */
-               if(ob->recalc & OB_RECALC) {
+               // XXX: should this case be OB_RECALC_OB instead?
+               if(ob->recalc & OB_RECALC_ALL) {
                        
                        if (G.f & G_DEBUG)
                                printf("recalcob %s\n", ob->id.name+2);
@@ -2489,56 +2568,69 @@ void object_handle_update(Scene *scene, Object *ob)
                        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;
                        
                        if (G.f & G_DEBUG)
                                printf("recalcdata %s\n", ob->id.name+2);
-                       
-                       /* includes all keys and modifiers */
-                       if(ob->type==OB_MESH) {
-                               EditMesh *em = BKE_mesh_get_editmesh(ob->data);
-                               
-                               /* evaluate drivers */
-                               // XXX: should we push this to derivedmesh instead?
-                               BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
-                               
-                                       // here was vieweditdatamask? XXX
-                               if(ob->mode & OB_MODE_EDIT) {
-                                       makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH);
-                                       BKE_mesh_end_editmesh(ob->data, em);
-                               } else
-                                       makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
-                       }
-                       else if(ob->type==OB_MBALL) {
-                               makeDispListMBall(scene, ob);
-                       } 
-                       else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-                               makeDispListCurveTypes(scene, ob, 0);
-                       }
-                       else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) {
+
+                       if(adt) {
                                /* evaluate drivers */
+                               // XXX: for mesh types, should we push this to derivedmesh instead?
                                BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
                        }
-                       else if(ob->type==OB_LATTICE) {
-                               lattice_calc_modifiers(scene, ob);
-                       }
-                       else if(ob->type==OB_ARMATURE) {
-                               /* this happens for reading old files and to match library armatures with poses */
-                               // XXX this won't screw up the pose set already...
-                               if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
-                                       armature_rebuild_pose(ob, ob->data);
-                               
-                               /* evaluate drivers */
-                               BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
-                               
+
+                       /* includes all keys and modifiers */
+                       switch(ob->type) {
+                       case OB_MESH:
+                               {
+#if 0                          // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask'
+                                       EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL;
+                                       BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH);
+                                       if(em) {
+                                               makeDerivedMesh(scene, ob, em,  scene->customdata_mask); /* was CD_MASK_BAREMESH */
+                                               BKE_mesh_end_editmesh(ob->data, em);
+                                       } else
+                                               makeDerivedMesh(scene, ob, NULL, scene->customdata_mask);
+
+#else                          /* ensure CD_MASK_BAREMESH for now */
+                                       EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL;
+                                       if(em) {
+                                               makeDerivedMesh(scene, ob, em,  scene->customdata_mask | CD_MASK_BAREMESH); /* was CD_MASK_BAREMESH */
+                                               BKE_mesh_end_editmesh(ob->data, em);
+                                       } else
+                                               makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH);
+#endif
+
+                               }
+                               break;
+
+                       case OB_ARMATURE:
                                if(ob->id.lib && ob->proxy_from) {
-                                       copy_pose_result(ob->pose, ob->proxy_from->pose);
                                        // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
+                                       copy_pose_result(ob->pose, ob->proxy_from->pose);
                                }
                                else {
                                        where_is_pose(scene, ob);
                                }
+                               break;
+
+                       case OB_MBALL:
+                               makeDispListMBall(scene, ob);
+                               break;
+
+                       case OB_CURVE:
+                       case OB_SURF:
+                       case OB_FONT:
+                               makeDispListCurveTypes(scene, ob, 0);
+                               break;
+                               
+                       case OB_LATTICE:
+                               lattice_calc_modifiers(scene, ob);
+                               break;
                        }
 
+
                        if(ob->particlesystem.first) {
                                ParticleSystem *tpsys, *psys;
                                DerivedMesh *dm;
@@ -2548,7 +2640,7 @@ void 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 &&
+                                               if(psys->part && (psys->part->draw_as == PART_DRAW_REND || G.rendering) &&
                                                        ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob)
                                                        || (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
                                                        ob->transflag |= OB_DUPLIPARTS;
@@ -2577,6 +2669,24 @@ void 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);
                }
 
                /* the no-group proxy case, we call update */
@@ -2587,7 +2697,7 @@ void object_handle_update(Scene *scene, Object *ob)
                        object_handle_update(scene, ob->proxy);
                }
        
-               ob->recalc &= ~OB_RECALC;
+               ob->recalc &= ~OB_RECALC_ALL;
        }
 
        /* the case when this is a group proxy, object_update is called in group.c */
@@ -2712,7 +2822,7 @@ void object_camera_matrix(
        float pixsize;
        float shiftx=0.0, shifty=0.0, winside, viewfac;
 
-       rd->mode &= ~R_ORTHO;
+       rd->mode &= ~(R_ORTHO|R_PANORAMA);
 
        /* question mark */
        (*ycor)= rd->yasp / rd->xasp;
@@ -2844,7 +2954,7 @@ void object_delete_ptcache(Object *ob, int index)
 /* shape key utility function */
 
 /************************* Mesh ************************/
-static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int from_mix)
 {
        Mesh *me= ob->data;
        Key *key= me->key;
@@ -2857,22 +2967,25 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_m
                newkey= 1;
        }
 
-       kb= add_keyblock(key, name);
-
        if(newkey || from_mix==FALSE) {
                /* create from mesh */
+               kb= add_keyblock(key, name);
                mesh_to_key(me, kb);
        }
        else {
                /* copy from current values */
-               kb->data= do_ob_key(scene, ob);
+               float *data= do_ob_key(scene, ob);
+
+               /* create new block with prepared data */
+               kb= add_keyblock(key, name);
+               kb->data= data;
                kb->totelem= me->totvert;
        }
 
        return kb;
 }
 /************************* Lattice ************************/
-static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int from_mix)
 {
        Lattice *lt= ob->data;
        Key *key= lt->key;
@@ -2885,27 +2998,31 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_m
                newkey= 1;
        }
 
-       kb= add_keyblock(key, name);
-
        if(newkey || from_mix==FALSE) {
+               kb= add_keyblock(key, name);
+
                /* create from lattice */
                latt_to_key(lt, kb);
        }
        else {
                /* copy from current values */
+               float *data= do_ob_key(scene, ob);
+
+               /* create new block with prepared data */
+               kb= add_keyblock(key, name);
                kb->totelem= lt->pntsu*lt->pntsv*lt->pntsw;
-               kb->data= do_ob_key(scene, ob);
+               kb->data= data;
        }
 
        return kb;
 }
 /************************* Curve ************************/
-static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_mix)
+static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int from_mix)
 {
        Curve *cu= ob->data;
        Key *key= cu->key;
        KeyBlock *kb;
-       ListBase *lb= (cu->editnurb)? cu->editnurb: &cu->nurb;
+       ListBase *lb= BKE_curve_nurbs(cu);
        int newkey= 0;
 
        if(key==NULL) {
@@ -2914,22 +3031,29 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_
                newkey= 1;
        }
 
-       kb= add_keyblock(key, name);
-
        if(newkey || from_mix==FALSE) {
                /* create from curve */
-               curve_to_key(cu, kb, lb);
+               kb= add_keyblock(key, name);
+               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);
        }
        else {
                /* copy from current values */
+               float *data= do_ob_key(scene, ob);
+
+               /* create new block with prepared data */
+               kb= add_keyblock(key, name);
                kb->totelem= count_curveverts(lb);
-               kb->data= do_ob_key(scene, ob);
+               kb->data= data;
        }
 
        return kb;
 }
 
-KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, char *name, int from_mix)
+KeyBlock *object_insert_shape_key(Scene *scene, Object *ob, const char *name, int from_mix)
 {
        if(ob->type==OB_MESH)                                    return insert_meshkey(scene, ob, name, from_mix);
        else if ELEM(ob->type, OB_CURVE, OB_SURF)return insert_curvekey(scene, ob, name, from_mix);