svn merge -r 12607:12653 https://svn.blender.org/svnroot/bf-blender/trunk/blender...
authorDaniel Genrich <daniel.genrich@gmx.net>
Thu, 22 Nov 2007 20:28:24 +0000 (20:28 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Thu, 22 Nov 2007 20:28:24 +0000 (20:28 +0000)
1  2 
CMakeLists.txt
intern/elbeem/CMakeLists.txt
intern/elbeem/intern/paraloopend.h
source/blender/blenkernel/intern/modifier.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/src/buttons_editing.c
source/blender/src/transform_conversions.c

diff --combined CMakeLists.txt
index 0227c51f39d17a3ff8fbc28324e14e4af3805016,0227c51f39d17a3ff8fbc28324e14e4af3805016..eabcdde1dde6ab84b8a6b08c361b6cd4f3ba8bcf
@@@ -65,8 -65,8 +65,9 @@@ OPTION(WITH_ELBEEM            "Enable Elbeem (Flu
  OPTION(WITH_QUICKTIME         "Enable Quicktime Support"                              OFF)
  OPTION(WITH_OPENEXR           "Enable OpenEXR Support (http://www.openexr.com)"       OFF)
  OPTION(WITH_FFMPEG            "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)"   OFF)
--OPTION(WITH_OPENAL            "Enable OpenAL Support (http://www.openal.org)" ON)
--OPTION(YESIAMSTUPID           "Enable execution on 64-bit platforms"                                  OFF)
++OPTION(WITH_OPENAL            "Enable OpenAL Support (http://www.openal.org)"         ON)
++OPTION(YESIAMSTUPID           "Enable execution on 64-bit platforms"                  OFF)
++OPTION(WITH_OPENMP            "Enable OpenMP (has to be supported by the compiler)"   OFF)
  
  IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
    MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE")
@@@ -186,6 -186,6 +187,12 @@@ IF(UNIX
  
    SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts")
  
++  IF(WITH_OPENMP)
++    SET(LLIBS ${LLIBS} gomp)
++    SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp")
++    SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp")
++  ENDIF(WITH_OPENMP)
++
    SET(PLATFORM_LINKFLAGS "-pthread")
  
    INCLUDE_DIRECTORIES(/usr/include /usr/local/include)
@@@ -270,6 -270,6 +277,11 @@@ IF(WIN32
    SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
    SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
  
++  IF(WITH_OPENMP)
++    SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "/openmp")
++    SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "/openmp")
++  ENDIF(WITH_OPENMP)
++
    SET(SDL ${LIBDIR}/sdl)
    SET(SDL_INC ${SDL}/include)
    SET(SDL_LIB SDL)
@@@ -347,6 -347,6 +359,12 @@@ IF(APPLE
    SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
    SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
  
++  IF(WITH_OPENMP)
++    SET(LLIBS ${LLIBS} gomp)
++    SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp")
++    SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp")
++  ENDIF(WITH_OPENMP)
++
    SET(SDL ${LIBDIR}/sdl)
    SET(SDL_INC ${SDL}/include)
    SET(SDL_LIB SDL)
index 86a60180b053225eb81c1625687e8649be07878d,86a60180b053225eb81c1625687e8649be07878d..ac35b8ce00f04c2d483afecd6c38f9972eedd731
@@@ -36,5 -36,5 +36,9 @@@ IF(WINDOWS
      ADD_DEFINITIONS(-DUSE_MSVC6FIXES)
  ENDIF(WINDOWS)
  
++IF(WITH_OPENMP)
++    ADD_DEFINITIONS(-DPARALLEL)
++ENDIF(WITH_OPENMP)
++
  BLENDERLIB_NOLIST(bf_elbeem "${SRC}" "${INC}")
  #, libtype='blender', priority=0 )
index 889e29308182e8b720f91d09774dada618c56e2c,0000000000000000000000000000000000000000..81fc329d159a07d7cb2ae76b6e5400cea7ec2fff
mode 100644,000000..100644
--- /dev/null
@@@ -1,13 -1,0 +1,13 @@@
- } /* all cell loop k,j,i */ 
 +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 +} /* i */ 
 +      int i=0; 
 +      ADVANCE_POINTERS(2*gridLoopBound); 
 +} /* j */ 
 +#pragma omp barrier 
 +      /* COMPRESSGRIDS!=1 */ 
 +      /* int i=0;  */ 
 +      /* ADVANCE_POINTERS(mLevel[lev].lSizex*2);  */ 
++} /* all cell loop k,j,i */
 +      if(doReduce) { } /* dummy remove warning */ 
 +} /* main_region */ 
 +
index a07e53a2a5e73582e7ff1070d8c3688c42c89d28,3a6611a2be778d2604a91d51eff4ca0f4885f2df..85dc1ca44fbf7f1af456bd2c31e09260cdb60696
@@@ -52,7 -52,6 +52,7 @@@
  #include "MEM_guardedalloc.h"
  
  #include "DNA_armature_types.h"
 +#include "DNA_cloth_types.h"
  #include "DNA_effect_types.h"
  #include "DNA_material_types.h"
  #include "DNA_mesh_types.h"
@@@ -73,7 -72,6 +73,7 @@@
  #include "BKE_main.h"
  #include "BKE_anim.h"
  #include "BKE_bad_level_calls.h"
 +#include "BKE_collisions.h"
  #include "BKE_customdata.h"
  #include "BKE_global.h"
  #include "BKE_utildefines.h"
@@@ -87,7 -85,6 +87,7 @@@
  #include "BKE_object.h"
  #include "BKE_mesh.h"
  #include "BKE_softbody.h"
 +#include "BKE_cloth.h"
  #include "BKE_material.h"
  #include "depsgraph_private.h"
  
