doxygen: blender/blenkernel tagged.
[blender.git] / source / blender / blenkernel / intern / object.c
index 9512aa3a1cee63c157bd04178ce3d7878bf109e5..0b3d6dd4390039742b2bcd99ccaebd50d1ef7d0d 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/object.c
+ *  \ingroup bke
+ */
+
+
 #include <string.h>
 #include <math.h>
 #include <stdio.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"
@@ -245,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;
@@ -267,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++) {
@@ -275,12 +286,12 @@ 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->gpd) ((ID *)ob->gpd)->us--;
@@ -316,7 +327,7 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec
 
        if (*obpoin==unlinkOb) {
                *obpoin = NULL;
-               ob->recalc |= OB_RECALC_ALL; // XXX: should this just be OB_RECALC_DATA?
+               ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA?
        }
 }
 
@@ -357,7 +368,7 @@ void unlink_object(Object *ob)
                
                if(obt->parent==ob) {
                        obt->parent= NULL;
-                       obt->recalc |= OB_RECALC_ALL;
+                       obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                }
                
                modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob);
@@ -367,15 +378,15 @@ void unlink_object(Object *ob)
 
                        if(cu->bevobj==ob) {
                                cu->bevobj= NULL;
-                               obt->recalc |= OB_RECALC_ALL;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                        if(cu->taperobj==ob) {
                                cu->taperobj= NULL;
-                               obt->recalc |= OB_RECALC_ALL;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                        if(cu->textoncurve==ob) {
                                cu->textoncurve= NULL;
-                               obt->recalc |= OB_RECALC_ALL;
+                               obt->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        }
                }
                else if(obt->type==OB_ARMATURE && obt->pose) {
@@ -693,7 +704,7 @@ int exist_object(Object *obtest)
        return 0;
 }
 
-void *add_camera(char *name)
+void *add_camera(const char *name)
 {
        Camera *cam;
        
@@ -715,7 +726,6 @@ Camera *copy_camera(Camera *cam)
        Camera *camn;
        
        camn= copy_libblock(cam);
-       camn->adt= BKE_copy_animdata(cam->adt);
        
        return camn;
 }
@@ -734,11 +744,11 @@ 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;
        }
        
@@ -752,9 +762,9 @@ 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);
@@ -764,7 +774,7 @@ void make_local_camera(Camera *cam)
                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--;
@@ -795,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;
        
@@ -883,11 +893,11 @@ 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;
        }
        
@@ -901,9 +911,9 @@ 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);
@@ -913,7 +923,7 @@ void make_local_lamp(Lamp *la)
                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--;
@@ -970,7 +980,7 @@ 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";
@@ -990,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;
 
@@ -1008,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;
        
@@ -1019,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) {
@@ -1070,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);
@@ -1079,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_ALL;
+       ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
 
        return ob;
 }
@@ -1119,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;
@@ -1323,8 +1336,8 @@ Object *copy_object(Object *ob)
 
        /* increase user numbers */
        id_us_plus((ID *)obn->data);
+       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]);
        
@@ -1539,7 +1552,7 @@ 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_ALL;
+       ob->recalc= target->recalc= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
        
        /* copy transform
         * - gob means this proxy comes from a group, just apply the matrix
@@ -1598,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;
 }
@@ -1608,7 +1631,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob)
 
 /* there is also a timing calculation in drawobject() */
 
-int no_speed_curve= 0;
+static int no_speed_curve= 0;
 
 void disable_speed_curve(int val)
 {
@@ -1669,9 +1692,13 @@ 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 */
@@ -1682,14 +1709,23 @@ void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat)
 {
        switch(ob->rotmode) {
        case ROT_MODE_QUAT:
-               mat3_to_quat(ob->quat, mat);
+               {
+                       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);
+               }
                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);
        }
 }
 
@@ -1704,7 +1740,7 @@ void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const
                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);
@@ -1713,6 +1749,10 @@ void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const
                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 */
@@ -1740,6 +1780,7 @@ void object_to_mat4(Object *ob, float mat[][4])
        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])
@@ -1773,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);
        }
@@ -1811,8 +1857,8 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
 #else
                        quat_apply_track(quat, ob->trackflag, ob->upflag);
 #endif
-
-                       quat_to_mat4(mat,quat);                 
+                       normalize_qt(quat);
+                       quat_to_mat4(mat, quat);
                }
                
                if(cu->flag & CU_PATH_RADIUS) {
@@ -2056,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);
@@ -2227,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};
@@ -2527,48 +2573,64 @@ void object_handle_update(Scene *scene, Object *ob)
                        
                        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 = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL;
-                               
-                               /* 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(em) {
-                                       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) {
-                               /* 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;
@@ -2892,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;
@@ -2923,7 +2985,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, char *name, int from_m
        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;
@@ -2955,7 +3017,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, char *name, int from_m
        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;
@@ -2991,7 +3053,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_
        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);