Fix for two proxy + undo related crashes:
[blender.git] / source / blender / blenkernel / intern / object.c
index a2780de9702d1bb9d5e37af207f9b78eaaec1783..a25afeafaef5fb3edd115b3ff865439c82d6cecb 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>
@@ -73,6 +70,7 @@
 
 #include "BKE_armature.h"
 #include "BKE_action.h"
+#include "BKE_bullet.h"
 #include "BKE_colortools.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
@@ -93,7 +91,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 "LBM_fluidsim.h"
 
+#ifndef DISABLE_PYTHON
 #include "BPY_extern.h"
+#endif
+
+#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);
@@ -179,6 +182,14 @@ void object_free_softbody(Object *ob)
        }
 }
 
+void object_free_bulletsoftbody(Object *ob)
+{
+       if(ob->bsoft) {
+               bsbFree(ob->bsoft);
+               ob->bsoft= NULL;
+       }
+}
+
 void object_free_modifiers(Object *ob)
 {
        while (ob->modifiers.first) {
@@ -250,7 +261,6 @@ void free_object(Object *ob)
                BLI_freelistN(&ob->defbase);
        if(ob->pose)
                free_pose(ob->pose);
-       free_effects(&ob->effect);
        free_properties(&ob->prop);
        object_free_modifiers(ob);
        
@@ -261,8 +271,10 @@ void free_object(Object *ob)
        free_constraints(&ob->constraints);
        free_constraint_channels(&ob->constraintChannels);
        free_nlastrips(&ob->nlastrips);
-       
+
+#ifndef DISABLE_PYTHON 
        BPY_free_scriptlink(&ob->scriptlink);
+#endif
        
        if(ob->pd){
                if(ob->pd->tex)
@@ -270,7 +282,8 @@ void free_object(Object *ob)
                MEM_freeN(ob->pd);
        }
        if(ob->soft) sbFree(ob->soft);
-       if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
+       if(ob->bsoft) bsbFree(ob->bsoft);
+       if(ob->gpulamp.first) GPU_lamp_free(ob);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -395,9 +408,7 @@ 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 */
@@ -630,9 +641,9 @@ Camera *copy_camera(Camera *cam)
        
        camn= copy_libblock(cam);
        id_us_plus((ID *)camn->ipo);
-
+#ifndef DISABLE_PYTHON
        BPY_copy_scriptlink(&camn->scriptlink);
-       
+#endif 
        return camn;
 }
 
@@ -699,9 +710,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]);
        }
@@ -737,6 +750,22 @@ 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;
+       la->sky_colorspace= BLI_CS_CIE;
+       la->sky_exposure= 1.0f;
+       
        curvemapping_initialize(la->curfalloff);
        return la;
 }
@@ -761,9 +790,9 @@ Lamp *copy_lamp(Lamp *la)
        id_us_plus((ID *)lan->ipo);
 
        if (la->preview) lan->preview = BKE_previewimg_copy(la->preview);
-
+#ifndef DISABLE_PYTHON
        BPY_copy_scriptlink(&la->scriptlink);
-       
+#endif
        return lan;
 }
 
@@ -821,7 +850,9 @@ void make_local_lamp(Lamp *la)
 
 void free_camera(Camera *ca)
 {
+#ifndef DISABLE_PYTHON
        BPY_free_scriptlink(&ca->scriptlink);
+#endif
 }
 
 void free_lamp(Lamp *la)
@@ -830,8 +861,9 @@ void free_lamp(Lamp *la)
        int a;
 
        /* scriptlinks */
-               
+#ifndef DISABLE_PYTHON
        BPY_free_scriptlink(&la->scriptlink);
+#endif
 
        for(a=0; a<MAX_MTEX; a++) {
                mtex= la->mtex[a];
@@ -907,10 +939,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;
@@ -947,8 +981,9 @@ 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;
        ob->fluidsimSettings = NULL;
@@ -999,11 +1034,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];
        }
 }
@@ -1029,6 +1066,17 @@ SoftBody *copy_softbody(SoftBody *sb)
        return sbn;
 }
 
+BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
+{
+       BulletSoftBody *bsbn;
+
+       if (bsb == NULL)
+               return NULL;
+       bsbn = MEM_dupallocN(bsb);
+       /* no pointer in this structure yet */
+       return bsbn;
+}
+
 ParticleSystem *copy_particlesystem(ParticleSystem *psys)
 {
        ParticleSystem *psysn;
@@ -1055,7 +1103,12 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
        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);