@@@ -241,12 -238,29 +241,29 @@@ static void latticeModifier_updateDepgr
        }
  }
  
+ static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
+ {
+       md= md->next;
+       if(md) {
+               if(md->type==eModifierType_Armature) {
+                       ArmatureModifierData *amd = (ArmatureModifierData*) md;
+                       if(amd->multi)
+                               amd->prevCos= MEM_dupallocN(vertexCos);
+               }
+               /* lattice/mesh modifier too */
+       }
+ }
  static void latticeModifier_deformVerts(
                  ModifierData *md, Object *ob, DerivedMesh *derivedData,
                  float (*vertexCos)[3], int numVerts)
  {
        LatticeModifierData *lmd = (LatticeModifierData*) md;
  
+       modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+       
        lattice_deform_verts(lmd->object, ob, derivedData,
                             vertexCos, numVerts, lmd->name);
  }
@@@ -4667,8 -4681,16 +4684,16 @@@ static void armatureModifier_deformVert
  {
        ArmatureModifierData *amd = (ArmatureModifierData*) md;
  
+       modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+       
        armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
-                             numVerts, amd->deformflag, amd->defgrp_name);
+                             numVerts, amd->deformflag, 
+                                                 amd->prevCos, amd->defgrp_name);
+       /* free cache */
+       if(amd->prevCos) {
+               MEM_freeN(amd->prevCos);
+               amd->prevCos= NULL;
+       }
  }
  
  static void armatureModifier_deformVertsEM(
        if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
  
        armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
-                             amd->deformflag, amd->defgrp_name);
+                             amd->deformflag, NULL, amd->defgrp_name);
  
        if(!derivedData) dm->release(dm);
  }
@@@ -4697,7 -4719,7 +4722,7 @@@ static void armatureModifier_deformMatr
        if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
  
        armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
-                             amd->deformflag, amd->defgrp_name);
+                             amd->deformflag, NULL, amd->defgrp_name);
  
        if(!derivedData) dm->release(dm);
  }
