Shape Keys
[blender-staging.git] / source / blender / blenkernel / intern / modifier.c
index c64c48b9ce74e5a63991d2d82b55835804966649..a445b6986f622e876a76a32c451f539f0e6b47ba 100644 (file)
@@ -34,6 +34,7 @@
 *
 */
 
+#include "stddef.h"
 #include "string.h"
 #include "stdarg.h"
 #include "math.h"
@@ -59,6 +60,7 @@
 #include "DNA_curve_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_group_types.h"
+#include "DNA_key_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -91,6 +93,7 @@
 #include "BKE_fluidsim.h"
 #include "BKE_global.h"
 #include "BKE_multires.h"
+#include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_material.h"
@@ -1186,9 +1189,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
 
        /* need to avoid infinite recursion here */
        if(amd->start_cap && amd->start_cap != ob)
-               start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
+               start_cap = amd->start_cap->derivedFinal;
        if(amd->end_cap && amd->end_cap != ob)
-               end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
+               end_cap = amd->end_cap->derivedFinal;
 
        Mat4One(offset);
 
@@ -5971,6 +5974,8 @@ static void clothModifier_copyData(ModifierData *md, ModifierData *target)
        tclmd->point_cache = NULL;
        
        tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
+       if(clmd->sim_parms->effector_weights)
+               tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
        tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
        tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches);
        tclmd->clothObject = NULL;
@@ -5992,8 +5997,11 @@ static void clothModifier_freeData(ModifierData *md)
                
                cloth_free_modifier_extern (clmd);
                
-               if(clmd->sim_parms)
+               if(clmd->sim_parms) {
+                       if(clmd->sim_parms->effector_weights)
+                               MEM_freeN(clmd->sim_parms->effector_weights);
                        MEM_freeN(clmd->sim_parms);
+               }
                if(clmd->coll_parms)
                        MEM_freeN(clmd->coll_parms);    
                
@@ -6206,7 +6214,8 @@ static void surfaceModifier_freeData(ModifierData *md)
                        MEM_freeN(surmd->bvhtree);
                }
 
-               surmd->dm->release(surmd->dm);
+               if(surmd->dm)
+                       surmd->dm->release(surmd->dm);
 
                if(surmd->x)
                        MEM_freeN(surmd->x);
@@ -6293,7 +6302,10 @@ static void surfaceModifier_deformVerts(
                else
                        surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
 
-               bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+               if(surmd->dm->getNumFaces(surmd->dm))
+                       bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
+               else
+                       bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
        }
 }
 
@@ -6346,7 +6358,7 @@ static DerivedMesh *booleanModifier_applyModifier(
 {
        // XXX doesn't handle derived data
        BooleanModifierData *bmd = (BooleanModifierData*) md;
-       DerivedMesh *dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_BAREMESH);
+       DerivedMesh *dm = bmd->object->derivedFinal;
 
        /* we do a quick sanity check */
        if(dm && (derivedData->getNumFaces(derivedData) > 3)
@@ -6601,6 +6613,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
 {
        DerivedMesh *dm = derivedData, *result;
        ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+       ParticleSimulationData sim;
        ParticleSystem * psys=0;
        ParticleData *pa=0, *pars=0;
        MFace *mface, *orig_mface;
@@ -6635,6 +6648,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
        if(totpart==0)
                return derivedData;
 
+       sim.scene = md->scene;
+       sim.ob = pimd->ob;
+       sim.psys = psys;
+       sim.psmd = psys_get_modifier(pimd->ob, psys);
+
        if(pimd->flag & eParticleInstanceFlag_UseSize) {
                int p;
                float *si;
@@ -6662,7 +6680,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
        maxvert=totvert*totpart;
        maxface=totface*totpart;
 
-       psys->lattice=psys_get_lattice(md->scene, ob, psys);
+       psys->lattice=psys_get_lattice(&sim);
 
        if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
 
@@ -6712,7 +6730,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
                                mv->co[axis] = 0.0;
                        }
 
-                       psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1);
+                       psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
 
                        Normalize(state.vel);
                        
@@ -6734,7 +6752,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
                }
                else{
                        state.time=-1.0;
-                       psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1);
+                       psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
                }       
 
                QuatMulVecf(state.rot,mv->co);
