Merging fluidcontrol to trunk from rev16649 fluidcontrol branch. Code provided by...
[blender-staging.git] / source / blender / blenkernel / intern / object.c
index 3ac4a572b960657484bf2e5eca2865dcbfe02c41..5d352c1e11db51f4aeb7a4cb61ab3383c838ee5c 100644 (file)
@@ -3,15 +3,12 @@
  * 
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,7 +26,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include <string.h>
@@ -53,6 +50,8 @@
 #include "DNA_lattice_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_curve_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_nla_types.h"
@@ -91,7 +90,6 @@
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
-#include "BKE_effect.h"
 #include "BKE_group.h"
 #include "BKE_icons.h"
 #include "BKE_ipo.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
 #include "BKE_particle.h"
+#include "BKE_pointcache.h"
 #include "BKE_property.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
 
 #include "BPY_extern.h"
 
+#include "GPU_material.h"
+
+#include "blendef.h"
+
 /* Local function protos */
 static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul);
 
@@ -157,6 +160,25 @@ void update_base_layer(Object *ob)
        }
 }
 
+void object_free_particlesystems(Object *ob)
+{
+       while(ob->particlesystem.first){
+               ParticleSystem *psys = ob->particlesystem.first;
+
+               BLI_remlink(&ob->particlesystem,psys);
+
+               psys_free(ob,psys);
+       }
+}
+
+void object_free_softbody(Object *ob)
+{
+       if(ob->soft) {
+               sbFree(ob->soft);
+               ob->soft= NULL;
+       }
+}
+
 void object_free_modifiers(Object *ob)
 {
        while (ob->modifiers.first) {
@@ -168,13 +190,10 @@ void object_free_modifiers(Object *ob)
        }
 
        /* particle modifiers were freed, so free the particlesystems as well */
-       while(ob->particlesystem.first){
-               ParticleSystem *psys = ob->particlesystem.first;
-
-               BLI_remlink(&ob->particlesystem,psys);
+       object_free_particlesystems(ob);
 
-               psys_free(ob,psys);
-       }
+       /* same for softbody */
+       object_free_softbody(ob);
 }
 
 /* here we will collect all local displist stuff */
@@ -229,11 +248,8 @@ void free_object(Object *ob)
        if(ob->dup_group) ob->dup_group->id.us--;
        if(ob->defbase.first)
                BLI_freelistN(&ob->defbase);
-       if(ob->pose) {
-               free_pose_channels(ob->pose);
-               MEM_freeN(ob->pose);
-       }
-       free_effects(&ob->effect);
+       if(ob->pose)
+               free_pose(ob->pose);
        free_properties(&ob->prop);
        object_free_modifiers(ob);
        
@@ -253,7 +269,7 @@ void free_object(Object *ob)
                MEM_freeN(ob->pd);
        }
        if(ob->soft) sbFree(ob->soft);
-       if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
+       if(ob->gpulamp.first) GPU_lamp_free(ob);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -279,6 +295,7 @@ void unlink_object(Object *ob)
        Camera *camera;
        bConstraint *con;
        bActionStrip *strip;
+       ModifierData *md;
        int a;
        
        unlink_controllers(&ob->controllers);
@@ -377,10 +394,13 @@ void unlink_object(Object *ob)
                
                /* object is deflector or field */
                if(ob->pd) {
-                       if(give_parteff(obt))
-                               obt->recalc |= OB_RECALC_DATA;
-                       else if(obt->soft)
+                       if(obt->soft)
                                obt->recalc |= OB_RECALC_DATA;
+
+                       /* cloth */
+                       for(md=obt->modifiers.first; md; md=md->next)
+                               if(md->type == eModifierType_Cloth)
+                                       obt->recalc |= OB_RECALC_DATA;
                }
                
                /* strips */