@@ -1096,6 +1149,8 @@ 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){
@@ -1108,7 +1163,10 @@ static void copy_object_pose(Object *obn, Object *ob)
                        ListBase targets = {NULL, NULL};
                        bConstraintTarget *ct;
                        
-                       if(con->ipo) {
+                       /* note that we can't change lib linked ipo blocks. for making
+                        * proxies this still works correct however because the object
+                        * is changed to object->proxy_from when evaluating the driver. */
+                       if(con->ipo && !con->ipo->id.lib) {
                                IpoCurve *icu;
                                for(icu= con->ipo->curve.first; icu; icu= icu->next) {
                                        if(icu->driver && icu->driver->ob==ob)
@@ -1147,7 +1205,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) {
@@ -1155,10 +1212,12 @@ Object *copy_object(Object *ob)
                modifier_copyData(md, nmd);
                BLI_addtail(&obn->modifiers, nmd);
        }
-       
+#ifndef DISABLE_PYTHON 
        BPY_copy_scriptlink(&ob->scriptlink);
-       
+#endif
+       obn->prop.first = obn->prop.last = NULL;
        copy_properties(&obn->prop, &ob->prop);
+       
        copy_sensors(&obn->sensors, &ob->sensors);
        copy_controllers(&obn->controllers, &ob->controllers);
        copy_actuators(&obn->actuators, &ob->actuators);
@@ -1191,15 +1250,7 @@ Object *copy_object(Object *ob)
                        id_us_plus(&(obn->pd->tex->id));
        }
        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->bsoft = copy_bulletsoftbody(ob->bsoft);
 
        copy_object_particlesystems(obn, ob);
        
@@ -1210,6 +1261,7 @@ Object *copy_object(Object *ob)
        obn->vnode = NULL;
 #endif
 
+       obn->gpulamp.first = obn->gpulamp.last = NULL;
 
        return obn;
 }
@@ -1217,6 +1269,7 @@ Object *copy_object(Object *ob)
 void expand_local_object(Object *ob)
 {
        bActionStrip *strip;
+       ParticleSystem *psys;
        int a;
        
        id_lib_extern((ID *)ob->action);
@@ -1230,7 +1283,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)
@@ -1354,11 +1408,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 */
@@ -1405,7 +1477,7 @@ 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 */
@@ -1418,25 +1490,46 @@ float bsystem_time(Object *ob, float cfra, float ofs)
        return cfra;
 }
 
-void object_to_mat3(Object *ob, float mat[][3])        /* no parent */
+void object_scale_to_mat3(Object *ob, float mat[][3])
 {
-       float smat[3][3], vec[3];
-       float rmat[3][3];
-       float q1[4];
-       
-       /* size */
+       float vec[3];
        if(ob->ipo) {
                vec[0]= ob->size[0]+ob->dsize[0];
                vec[1]= ob->size[1]+ob->dsize[1];
                vec[2]= ob->size[2]+ob->dsize[2];
-               SizeToMat3(vec, smat);
+               SizeToMat3(vec, mat);
+       }
+       else {
+               SizeToMat3(ob->size, mat);
+       }
+}
+
+void object_rot_to_mat3(Object *ob, float mat[][3])
+{
+       float vec[3];
+       if(ob->ipo) {
+               vec[0]= ob->rot[0]+ob->drot[0];
+               vec[1]= ob->rot[1]+ob->drot[1];
+               vec[2]= ob->rot[2]+ob->drot[2];
+               EulToMat3(vec, mat);
        }
        else {
-               SizeToMat3(ob->size, smat);
+               EulToMat3(ob->rot, mat);
        }
+}
+
+void object_to_mat3(Object *ob, float mat[][3])        /* no parent */
+{
+       float smat[3][3];
+       float rmat[3][3];
+       /*float q1[4];*/
+       
+       /* size */
+       object_scale_to_mat3(ob, smat);
 
        /* 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);
@@ -1445,17 +1538,9 @@ void object_to_mat3(Object *ob, float mat[][3])  /* no parent */
                        QuatToMat3(ob->quat, rmat);
                }
        }
-       else {
-               if(ob->ipo) {
-                       vec[0]= ob->rot[0]+ob->drot[0];
-                       vec[1]= ob->rot[1]+ob->drot[1];
-                       vec[2]= ob->rot[2]+ob->drot[2];
-                       EulToMat3(vec, rmat);
-               }
-               else {
-                       EulToMat3(ob->rot, rmat);
-               }
-       }
+       else {*/
+               object_rot_to_mat3(ob, rmat);
+       /*}*/
        Mat3MulMat3(mat, rmat, smat);
 }
 
@@ -1590,7 +1675,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;
                                }
                        }
@@ -1612,9 +1697,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);
                                }
                        }
@@ -1625,18 +1713,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;
                                        }
@@ -1649,7 +1739,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++;
@@ -1837,10 +1928,11 @@ void where_is_object_time(Object *ob, float ctime)
                
                constraints_clear_evalob(cob);
        }
-       
+#ifndef DISABLE_PYTHON
        if(ob->scriptlink.totscript && !during_script()) {
                if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_REDRAW);
        }
+#endif
        
        /* set negative scale flag in object */
        Crossf(vec, ob->obmat[0], ob->obmat[1]);
@@ -2207,7 +2299,9 @@ void object_handle_update(Object *ob)
                        }
                        else
                                where_is_object(ob);
+#ifndef DISABLE_PYTHON
                        if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBJECTUPDATE);
+#endif
                }
                
                if(ob->recalc & OB_RECALC_DATA) {
@@ -2227,6 +2321,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))
@@ -2273,7 +2377,9 @@ void object_handle_update(Object *ob)
                                                psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
                                }
                        }
+#ifndef DISABLE_PYTHON
                        if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBDATAUPDATE);
+#endif
                }
 
                /* the no-group proxy case, we call update */
@@ -2340,3 +2446,31 @@ int give_obdata_texspace(Object *ob, int **texflag, float **loc, float **size, f
        }
        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;
+}