@@ -7416,6 +7434,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
        DerivedMesh *explode, *dm=to_explode;
        MFace *mf=0;
        ParticleSettings *part=psmd->psys->part;
+       ParticleSimulationData sim = {scene, ob, psmd->psys, psmd};
        ParticleData *pa=NULL, *pars=psmd->psys->particles;
        ParticleKey state;
        EdgeHash *vertpahash;
@@ -7431,7 +7450,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
        totvert= dm->getNumVerts(dm);
        totpart= psmd->psys->totpart;
 
-       timestep= psys_get_timestep(part);
+       timestep= psys_get_timestep(&sim);
 
        //if(part->flag & PART_GLOB_TIME)
                cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0);
@@ -7474,7 +7493,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
        /* getting back to object space */
        Mat4Invert(imat,ob->obmat);
 
-       psmd->psys->lattice = psys_get_lattice(scene, ob, psmd->psys);
+       psmd->psys->lattice = psys_get_lattice(&sim);
 
        /* duplicate & displace vertices */
        ehi= BLI_edgehashIterator_new(vertpahash);
@@ -7502,7 +7521,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
                        Mat4MulVecfl(ob->obmat,loc0);
 
                        state.time=cfra;
-                       psys_get_particle_state(scene, ob, psmd->psys, i, &state,1);
+                       psys_get_particle_state(&sim, i, &state, 1);
 
                        vertco=CDDM_get_vert(explode,v)->co;
                        
@@ -7591,7 +7610,7 @@ static DerivedMesh * explodeModifier_applyModifier(
 {
        DerivedMesh *dm = derivedData;
        ExplodeModifierData *emd= (ExplodeModifierData*) md;
-       ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);;
+       ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);
 
        if(psmd){
                ParticleSystem * psys=psmd->psys;
@@ -8324,6 +8343,52 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, Edi
                dm->release(dm);
 }
 
+/* Shape Key */
+
+static void shapekeyModifier_deformVerts(
+                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
+      float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+       KeyBlock *kb= ob_get_keyblock(ob);
+       float (*deformedVerts)[3];
+
+       if(kb && kb->totelem == numVerts) {
+               deformedVerts= (float(*)[3])do_ob_key(md->scene, ob);
+               if(deformedVerts) {
+                       memcpy(vertexCos, deformedVerts, sizeof(float)*3*numVerts);
+                       MEM_freeN(deformedVerts);
+               }
+       }
+}
+
+static void shapekeyModifier_deformVertsEM(
+                                          ModifierData *md, Object *ob, EditMesh *editData,
+       DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+       Key *key= ob_get_key(ob);
+
+       if(key && key->type == KEY_RELATIVE)
+               shapekeyModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
+}
+
+static void shapekeyModifier_deformMatricesEM(
+                                             ModifierData *md, Object *ob, EditMesh *editData,
+          DerivedMesh *derivedData, float (*vertexCos)[3],
+                                            float (*defMats)[3][3], int numVerts)
+{
+       Key *key= ob_get_key(ob);
+       KeyBlock *kb= ob_get_keyblock(ob);
+       float scale[3][3];
+       int a;
+
+       if(kb && kb->totelem==numVerts && kb!=key->refkey) {
+               Mat3Scale(scale, kb->curval);
+
+               for(a=0; a<numVerts; a++)
+                       Mat3CpyMat3(defMats[a], scale);
+       }
+}
+
 /***/
 
 static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
@@ -8728,6 +8793,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->copyData = multiresModifier_copyData;
                mti->applyModifier = multiresModifier_applyModifier;
 
+               mti = INIT_TYPE(ShapeKey);
+               mti->type = eModifierTypeType_OnlyDeform;
+               mti->flags = eModifierTypeFlag_AcceptsCVs
+                               | eModifierTypeFlag_SupportsEditmode;
+               mti->deformVerts = shapekeyModifier_deformVerts;
+               mti->deformVertsEM = shapekeyModifier_deformVertsEM;
+               mti->deformMatricesEM = shapekeyModifier_deformMatricesEM;
+
                typeArrInit = 0;
 #undef INIT_TYPE
        }