@@ -516,11 +536,11 @@ void unlink_object(Object *ob)
 
                                        if(v3d->camera==ob) {
                                                v3d->camera= NULL;
-                                               if(v3d->persp>1) v3d->persp= 1;
+                                               if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
                                        }
                                        if(v3d->localvd && v3d->localvd->camera==ob ) {
                                                v3d->localvd->camera= NULL;
-                                               if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
+                                               if(v3d->localvd->persp==V3D_CAMOB) v3d->localvd->persp= V3D_PERSP;
                                        }
                                }
                                else if(sl->spacetype==SPACE_IPO) {
@@ -676,9 +696,11 @@ float dof_camera(Object *ob)
        if (cam->dof_ob) {      
                /* too simple, better to return the distance on the view axis only
                 * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */
+               float mat[4][4], obmat[4][4];
                
-               float mat[4][4];
-               Mat4Invert(ob->imat, ob->obmat);
+               Mat4CpyMat4(obmat, ob->obmat);
+               Mat4Ortho(obmat);
+               Mat4Invert(ob->imat, obmat);
                Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat);
                return fabs(mat[3][2]);
        }
@@ -714,6 +736,20 @@ void *add_lamp(char *name)
        la->preview=NULL;
        la->falloff_type = LA_FALLOFF_INVLINEAR;
        la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f);
+       la->sun_effect_type = 0;
+       la->horizon_brightness = 1.0;
+       la->spread = 1.0;
+       la->sun_brightness = 1.0;
+       la->sun_size = 1.0;
+       la->backscattered_light = 1.0;
+       la->atm_turbidity = 2.0;
+       la->atm_inscattering_factor = 1.0;
+       la->atm_extinction_factor = 1.0;
+       la->atm_distance_factor = 1.0;
+       la->sun_intensity = 1.0;
+       la->skyblendtype= MA_RAMP_ADD;
+       la->skyblendfac= 1.0f;
+
        curvemapping_initialize(la->curfalloff);
        return la;
 }
@@ -884,10 +920,12 @@ Object *add_only_object(int type, char *name)
        ob->type= type;
        /* ob->transflag= OB_QUAT; */
 
+#if 0 /* not used yet */
        QuatOne(ob->quat);
        QuatOne(ob->dquat);
+#endif 
 
-       ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+       ob->col[0]= ob->col[1]= ob->col[2]= 1.0;
        ob->col[3]= 1.0;
 
        ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
@@ -924,7 +962,8 @@ Object *add_only_object(int type, char *name)
        ob->anisotropicFriction[0] = 1.0f;
        ob->anisotropicFriction[1] = 1.0f;
        ob->anisotropicFriction[2] = 1.0f;
-       ob->gameflag= OB_PROP;
+       ob->gameflag= OB_PROP|OB_COLLISION;
+       ob->margin = 0.0;
 
        /* NT fluid sim defaults */
        ob->fluidsimFlag = 0;
@@ -976,11 +1015,13 @@ void base_init_from_view3d(Base *base, View3D *v3d)
 
        if (U.flag & USER_ADD_VIEWALIGNED) {
                v3d->viewquat[0]= -v3d->viewquat[0];
-               if (ob->transflag & OB_QUAT) {
+
+               /* Quats arnt used yet */
+               /*if (ob->transflag & OB_QUAT) {
                        QUATCOPY(ob->quat, v3d->viewquat);
-               } else {
+               } else {*/
                        QuatToEul(v3d->viewquat, ob->rot);
-               }
+               /*}*/
                v3d->viewquat[0]= -v3d->viewquat[0];
        }
 }
@@ -995,12 +1036,14 @@ SoftBody *copy_softbody(SoftBody *sb)
        sbn->totspring= sbn->totpoint= 0;
        sbn->bpoint= NULL;
        sbn->bspring= NULL;
-       sbn->ctime= 0.0f;
        
        sbn->keys= NULL;
        sbn->totkey= sbn->totpointkey= 0;
        
        sbn->scratch= NULL;
+
+       sbn->pointcache= BKE_ptcache_copy(sb->pointcache);
+
        return sbn;
 }
 
@@ -1021,23 +1064,63 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
                        pa->keys= MEM_dupallocN(pa->keys);
        }
 
-       if(psys->soft)
+       if(psys->soft) {
                psysn->soft= copy_softbody(psys->soft);
+               psysn->soft->particles = psysn;
+       }
        
        psysn->pathcache= NULL;
        psysn->childcache= NULL;
        psysn->edit= NULL;
        psysn->effectors.first= psysn->effectors.last= 0;
+       
+       psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
+       psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
+       psysn->reactevents.first = psysn->reactevents.last = NULL;
+       psysn->renderdata = NULL;
+       
+       psysn->pointcache= BKE_ptcache_copy(psys->pointcache);
 
        id_us_plus((ID *)psysn->part);
 
        return psysn;
 }
 