@@@ -4910,256 -4932,6 +4935,256 @@@ static void softbodyModifier_deformVert
        sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
  }
  
 +
 +/* Cloth */
 +
 +static void clothModifier_initData(ModifierData *md) 
 +{
 +      ClothModifierData *clmd = (ClothModifierData*) md;
 +      
 +      clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings),
 +                  "cloth sim parms");
 +      clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings),
 +                                    "cloth coll parms");
 +      
 +      cloth_init (clmd);
 +}
 +/*
 +static void clothModifier_deformVerts(
 +              ModifierData *md, Object *ob, DerivedMesh *derivedData,
 +              float (*vertexCos)[3], int numVerts)
 +{
 +      DerivedMesh *dm = NULL;
 +
 +      // if possible use/create DerivedMesh
 +      
 +      if(derivedData) dm = CDDM_copy(derivedData);
 +      else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
 +      
 +      if(dm)
 +      {
 +              CDDM_apply_vert_coords(dm, vertexCos);
 +              CDDM_calc_normals(dm);
 +      }
 +      
 +      clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts);
 +      
 +      if(dm)
 +              dm->release(dm);
 +}
 +*/
 +
 +static DerivedMesh *clothModifier_applyModifier(
 +                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
 +                 int useRenderParams, int isFinalCalc)
 +{
 +      ClothModifierData *clmd = (ClothModifierData*) md;
 +      DerivedMesh *result=NULL;
 +
 +      result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc);
 +
 +      if(result)
 +      {
 +              return result;
 +      }
 +      return derivedData;
 +}
 +
 +static void clothModifier_updateDepgraph(
 +                ModifierData *md, DagForest *forest, Object *ob,
 +                DagNode *obNode)
 +{
 +      ClothModifierData *clmd = (ClothModifierData*) md;
 +      
 +      Base *base;
 +      
 +      if(clmd)
 +      {
 +              for(base = G.scene->base.first; base; base= base->next) 
 +              {
 +                      Object *ob1= base->object;
 +                      if(ob1 != ob)
 +                      {
 +                              CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
 +                              if(collmd)
 +                              {
 +                                      DagNode *curNode = dag_get_node(forest, ob1);
 +                                      
 +                                      dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
 +                              
 +                              }
 +                      }
 +              }
 +      }       
 +}
 +
 +CustomDataMask clothModifier_requiredDataMask(ModifierData *md)
 +{
 +      ClothModifierData *clmd = (ClothModifierData *)md;
 +      CustomDataMask dataMask = 0;
 +
 +      /* ask for vertexgroups if we need them */
 +      if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
 +              if (clmd->sim_parms->vgroup_mass > 0)
 +                      dataMask |= (1 << CD_MDEFORMVERT);
 +
 +      return dataMask;
 +}
 +
 +
 +static int clothModifier_dependsOnTime(ModifierData *md)
 +{
 +      return 1;
 +}
 +
 +static void clothModifier_freeData(ModifierData *md)
 +{
 +      ClothModifierData *clmd = (ClothModifierData*) md;
 +      
 +      if (clmd) 
 +      {
 +              
 +              clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT;
 +              cloth_free_modifier (clmd);
 +              
 +              MEM_freeN(clmd->sim_parms);
 +              MEM_freeN(clmd->coll_parms);
 +      }
 +}
 +
 +/* Collision */
 +
 +static void collisionModifier_initData(ModifierData *md) 
 +{
 +      CollisionModifierData *collmd = (CollisionModifierData*) md;
 +      
 +      collmd->x = NULL;
 +      collmd->xnew = NULL;
 +      collmd->current_x = NULL;
 +      collmd->current_xnew = NULL;
 +      collmd->time = -1;
 +      collmd->numverts = 0;
 +      collmd->tree = NULL;
 +}
 +
 +static void collisionModifier_freeData(ModifierData *md)
 +{
 +      CollisionModifierData *collmd = (CollisionModifierData*) md;
 +      
 +      if (collmd) 
 +      {
 +              if(collmd->tree)
 +                      bvh_free(collmd->tree);
 +              if(collmd->x)
 +                      MEM_freeN(collmd->x);
 +              if(collmd->xnew)
 +                      MEM_freeN(collmd->xnew);
 +              if(collmd->current_x)
 +                      MEM_freeN(collmd->current_x);
 +              if(collmd->current_xnew)
 +                      MEM_freeN(collmd->current_xnew);
 +              
 +              collmd->x = NULL;
 +              collmd->xnew = NULL;
 +              collmd->current_x = NULL;
 +              collmd->current_xnew = NULL;
 +              collmd->time = -1;
 +              collmd->numverts = 0;
 +              collmd->tree = NULL;
 +      }
 +}
 +
 +static int collisionModifier_dependsOnTime(ModifierData *md)
 +{
 +      return 1;
 +}
 +
 +static void collisionModifier_deformVerts(
 +                                    ModifierData *md, Object *ob, DerivedMesh *derivedData,
 +        float (*vertexCos)[3], int numVerts)
 +{
 +      CollisionModifierData *collmd = (CollisionModifierData*) md;
 +      DerivedMesh *dm = NULL;
 +      float current_time = 0;
 +      unsigned int numverts = 0, i = 0;
 +      MVert *tempVert = NULL;
 +
 +      // if possible use/create DerivedMesh
 +      
 +      if(derivedData) dm = CDDM_copy(derivedData);
 +      else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
 +      
 +      if(!ob->pd)
 +      {
 +              printf("collisionModifier_deformVerts: Should not happen!\n");
 +              return;
 +      }
 +      
 +      if(dm)
 +      {
 +              CDDM_apply_vert_coords(dm, vertexCos);
 +              CDDM_calc_normals(dm);
 +      
 +      
 +              current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
 +              
 +              if(current_time > collmd->time)
 +              {
 +                      numverts = dm->getNumVerts ( dm );
 +                      
 +                      // check if mesh has changed
 +                      if(collmd->x && (numverts != collmd->numverts))
 +                              collisionModifier_freeData((ModifierData *)collmd);
 +                      
 +                      if(collmd->time == -1) // first time
 +                      {
 +                              collmd->x = dm->dupVertArray(dm); // frame start position
 +                              
 +                              for ( i = 0; i < numverts; i++ )
 +                              {
 +                                      // we save global positions
 +                                      Mat4MulVecfl ( ob->obmat, collmd->x[i].co );
 +                              }
 +                              
 +                              collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
 +                              collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
 +                              collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
 +                              collmd->numverts = numverts;
 +                              
 +                              // TODO: epsilon
 +                              // create bounding box hierarchy
 +                              collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift);
 +                      }
 +                      else if(numverts == collmd->numverts)
 +                      {
 +                              // put positions to old positions
 +                              tempVert = collmd->x;
 +                              collmd->x = collmd->xnew;
 +                              collmd->xnew = tempVert;
 +                              
 +                              memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
 +                              
 +                              for ( i = 0; i < numverts; i++ )
 +                              {
 +                                      // we save global positions
 +                                      Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co );
 +                              }
 +                              
 +                              memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
 +                              memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert));
 +                              
 +                              // recalc static bounding boxes
 +                              bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
 +                      }
 +                      
 +                      collmd->time = current_time;
 +              }
 +      }
 +      
 +      if(dm)
 +              dm->release(dm);
 +}
 +
  /* Boolean */
  
  static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@@ -5494,6 -5266,8 +5519,8 @@@ static void meshdeformModifier_deformVe
        else
                dm= derivedData;
  
+       modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
+       
        meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
  
        if(dm != derivedData)
@@@ -5517,83 -5291,6 +5544,83 @@@ static void meshdeformModifier_deformVe
                dm->release(dm);
  }
  
 +
 +/* PointCache - example DONT USE SERIOUSLY */
 +static void pointCacheModifier_initData(ModifierData *md)
 +{
 +      PointCacheModifierData *pcm= (PointCacheModifierData*) md;
 +
 +      pcm->mode= ePointCache_Read; /* read */
 +}
 +static void pointCacheModifier_freeData(ModifierData *md)
 +{
 +      PointCacheModifierData *pcm = (PointCacheModifierData*) md;
 +}
 +static void pointCacheModifier_copyData(ModifierData *md, ModifierData *target)
 +{
 +      PointCacheModifierData *pcm= (PointCacheModifierData*) md;
 +      PointCacheModifierData *tpcm= (PointCacheModifierData*) target;
 +
 +      tpcm->mode = pcm->mode;
 +}
 +static int pointCacheModifier_dependsOnTime(ModifierData *md) 
 +{
 +      return 1;
 +}
 +CustomDataMask pointCacheModifier_requiredDataMask(ModifierData *md)
 +{
 +      PointCacheModifierData *pcm= (PointCacheModifierData*) md;
 +      CustomDataMask dataMask = 0;
 +      return dataMask;
 +}
 +
 +static void pointCacheModifier_deformVerts(
 +                                         ModifierData *md, Object *ob, DerivedMesh *derivedData,
 +      float (*vertexCos)[3], int numVerts)
 +{
 +      PointCacheModifierData *pcm = (PointCacheModifierData*) md;
 +
 +      FILE *fp = NULL;
 +      int i;
 +      int stack_index = modifiers_indexInObject(ob, md);
 +      int totvert;
 +      MVert *mvert, *mv;
 +      
 +      DerivedMesh *dm;
 +
 +      if(derivedData) dm = CDDM_copy(derivedData);
 +      else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
 +      else return;
 +
 +      CDDM_apply_vert_coords(dm, vertexCos);
 +      CDDM_calc_normals(dm);
 +      
 +      mvert = mv = dm->getVertArray(dm);
 +      totvert = dm->getNumVerts(dm);
 +                      
 +      if (pcm->mode == ePointCache_Read) {
 +              fp = PTCache_id_fopen((ID *)ob, 'w', G.scene->r.cfra, stack_index);
 +              if (!fp) return;
 +              for (mv=mvert, i=0; i<totvert; mv++, i++) {
 +                      fwrite(&mv->co, sizeof(float), 3, fp);
 +              }
 +              fclose(fp);
 +      } else if (pcm->mode == ePointCache_Write) {
 +              float pt[3];
 +              fp = PTCache_id_fopen((ID *)ob, 'r', G.scene->r.cfra, stack_index);
 +              if (!fp) return;
 +              for (mv=mvert, i=0; i<totvert; mv++, i++) {
 +                      float *co = vertexCos[i];
 +                      if ((fread(co, sizeof(float), 3, fp)) != 3) {
 +                              break;
 +                      }
 +              }
 +              fclose(fp);
 +      }
 +      
 +      if(!derivedData) dm->release(dm);
 +}
 +
  /***/
  
  static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