@@ -8745,7 +8818,8 @@ ModifierData *modifier_new(int type)
 {
        ModifierTypeInfo *mti = modifierType_getInfo(type);
        ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
-
+       
+       // FIXME: we need to make the name always be unique somehow...
        strcpy(md->name, mti->name);
 
        md->type = type;
@@ -8770,6 +8844,15 @@ void modifier_free(ModifierData *md)
        MEM_freeN(md);
 }
 
+void modifier_unique_name(ListBase *modifiers, ModifierData *md)
+{
+       if (modifiers && md) {
+               ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+               
+               BLI_uniquename(modifiers, md, mti->name, '.', offsetof(ModifierData, name), sizeof(md->name));
+       }
+}
+
 int modifier_dependsOnTime(ModifierData *md) 
 {
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -8882,9 +8965,9 @@ void modifier_setError(ModifierData *md, char *format, ...)
  * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
  * then is NULL)
  */
-int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
+int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r, int virtual_)
 {
-       ModifierData *md = ob->modifiers.first;
+       ModifierData *md = (virtual_)? modifiers_getVirtualModifierList(ob): ob->modifiers.first;
        int i, cageIndex = -1;
 
        /* Find the last modifier acting on the cage. */
@@ -8993,11 +9076,11 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
        static ArmatureModifierData amd;
        static CurveModifierData cmd;
        static LatticeModifierData lmd;
+       static ShapeKeyModifierData smd;
        static int init = 1;
+       ModifierData *md;
 
        if (init) {
-               ModifierData *md;
-
                md = modifier_new(eModifierType_Armature);
                amd = *((ArmatureModifierData*) md);
                modifier_free(md);
@@ -9010,32 +9093,50 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
                lmd = *((LatticeModifierData*) md);
                modifier_free(md);
 
+               md = modifier_new(eModifierType_ShapeKey);
+               smd = *((ShapeKeyModifierData*) md);
+               modifier_free(md);
+
                amd.modifier.mode |= eModifierMode_Virtual;
                cmd.modifier.mode |= eModifierMode_Virtual;
                lmd.modifier.mode |= eModifierMode_Virtual;
+               smd.modifier.mode |= eModifierMode_Virtual;
 
                init = 0;
        }
 
-       if (ob->parent) {
+       md = ob->modifiers.first;
+
+       if(ob->parent) {
                if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
                        amd.object = ob->parent;
-                       amd.modifier.next = ob->modifiers.first;
+                       amd.modifier.next = md;
                        amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
-                       return &amd.modifier;
+                       md = &amd.modifier;
                } else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
                        cmd.object = ob->parent;
                        cmd.defaxis = ob->trackflag + 1;
-                       cmd.modifier.next = ob->modifiers.first;
-                       return &cmd.modifier;
+                       cmd.modifier.next = md;
+                       md = &cmd.modifier;
                } else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
                        lmd.object = ob->parent;
-                       lmd.modifier.next = ob->modifiers.first;
-                       return &lmd.modifier;
+                       lmd.modifier.next = md;
+                       md = &lmd.modifier;
                }
        }
 
-       return ob->modifiers.first;
+       /* shape key modifier, not yet for curves */
+       if(ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
+               if(ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
+                       smd.modifier.mode |= eModifierMode_Editmode|eModifierMode_OnCage;
+               else
+                       smd.modifier.mode &= ~eModifierMode_Editmode|eModifierMode_OnCage;
+
+               smd.modifier.next = md;
+               md = &smd.modifier;
+       }
+
+       return md;
 }
 /* Takes an object and returns its first selected armature, else just its
  * armature
@@ -9112,6 +9213,8 @@ int modifier_isDeformer(ModifierData *md)
                return 1;
        if (md->type==eModifierType_Lattice)
                return 1;
+       if (md->type==eModifierType_ShapeKey)
+               return 1;
        
        return 0;
 }
@@ -9121,7 +9224,7 @@ int modifiers_isDeformed(Scene *scene, Object *ob)
        ModifierData *md = modifiers_getVirtualModifierList(ob);
        
        for (; md; md=md->next) {
-               if(ob==scene->obedit && (md->mode & eModifierMode_Editmode)==0);
+               if(ob->mode==OB_MODE_EDIT && (md->mode & eModifierMode_Editmode)==0);
                else 
                        if(modifier_isDeformer(md))
                                return 1;