+void copy_object_particlesystems(Object *obn, Object *ob)
+{
+       ParticleSystemModifierData *psmd;
+       ParticleSystem *psys, *npsys;
+       ModifierData *md;
+
+       obn->particlesystem.first= obn->particlesystem.last= NULL;
+       for(psys=ob->particlesystem.first; psys; psys=psys->next) {
+               npsys= copy_particlesystem(psys);
+
+               BLI_addtail(&obn->particlesystem, npsys);
+
+               /* need to update particle modifiers too */
+               for(md=obn->modifiers.first; md; md=md->next) {
+                       if(md->type==eModifierType_ParticleSystem) {
+                               psmd= (ParticleSystemModifierData*)md;
+                               if(psmd->psys==psys)
+                                       psmd->psys= npsys;
+                       }
+               }
+       }
+}
+
+void copy_object_softbody(Object *obn, Object *ob)
+{
+       if(ob->soft)
+               obn->soft= copy_softbody(ob->soft);
+}
+
 static void copy_object_pose(Object *obn, Object *ob)
 {
        bPoseChannel *chan;
        
+       /* note: need to clear obn->pose pointer first, so that copy_pose works (otherwise there's a crash) */
+       obn->pose= NULL;
        copy_pose(&obn->pose, ob->pose, 1);     /* 1 = copy constraints */
 
        for (chan = obn->pose->chanbase.first; chan; chan=chan->next){
@@ -1077,7 +1160,6 @@ Object *copy_object(Object *ob)
 {
        Object *obn;
        ModifierData *md;
-       ParticleSystem *psys;
        int a;
 
        obn= copy_libblock(ob);
@@ -1090,7 +1172,6 @@ Object *copy_object(Object *ob)
        obn->path= NULL;
        obn->flag &= ~OB_FROMGROUP;
        
-       copy_effects(&obn->effect, &ob->effect);
        obn->modifiers.first = obn->modifiers.last= NULL;
        
        for (md=ob->modifiers.first; md; md=md->next) {
@@ -1135,31 +1216,7 @@ Object *copy_object(Object *ob)
        }
        obn->soft= copy_softbody(ob->soft);
 
-       /* NT copy fluid sim setting memory */
-       if(obn->fluidsimSettings) {
-               obn->fluidsimSettings = fluidsimSettingsCopy(ob->fluidsimSettings);
-               /* copying might fail... */
-               if(obn->fluidsimSettings) {
-                       obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
-               }
-       }
-
-       obn->particlesystem.first= obn->particlesystem.last= NULL;
-       for(psys=ob->particlesystem.first; psys; psys=psys->next) {
-               ParticleSystemModifierData *psmd;
-               ParticleSystem *npsys= copy_particlesystem(psys);
-
-               BLI_addtail(&obn->particlesystem, npsys);
-
-               /* need to update particle modifiers too */
-               for(md=obn->modifiers.first; md; md=md->next) {
-                       if(md->type==eModifierType_ParticleSystem) {
-                               psmd= (ParticleSystemModifierData*)md;
-                               if(psmd->psys==psys)
-                                       psmd->psys= npsys;
-                       }
-               }
-       }
+       copy_object_particlesystems(obn, ob);
        
        obn->derivedDeform = NULL;
        obn->derivedFinal = NULL;
@@ -1168,6 +1225,7 @@ Object *copy_object(Object *ob)
        obn->vnode = NULL;
 #endif
 
+       obn->gpulamp.first = obn->gpulamp.last = NULL;
 
        return obn;
 }
@@ -1175,11 +1233,13 @@ Object *copy_object(Object *ob)
 void expand_local_object(Object *ob)
 {
        bActionStrip *strip;
+       ParticleSystem *psys;
        int a;
        
        id_lib_extern((ID *)ob->action);
        id_lib_extern((ID *)ob->ipo);
        id_lib_extern((ID *)ob->data);
+       id_lib_extern((ID *)ob->dup_group);
        
        for(a=0; a<ob->totcol; a++) {
                id_lib_extern((ID *)ob->mat[a]);
@@ -1187,7 +1247,8 @@ void expand_local_object(Object *ob)
        for (strip=ob->nlastrips.first; strip; strip=strip->next) {
                id_lib_extern((ID *)strip->act);
        }
-
+       for(psys=ob->particlesystem.first; psys; psys=psys->next)
+               id_lib_extern((ID *)psys->part);
 }
 
 void make_local_object(Object *ob)
@@ -1311,11 +1372,29 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
        
        /* skip constraints, constraintchannels, nla? */
        
-       
+       /* set object type and link to data */
        ob->type= target->type;
        ob->data= target->data;
        id_us_plus((ID *)ob->data);             /* ensures lib data becomes LIB_EXTERN */
        
+       /* copy material and index information */
+       ob->actcol= ob->totcol= 0;
+       if(ob->mat) MEM_freeN(ob->mat);
+       ob->mat = NULL;
+       if ((target->totcol) && (target->mat) && OB_SUPPORT_MATERIAL(ob)) {
+               int i;
+               ob->colbits = target->colbits;
+               
+               ob->actcol= target->actcol;
+               ob->totcol= target->totcol;
+               
+               ob->mat = MEM_dupallocN(target->mat);
+               for(i=0; i<target->totcol; i++) {
+                       /* dont need to run test_object_materials since we know this object is new and not used elsewhere */
+                       id_us_plus((ID *)ob->mat[i]); 
+               }
+       }
+       
        /* type conversions */
        if(target->type == OB_ARMATURE) {
                copy_object_pose(ob, target);   /* data copy, object pointers in constraints */
@@ -1362,12 +1441,12 @@ float bsystem_time(Object *ob, float cfra, float ofs)
        cfra*= G.scene->r.framelen;     
        
        if (ob) {
-               if (no_speed_curve==0 && ob->ipo) 
+               if (no_speed_curve==0 && ob->ipo)
                        cfra= calc_ipo_time(ob->ipo, cfra);
                
                /* ofset frames */
                if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) 
-                       cfra-= ob->sf;
+                       cfra-= give_timeoffset(ob);
        }
        
        cfra-= ofs;
@@ -1379,7 +1458,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
 {
        float smat[3][3], vec[3];
        float rmat[3][3];
-       float q1[4];
+       /*float q1[4];*/
        
        /* size */
        if(ob->ipo) {
@@ -1393,7 +1472,8 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
        }
 
        /* rot */
-       if(ob->transflag & OB_QUAT) {
+       /* Quats arnt used yet */
+       /*if(ob->transflag & OB_QUAT) {
                if(ob->ipo) {
                        QuatMul(q1, ob->quat, ob->dquat);
                        QuatToMat3(q1, rmat);
@@ -1402,7 +1482,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
                        QuatToMat3(ob->quat, rmat);
                }
        }
-       else {
+       else {*/
                if(ob->ipo) {
                        vec[0]= ob->rot[0]+ob->drot[0];
                        vec[1]= ob->rot[1]+ob->drot[1];
@@ -1412,7 +1492,7 @@ void object_to_mat3(Object *ob, float mat[][3])   /* no parent */
                else {
                        EulToMat3(ob->rot, rmat);
                }
-       }
+       /*}*/
        Mat3MulMat3(mat, rmat, smat);
 }
 
@@ -1437,8 +1517,8 @@ int enable_cu_speed= 1;
 static void ob_parcurve(Object *ob, Object *par, float mat[][4])
 {
        Curve *cu;
-       float q[4], vec[4], dir[3], *quat, x1, ctime;
-       float timeoffs= 0.0;
+       float q[4], vec[4], dir[3], quat[4], x1, ctime;
+       float timeoffs = 0.0, sf_orig = 0.0;
        
        Mat4One(mat);
        
@@ -1449,7 +1529,8 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
        
        /* exception, timeoffset is regarded as distance offset */
        if(cu->flag & CU_OFFS_PATHDIST) {
-               SWAP(float, timeoffs, ob->sf);
+               timeoffs = give_timeoffset(ob);
+               SWAP(float, sf_orig, ob->sf);
        }
        
        /* catch exceptions: feature for nla stride editing */
@@ -1466,7 +1547,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
                }
        }
        else {
-               ctime= G.scene->r.cfra - ob->sf;
+               ctime= G.scene->r.cfra - give_timeoffset(ob);
                ctime /= cu->pathlen;
                
                CLAMP(ctime, 0.0, 1.0);
@@ -1477,7 +1558,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
                ctime += timeoffs/cu->path->totdist;
 
                /* restore */
-               SWAP(float, timeoffs, ob->sf);
+               SWAP(float, sf_orig, ob->sf);
        }
        
        
@@ -1485,7 +1566,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4])
        if( where_on_path(par, ctime, vec, dir) ) {
 
                if(cu->flag & CU_FOLLOW) {
-                       quat= vectoquat(dir, ob->trackflag, ob->upflag);
+                       vectoquat(dir, ob->trackflag, ob->upflag, quat);
                        
                        /* the tilt */
                        Normalize(dir);
@@ -1546,7 +1627,7 @@ static void give_parvert(Object *par, int nr, float *vec)
                        
                        for(eve= em->verts.first; eve; eve= eve->next) {
                                if(eve->keyindex==nr) {
-                                       memcpy(vec, eve->co, 12);
+                                       memcpy(vec, eve->co, sizeof(float)*3);
                                        break;
                                }
                        }
@@ -1568,9 +1649,12 @@ static void give_parvert(Object *par, int nr, float *vec)
                                        }
                                }
 
-                               if(count > 0) {
+                               if (count==0) {
+                                       /* keep as 0,0,0 */
+                               } else if(count > 0) {
                                        VecMulf(vec, 1.0f / count);
                                } else {
+                                       /* use first index if its out of range */
                                        dm->getVertCo(dm, 0, vec);
                                }
                        }
@@ -1581,18 +1665,20 @@ static void give_parvert(Object *par, int nr, float *vec)
                Curve *cu;
                BPoint *bp;
                BezTriple *bezt;
+               int found= 0;
                
                cu= par->data;
                nu= cu->nurb.first;
                if(par==G.obedit) nu= editNurb.first;
                
                count= 0;
-               while(nu) {
+               while(nu && !found) {
                        if((nu->type & 7)==CU_BEZIER) {
                                bezt= nu->bezt;
                                a= nu->pntsu;
                                while(a--) {
                                        if(count==nr) {
+                                               found= 1;
                                                VECCOPY(vec, bezt->vec[1]);
                                                break;
                                        }
@@ -1605,7 +1691,8 @@ static void give_parvert(Object *par, int nr, float *vec)
                                a= nu->pntsu*nu->pntsv;
                                while(a--) {
                                        if(count==nr) {
-                                               memcpy(vec, bp->vec, 12);
+                                               found= 1;
+                                               memcpy(vec, bp->vec, sizeof(float)*3);
                                                break;
                                        }
                                        count++;
@@ -1735,7 +1822,7 @@ void where_is_object_time(Object *ob, float ctime)
        if(ob->parent) {
                Object *par= ob->parent;
                
-               if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf;
+               if(ob->ipoflag & OB_OFFS_PARENT) ctime-= give_timeoffset(ob);
                
                /* hurms, code below conflicts with depgraph... (ton) */
                /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */
@@ -1759,7 +1846,7 @@ void where_is_object_time(Object *ob, float ctime)
                if(ob->partype & PARSLOW) {
                        // include framerate
 
-                       fac1= (1.0f/(1.0f+ fabs(ob->sf)));
+                       fac1= (1.0f/(1.0f+ fabs(give_timeoffset(ob))));
                        if(fac1>=1.0) return;
                        fac2= 1.0f-fac1;
                        
@@ -1885,13 +1972,13 @@ static void solve_parenting (Object *ob, Object *par, float obmat[][4], float sl
 }
 void solve_tracking (Object *ob, float targetmat[][4])
 {
-       float *quat;
+       float quat[4];
        float vec[3];
        float totmat[3][3];
        float tmat[4][4];
        
        VecSubf(vec, ob->obmat[3], targetmat[3]);
-       quat= vectoquat(vec, ob->trackflag, ob->upflag);
+       vectoquat(vec, ob->trackflag, ob->upflag, quat);
        QuatToMat3(quat, totmat);
        
        if(ob->parent && (ob->transflag & OB_POWERTRACK)) {
@@ -1942,7 +2029,7 @@ for a lamp that is the child of another object */
 
                if(ob->partype & PARSLOW) {
 
-                       fac1= (float)(1.0/(1.0+ fabs(ob->sf)));
+                       fac1= (float)(1.0/(1.0+ fabs(give_timeoffset(ob))));
                        fac2= 1.0f-fac1;
                        fp1= ob->obmat[0];
                        fp2= slowmat[0];
@@ -2147,7 +2234,7 @@ void object_handle_update(Object *ob)
        if(ob->recalc & OB_RECALC) {
                
                if(ob->recalc & OB_RECALC_OB) {
-                       
+
                        // printf("recalcob %s\n", ob->id.name+2);
                        
                        /* handle proxy copy for target */
@@ -2163,6 +2250,7 @@ void object_handle_update(Object *ob)
                        }
                        else
                                where_is_object(ob);
+                       if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBJECTUPDATE);
                }
                
                if(ob->recalc & OB_RECALC_DATA) {
@@ -2182,6 +2270,16 @@ void object_handle_update(Object *ob)
                        else if(ob->type==OB_LATTICE) {
                                lattice_calc_modifiers(ob);
                        }
+                       else if(ob->type==OB_CAMERA) {
+                               Camera *cam = (Camera *)ob->data;
+                               calc_ipo(cam->ipo, frame_to_float(G.scene->r.cfra));
+                               execute_ipo(&cam->id, cam->ipo);
+                       }
+                       else if(ob->type==OB_LAMP) {
+                               Lamp *la = (Lamp *)ob->data;
+                               calc_ipo(la->ipo, frame_to_float(G.scene->r.cfra));
+                               execute_ipo(&la->id, la->ipo);
+                       }
                        else if(ob->type==OB_ARMATURE) {
                                /* this happens for reading old files and to match library armatures with poses */
                                if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
@@ -2228,6 +2326,7 @@ void object_handle_update(Object *ob)
                                                psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
                                }
                        }
+                       if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBDATAUPDATE);
                }
 
                /* the no-group proxy case, we call update */
@@ -2247,3 +2346,78 @@ void object_handle_update(Object *ob)
                // printf("set proxy pointer for later group stuff %s\n", ob->id.name);
        }
 }
+
+float give_timeoffset(Object *ob) {
+       if ((ob->ipoflag & OB_OFFS_PARENTADD) && ob->parent) {
+               return ob->sf + give_timeoffset(ob->parent);
+       } else {
+               return ob->sf;
+       }
+}
+
+int give_obdata_texspace(Object *ob, int **texflag, float **loc, float **size, float **rot) {
+       
+       if (ob->data==NULL)
+               return 0;
+       
+       switch (GS(((ID *)ob->data)->name)) {
+       case ID_ME:
+       {
+               Mesh *me= ob->data;
+               if (texflag)    *texflag = &me->texflag;
+               if (loc)                *loc = me->loc;
+               if (size)               *size = me->size;
+               if (rot)                *rot = me->rot;
+               break;
+       }
+       case ID_CU:
+       {
+               Curve *cu= ob->data;
+               if (texflag)    *texflag = &cu->texflag;
+               if (loc)                *loc = cu->loc;
+               if (size)               *size = cu->size;
+               if (rot)                *rot = cu->rot;
+               break;
+       }
+       case ID_MB:
+       {
+               MetaBall *mb= ob->data;
+               if (texflag)    *texflag = &mb->texflag;
+               if (loc)                *loc = mb->loc;
+               if (size)               *size = mb->size;
+               if (rot)                *rot = mb->rot;
+               break;
+       }
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Test a bounding box for ray intersection
+ * assumes the ray is already local to the boundbox space
+ */
+int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3])
+{
+       static int triangle_indexes[12][3] = {{0, 1, 2}, {0, 2, 3},
+                                                                                 {3, 2, 6}, {3, 6, 7},
+                                                                                 {1, 2, 6}, {1, 6, 5}, 
+                                                                                 {5, 6, 7}, {4, 5, 7},
+                                                                                 {0, 3, 7}, {0, 4, 7},
+                                                                                 {0, 1, 5}, {0, 4, 5}};
+       int result = 0;
+       int i;
+       
+       for (i = 0; i < 12 && result == 0; i++)
+       {
+               float lambda;
+               int v1, v2, v3;
+               v1 = triangle_indexes[i][0];
+               v2 = triangle_indexes[i][1];
+               v3 = triangle_indexes[i][2];
+               result = RayIntersectsTriangle(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL);
+       }
+       
+       return result;
+}