@@@ -5814,32 -5511,6 +5841,32 @@@ ModifierTypeInfo *modifierType_getInfo(
                mti->flags = eModifierTypeFlag_AcceptsCVs
                             | eModifierTypeFlag_RequiresOriginalData;
                mti->deformVerts = softbodyModifier_deformVerts;
 +      
 +              mti = INIT_TYPE(Cloth);
 +              mti->type = eModifierTypeType_Nonconstructive;
 +              mti->initData = clothModifier_initData;
 +              mti->flags = eModifierTypeFlag_AcceptsMesh
 +                              | eModifierTypeFlag_RequiresOriginalData;
 +                                      // | eModifierTypeFlag_SupportsMapping
 +                                      // | eModifierTypeFlag_SupportsEditmode 
 +                                      // | eModifierTypeFlag_EnableInEditmode;
 +              mti->dependsOnTime = clothModifier_dependsOnTime;
 +              mti->freeData = clothModifier_freeData; 
 +              mti->requiredDataMask = clothModifier_requiredDataMask;
 +              // mti->copyData = clothModifier_copyData;
 +              // mti->deformVerts = clothModifier_deformVerts;
 +              mti->applyModifier = clothModifier_applyModifier;
 +              mti->updateDepgraph = clothModifier_updateDepgraph;
 +              
 +              mti = INIT_TYPE(Collision);
 +              mti->type = eModifierTypeType_OnlyDeform;
 +              mti->initData = collisionModifier_initData;
 +              mti->flags = eModifierTypeFlag_AcceptsMesh 
 +                              | eModifierTypeFlag_RequiresOriginalData;
 +              mti->dependsOnTime = collisionModifier_dependsOnTime;
 +              mti->freeData = collisionModifier_freeData; 
 +              mti->deformVerts = collisionModifier_deformVerts;
 +              // mti->copyData = collisionModifier_copyData;
  
                mti = INIT_TYPE(Boolean);
                mti->type = eModifierTypeType_Nonconstructive;
                mti->updateDepgraph = meshdeformModifier_updateDepgraph;
                mti->deformVerts = meshdeformModifier_deformVerts;
                mti->deformVertsEM = meshdeformModifier_deformVertsEM;
 +              
 +              mti = INIT_TYPE(PointCache);
 +              mti->type = eModifierTypeType_OnlyDeform;
 +              mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
 +              mti->initData = pointCacheModifier_initData;
 +              mti->freeData = pointCacheModifier_freeData;
 +              mti->copyData = pointCacheModifier_copyData;
 +              mti->dependsOnTime = pointCacheModifier_dependsOnTime;
 +              mti->requiredDataMask = pointCacheModifier_requiredDataMask;
 +              mti->deformVerts = pointCacheModifier_deformVerts;
  
                typeArrInit = 0;
  #undef INIT_TYPE
@@@ -6066,13 -5727,6 +6093,13 @@@ int modifiers_isSoftbodyEnabled(Object 
        return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
  }
  
 +ClothModifierData *modifiers_isClothEnabled(Object *ob)
 +{
 +      ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +
 +      return clmd;
 +}
 +
  LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
  {
        LinkNode *dataMasks = NULL;
@@@ -6256,27 -5910,3 +6283,27 @@@ int modifiers_isDeformed(Object *ob
        return 0;
  }
  
 +/* checks we only have deform modifiers */
 +int modifiers_isDeformedOnly(Object *ob)
 +{
 +      ModifierData *md = modifiers_getVirtualModifierList(ob);
 +      ModifierTypeInfo *mti;
 +      for (; md; md=md->next) {
 +              mti = modifierType_getInfo(md->type);
 +              /* TODO - check the modifier is being used! */
 +              if (mti->type != eModifierTypeType_OnlyDeform) {
 +                      return 0;
 +              }
 +      }
 +      return 1;
 +}
 +
 +int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
 +{
 +      int i= 0;
 +      ModifierData *md;
 +      
 +      for (md=ob->modifiers.first; (md && md_seek!=md); md=md->next, i++);
 +      if (!md) return -1; /* modifier isnt in the object */
 +      return i;
 +}
index 5861ba39da236c522c024352ab8af2bd81633955,0903062461b3ec95477c5e335e8e46ebfb259482..6d16a326a0ba5c8a0751a9ef8a6ce5e82c7282d6
@@@ -60,7 -60,6 +60,7 @@@
  #include "DNA_actuator_types.h"
  #include "DNA_brush_types.h"
  #include "DNA_camera_types.h"
 +#include "DNA_cloth_types.h"
  #include "DNA_color_types.h"
  #include "DNA_controller_types.h"
  #include "DNA_constraint_types.h"
  
  #include "BKE_action.h"
  #include "BKE_armature.h"
 +#include "BKE_cloth.h"
  #include "BKE_colortools.h"
  #include "BKE_constraint.h"
  #include "BKE_curve.h"
@@@ -2880,28 -2878,7 +2880,28 @@@ static void direct_link_modifiers(FileD
                        SubsurfModifierData *smd = (SubsurfModifierData*) md;
  
                        smd->emCache = smd->mCache = 0;
 -              } else if (md->type==eModifierType_Hook) {
 +              } 
 +              else if (md->type==eModifierType_Cloth) {
 +                 ClothModifierData    *clmd = (ClothModifierData*) md;
 +
 +                 clmd->clothObject = NULL;
 +                 
 +                 clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
 +                 clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
 +                 
 +              } 
 +              else if (md->type==eModifierType_Collision) {
 +                      CollisionModifierData *collmd = (CollisionModifierData*) md;
 +                      
 +                      collmd->x = NULL;
 +                      collmd->xnew = NULL;
 +                      collmd->current_x = NULL;
 +                      collmd->current_xnew = NULL;
 +                      collmd->time = -1;
 +                      collmd->numverts = 0;
 +                      collmd->tree = NULL;
 +              }
 +              else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
  
                        hmd->indexar= newdataadr(fd, hmd->indexar);
@@@ -3036,6 -3013,7 +3036,6 @@@ static void direct_link_object(FileDat
                sb->bpoint= NULL;       // init pointers so it gets rebuilt nicely
                sb->bspring= NULL;
                sb->scratch= NULL;
 -
                
                sb->keys= newdataadr(fd, sb->keys);
                test_pointer_array(fd, (void **)&sb->keys);
@@@ -3226,7 -3204,6 +3226,6 @@@ static void direct_link_scene(FileData 
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
-       StripElem *se;
        int a;
  
        sce->theDag = NULL;
                        /* a patch: after introduction of effects with 3 input strips */
                        if(seq->seq3==0) seq->seq3= seq->seq2;
  
-                       seq->curelem= 0;
                        seq->plugin= newdataadr(fd, seq->plugin);
                        seq->effectdata= newdataadr(fd, seq->effectdata);
                        
                        seq->strip= newdataadr(fd, seq->strip);
                        if(seq->strip && seq->strip->done==0) {
                                seq->strip->done= 1;
-                               /* standard: strips from effects/metas are not written, but are mallocced */
-                               if(seq->type==SEQ_IMAGE) {
-                                       seq->strip->stripdata= newdataadr(fd, seq->strip->stripdata);
-                                       se= seq->strip->stripdata;
-                                       if(se) {
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 1;
-                                                       se->ibuf= 0;
-                                               }
-                                       }
-                               }
-                               else if(seq->type==SEQ_MOVIE) {
-                                       /* only first stripelem is in file */
-                                       se= newdataadr(fd, seq->strip->stripdata);
-                                       if(se) {
-                                               seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-                                               *seq->strip->stripdata= *se;
-                                               MEM_freeN(se);
-                                               se= seq->strip->stripdata;
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 1;
-                                                       se->ibuf= 0;
-                                                       se->nr= a + 1;
-                                               }
-                                       }
-                               }
-                               else if(seq->type==SEQ_RAM_SOUND
-                                       || seq->type == SEQ_HD_SOUND) {
-                                       /* only first stripelem is in file */
-                                       se= newdataadr(fd, seq->strip->stripdata);
-                                       if(se) {
-                                               seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-                                               *seq->strip->stripdata= *se;
-                                               MEM_freeN(se);
-                                               se= seq->strip->stripdata;
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 2; /* why? */
-                                                       se->ibuf= 0;
-                                                       se->nr= a + 1;
-                                               }
-                                       }
+                               seq->strip->tstripdata = 0;
+                               if(seq->type == SEQ_IMAGE ||
+                                  seq->type == SEQ_MOVIE ||
+                                  seq->type == SEQ_RAM_SOUND ||
+                                  seq->type == SEQ_HD_SOUND) {
+                                       seq->strip->stripdata = newdataadr(
+                                               fd, seq->strip->stripdata);
+                               } else {
+                                       seq->strip->stripdata = 0;
                                }
-                               else if(seq->len>0)
-                                       seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
                        }
                }
                END_SEQ
index 68290c6e9b5c103c18df78377e774c2440b1de1d,0802fbf0e4063652e6c55981cd7e2227b023fe76..903f1a540b3a07b1e7f255550c1f4437e954f6b8
@@@ -29,9 -29,6 +29,9 @@@ typedef enum ModifierType 
        eModifierType_Smooth,
        eModifierType_Cast,
        eModifierType_MeshDeform,
 +      eModifierType_PointCache,
 +      eModifierType_Cloth,
 +        eModifierType_Collision,      
        NUM_MODIFIER_TYPES
  } ModifierType;
  
@@@ -316,9 -313,10 +316,10 @@@ typedef struct WaveModifierData 
  typedef struct ArmatureModifierData {
        ModifierData modifier;
  
-       short deformflag, pad1;         /* deformflag replaces armature->deformflag */
+       short deformflag, multi;                /* deformflag replaces armature->deformflag */
        int pad2;
        struct Object *object;
+       float *prevCos;         /* stored input of previous modifier, for vertexgroup blending */
        char defgrp_name[32];
  } ArmatureModifierData;
  
@@@ -340,27 -338,6 +341,27 @@@ typedef struct SoftbodyModifierData 
        ModifierData modifier;
  } SoftbodyModifierData;
  
 +typedef struct ClothModifierData {
 +   ModifierData               modifier;
 +
 +   struct Cloth *clothObject; /* The internal data structure for cloth. */
 +   struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */
 +   struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */
 +} ClothModifierData;
 +
 +typedef struct CollisionModifierData {
 +      ModifierData            modifier;
 +      
 +      struct MVert *x; /* position at the beginning of the frame */
 +      struct MVert *xnew; /* position at the end of the frame */
 +      struct MVert *current_xnew; /* new position at the actual inter-frame step */
 +      struct MVert *current_x; /* position at the actual inter-frame step */
 +      
 +      unsigned int numverts;
 +      float time;
 +      struct BVH *tree;       /* collision tree for this cloth object */
 +} CollisionModifierData;
 +
  typedef enum {
        eBooleanModifierOp_Intersect,
        eBooleanModifierOp_Union,
@@@ -408,14 -385,4 +409,14 @@@ typedef struct MeshDeformModifierData 
        float bindmat[4][4];                    /* matrix of cage at binding time */
  } MeshDeformModifierData;
  
 +typedef struct PointCacheModifierData {
 +      ModifierData modifier;
 +      short mode, pad1, pad2, pad3;
 +} PointCacheModifierData;
 +
 +typedef enum {
 +      ePointCache_Read =      (1<<0),
 +                               ePointCache_Write =            (1<<1),
 +} PointCacheFlag;
 +
  #endif
index 25540106356e4728d8b7633bc67bda1a8156d0f2,082353f11742a7e00d8a37667b1d309fca95b8b1..70d1c0920662f521324acc1b5483d6898d30ae81
@@@ -88,7 -88,6 +88,7 @@@
  #include "BKE_main.h"
  #include "BKE_modifier.h"
  #include "BKE_packedFile.h"
 +#include "BKE_pointcache.h"
  #include "BKE_scene.h"
  
  #include "BLI_blenlib.h"
@@@ -952,8 -951,6 +952,8 @@@ static uiBlock *modifiers_add_menu(voi
  
                /* Only allow adding through appropriate other interfaces */
                if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
 +              
 +              if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
  
                if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
                   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@@ -1399,14 -1396,6 +1399,14 @@@ static void modifiers_convertToReal(voi
        BIF_undo_push("Modifier convert to real");
  }
  
 +static void modifiers_pointCacheClearModifier(void *ob_v, void *md_v)
 +{
 +      Object *ob = ob_v;
 +      ModifierData *md = md_v;        
 +      int stack_index = modifiers_indexInObject(ob_v, md_v);
 +      PTCache_id_clear((ID *)ob, CFRA, stack_index);
 +}
 +
  static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
                                      int *uvlayer_tmp, char *uvlayer_name)
  {
@@@ -1535,7 -1524,7 +1535,7 @@@ static void draw_modifier(uiBlock *bloc
        uiBlockSetCol(block, TH_AUTO);
        
        /* open/close icon */
 -      if (!isVirtual) {
 +      if (!isVirtual && md->type!=eModifierType_Collision) {
                uiBlockSetEmboss(block, UI_EMBOSSN);
                uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
        }
                uiBlockBeginAlign(block);
                uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
  
 -                      /* Softbody not allowed in this situation, enforce! */
 -              if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
 +              /* Softbody not allowed in this situation, enforce! */
 +              if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
                        uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
                        uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
                        if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
                uiButSetFunc(but, modifiers_moveDown, ob, md);
                
                uiBlockSetEmboss(block, UI_EMBOSSN);
 -
 -              but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
 -              uiButSetFunc(but, modifiers_del, ob, md);
 +              
 +              // deletion over the deflection panel
 +              if(md->type!=eModifierType_Collision)
 +              {
 +                      but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
 +                      uiButSetFunc(but, modifiers_del, ob, md);
 +              }
                uiBlockSetCol(block, TH_AUTO);
        }
  
                        if(wmd->flag & MOD_WAVE_NORM)
                                height += 19;
                } else if (md->type==eModifierType_Armature) {
-                       height = 86;
+                       height = 105;
                } else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
                        height = 86;
                                height += 20;
                } else if (md->type==eModifierType_Softbody) {
                        height = 26;
 +              } else if (md->type==eModifierType_Cloth) {
 +                      height = 26;
 +              } else if (md->type==eModifierType_Collision) {
 +                      height = 19;
                } else if (md->type==eModifierType_Boolean) {
                        height = 48;
                } else if (md->type==eModifierType_Array) {
                } else if (md->type==eModifierType_MeshDeform) {
                        MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
                        height = (mmd->bindcos)? 73: 93;
 +              } else if (md->type==eModifierType_PointCache) {
 +                      height = 48;
                } 
                
                                                        /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
  
                y -= 18;
  
 -              if (!isVirtual) {
 +              if (!isVirtual && (md->type!=eModifierType_Collision)) {
                        uiBlockBeginAlign(block);
                        but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
                        uiButSetFunc(but, modifiers_applyModifier, ob, md);
 -                      if (md->type!=eModifierType_Softbody) {
 +                      if ((md->type!=eModifierType_Softbody) && (md->type!=eModifierType_Cloth)) {
                                but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
                                uiButSetFunc(but, modifiers_copyModifier, ob, md);
                        }
                        ArmatureModifierData *amd = (ArmatureModifierData*) md;
                        uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
                        
-                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
                        uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv",        lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence");
+                       
                        uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups",       lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
                        uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes",       lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
                        uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion",    lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
                        uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position");
+                       
+                       uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier",        lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup");
                } else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
                                uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
                        }
                        uiBlockEndAlign(block);
 +              } else if (md->type==eModifierType_PointCache) {
 +              PointCacheModifierData *pcm = (PointCacheModifierData *) md;
 +              uiBut *but;     
 +              cy -= 20;
 +              uiBlockEndAlign(block);
 +                      
 +              uiDefButS(block, ROW,B_MODIFIER_RECALC,"Write Cache",           lx, cy, 75, 19, &pcm->mode, 12.0, ePointCache_Read, 0, 0, "");
 +              uiDefButS(block, ROW,B_MODIFIER_RECALC,"Read Cache",            lx+75, cy, 75,19, &pcm->mode, 12.0, ePointCache_Write, 0, 0, "");
 +              cy -= 20;                       
 +              but = uiDefBut(block, BUT, B_NOP, "Clear Cache",                        lx, cy, 150,19, 0, 0, 0, 0, 0, "");
 +              uiButSetFunc(but, modifiers_pointCacheClearModifier, ob, md);
 +                      
                }
  
                uiBlockEndAlign(block);
@@@ -2245,7 -2217,7 +2250,7 @@@ static void editing_panel_modifiers(Obj
        if(yco < 0) uiNewPanelHeight(block, 204-yco);
  }
  
- static char *make_key_menu(Key *key)
+ static char *make_key_menu(Key *key, int startindex)
  {
        KeyBlock *kb;
        int index= 1;
        str= MEM_mallocN(index*40, "key string");
        str[0]= 0;
        
-       index= 1;
+       index= startindex;
        for (kb = key->block.first; kb; kb=kb->next, index++) {
                sprintf (item,  "|%s%%x%d", kb->name, index);
                strcat(str, item);
@@@ -2301,9 -2273,10 +2306,10 @@@ static void editing_panel_shapes(Objec
        uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
        uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
        uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
-       strp= make_key_menu(key);
-       uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
+       strp= make_key_menu(key, 1);
+       uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
        MEM_freeN(strp);
+       
        uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
        uiClearButLock();
        uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
                uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
                uiBlockEndAlign(block);
        }
-       if(key->type && ob->shapenr!=1)
+       if(key->type && ob->shapenr!=1) {
                uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",     10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
  
+               strp= make_key_menu(key, 0);
+               uiDefButS(block, MENU, B_MODIFIER_RECALC, strp,         160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key");
+               MEM_freeN(strp);
+       }
+       
        if(key->type==0)
                uiDefButS(block, NUM, B_DIFF, "Slurph:",                        10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first");
        
@@@ -3450,9 -3428,6 +3461,9 @@@ void do_latticebuts(unsigned short even
                        if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
                        else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
                        ob->softflag |= OB_SB_REDO;
 +                      if(modifiers_isClothEnabled(ob)) {
 +                              cloth_free_modifier(modifiers_isClothEnabled(ob));
 +                      }
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue(REDRAWVIEW3D, 0);
                }
                        lt = ob->data;
                        resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob);
                        ob->softflag |= OB_SB_REDO;
 +                      if(modifiers_isClothEnabled(ob)) {
 +                              cloth_free_modifier(modifiers_isClothEnabled(ob));
 +                      }
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue(REDRAWVIEW3D, 0);
                }
index 259e82968dad7a57c963dd170ecb117afb190f71,fd2e089e169eefef593b917e6becf8acaa2cedf3..d357ad1bce58224337e2db7bd4a178c15af0b158
@@@ -76,7 -76,6 +76,7 @@@
  #include "BKE_action.h"
  #include "BKE_armature.h"
  #include "BKE_blender.h"
 +#include "BKE_cloth.h"
  #include "BKE_curve.h"
  #include "BKE_constraint.h"
  #include "BKE_depsgraph.h"
@@@ -2694,11 -2693,11 +2694,11 @@@ void autokeyframe_ob_cb_func(Object *ob
        char *actname="";
        
        if (G.flags & G_RECORDKEYS) {
-               if(ob->ipoflag & OB_ACTION_OB)
+               if (ob->ipoflag & OB_ACTION_OB)
                        actname= "Object";
-               if(U.uiflag & USER_KEYINSERTAVAI) {
-                       if(ob->ipo || ob->action) {
+               
+               if (U.uiflag & USER_KEYINSERTAVAI) {
+                       if (ob->ipo || ob->action) {
                                ID *id= (ID *)(ob);
                                
                                if (ob->ipo) {
                                                icu= NULL;
                                }
                                
-                               while(icu) {
+                               while (icu) {
                                        icu->flag &= ~IPO_SELECT;
                                        if (U.uiflag & USER_KEYINSERTNEED)
                                                insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
                        }
                }
                else if (U.uiflag & USER_KEYINSERTNEED) {
-                       if (tmode==TFM_RESIZE) {
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
+                       short doLoc=0, doRot=0, doScale=0;
+                       
+                       /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+                       if (tmode == TFM_TRANSLATION) {
+                               doLoc = 1;
                        }
-                       else if (tmode==TFM_ROTATION) {
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
-                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
+                       else if (tmode == TFM_ROTATION) {
+                               if (G.vd->around == V3D_ACTIVE) {
+                                       if (ob != OBACT)
+                                               doLoc = 1;
+                               }
+                               else if (G.vd->around == V3D_CURSOR)
+                                       doLoc = 1;      
+                               
+                               if ((G.vd->flag & V3D_ALIGN)==0) 
+                                       doRot = 1;
                        }
-                       else if (tmode==TFM_TRANSLATION) {
+                       else if (tmode == TFM_RESIZE) {
+                               if (G.vd->around == V3D_ACTIVE) {
+                                       if (ob != OBACT)
+                                               doLoc = 1;
+                               }
+                               else if (G.vd->around == V3D_CURSOR)
+                                       doLoc = 1;      
+                               
+                               if ((G.vd->flag & V3D_ALIGN)==0)
+                                       doScale = 1;
+                       }
+                       
+                       if (doLoc) {
                                insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
                                insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
                                insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
                        }
+                       if (doRot) {
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
+                       }
+                       if (doScale) {
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
+                               insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
+                       }
                }
                else {
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z, 0);
+                       
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z, 0);
+                       
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y, 0);
                        insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z, 0);
                }
+               
                remake_object_ipos(ob);
                allqueue(REDRAWMARKER, 0);
        }
@@@ -2785,7 -2813,7 +2814,7 @@@ void autokeyframe_pose_cb_func(Object *
                                pchan->bone->flag &= ~BONE_UNKEYED;
                                
                                /* only insert into available channels? */
-                               if(U.uiflag & USER_KEYINSERTAVAI) {
+                               if (U.uiflag & USER_KEYINSERTAVAI) {
                                        bActionChannel *achan; 
                                        
                                        for (achan = act->chanbase.first; achan; achan=achan->next){
                                }
                                /* only insert keyframe if needed? */
                                else if (U.uiflag & USER_KEYINSERTNEED) {
-                                       if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) {
+                                       short doLoc=0, doRot=0, doScale=0;
+                                       
+                                       /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+                                       if (tmode == TFM_TRANSLATION) {
+                                               if (targetless_ik) 
+                                                       doRot= 1;
+                                               else 
+                                                       doLoc = 1;
+                                       }
+                                       else if (tmode == TFM_ROTATION) {
+                                               if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE))
+                                                       doLoc = 1;
+                                                       
+                                               if ((G.vd->flag & V3D_ALIGN)==0) 
+                                                       doRot = 1;
+                                       }
+                                       else if (tmode == TFM_RESIZE) {
+                                               if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE))
+                                                       doLoc = 1;
+                                               
+                                               if ((G.vd->flag & V3D_ALIGN)==0)
+                                                       doScale = 1;
+                                       }
+                                       
+                                       if (doLoc) {
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
                                        }
-                                       if ((tmode==TFM_ROTATION) || ((tmode==TFM_TRANSLATION) && targetless_ik)) {
+                                       if (doRot) {
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
                                        }
-                                       if (tmode==TFM_RESIZE) {
+                                       if (doScale) {
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
                                                insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
@@@ -2889,7 -2941,7 +2942,7 @@@ void special_aftertrans_update(TransInf
        if (t->spacetype==SPACE_VIEW3D)
                EM_automerge(1);
        
-       if(t->spacetype == SPACE_ACTION) {
+       if (t->spacetype == SPACE_ACTION) {
                void *data;
                short datatype;
                
                        DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
                }
        }
-       else if(t->spacetype == SPACE_NLA) {
+       else if (t->spacetype == SPACE_NLA) {
                synchronize_action_strips();
                
                /* cleanup */
                
                recalc_all_ipos();      // bad
        }
-       else if(t->spacetype == SPACE_IPO) {
+       else if (t->spacetype == SPACE_IPO) {
                // FIXME! is there any code from the old transform_ipo that needs to be added back? 
                
                /* resetting slow-parents isn't really necessary when editing sequence ipo's */
                if (G.sipo->blocktype==ID_SEQ)
                        resetslowpar= 0;
        }
-       else if(G.obedit) {
-               if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
+       else if (G.obedit) {
+               if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
                        allqueue(REDRAWBUTSEDIT, 0);
                
                /* table needs to be created for each edit command, since vertices can move etc */
                mesh_octree_table(G.obedit, NULL, 'e');
        }
-       else if( (t->flag & T_POSE) && t->poseobj) {
+       else if ((t->flag & T_POSE) && (t->poseobj)) {
                bArmature *arm;
                bPose   *pose;
                bPoseChannel *pchan;
                short targetless_ik= 0;
+               
                ob= t->poseobj;
                arm= ob->data;
                pose= ob->pose;
                
                /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
                pose->flag |= POSE_DO_UNLOCK;
+               
                /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
-               if(!cancelled && t->mode==TFM_TRANSLATION)
+               if (!cancelled && t->mode==TFM_TRANSLATION)
                        targetless_ik= apply_targetless_ik(ob);
                else {
                        /* not forget to clear the auto flag */
                        }
                }
                
-               if(t->mode==TFM_TRANSLATION)
+               if (t->mode==TFM_TRANSLATION)
                        pose_grab_with_ik_clear(ob);
                        
                /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */
-               if(!cancelled && (t->mode != TFM_DUMMY)) {
+               if (!cancelled && (t->mode != TFM_DUMMY)) {
                        autokeyframe_pose_cb_func(ob, t->mode, targetless_ik);
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                }
-               else if(arm->flag & ARM_DELAYDEFORM) {
+               else if (arm->flag & ARM_DELAYDEFORM) {
                        /* old optimize trick... this enforces to bypass the depgraph */
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        ob->recalc= 0;  // is set on OK position already by recalcData()
                else 
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                
-               if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
+               if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
                        allqueue(REDRAWBUTSEDIT, 0);
                
        }
        else {
                base= FIRSTBASE;
-               while(base) {                                           
 -              while (base) {  
 -                      
++
++              while (base) {                  
++
                        if(base->flag & BA_DO_IPO) redrawipo= 1;
                        
                        ob= base->object;
                        
-                       if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
+                       if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
 +                      else if(modifiers_isClothEnabled(ob)) {
 +                              cloth_free_modifier(modifiers_isClothEnabled(ob));
 +                      }
                        
                        /* Set autokey if necessary */
                        if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {
        
        clear_trans_object_base_flags();
        
-       if(redrawipo) {
+       if (redrawipo) {
                allqueue(REDRAWNLA, 0);
                allqueue(REDRAWACTION, 0);
                allqueue(REDRAWIPO, 0);