svn merge -r 13357:13382 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Thu, 24 Jan 2008 10:53:16 +0000 (10:53 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Thu, 24 Jan 2008 10:53:16 +0000 (10:53 +0000)
1  2 
SConstruct
source/blender/blenkernel/intern/modifier.c
source/blender/makesdna/DNA_userdef_types.h
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/transform_conversions.c

diff --combined SConstruct
index adecfcb5dcf15056e285a3c8ac6c448de519359c,51f925f634b3598f15b0c8dac8bc6e526b41e2bf..1886b6486b8ebc90eb5804bf05813fb8cefe5596
@@@ -179,18 -179,6 +179,18 @@@ if env['BF_NO_ELBEEM'] == 1
      env['CXXFLAGS'].append('-DDISABLE_ELBEEM')
      env['CCFLAGS'].append('-DDISABLE_ELBEEM')
  
 +if env['WITH_BF_OPENMP'] == 1:
 +      if env['OURPLATFORM']=='win32-vc':
 +              env.Append(LINKFLAGS=['/openmp'])
 +              env['CCFLAGS'].append('/openmp')
 +              env['CPPFLAGS'].append('/openmp')
 +              env['CXXFLAGS'].append('/openmp')
 +      else:
 +              env.Append(LINKFLAGS=['-lgomp'])
 +              env['CCFLAGS'].append('-fopenmp')
 +              env['CPPFLAGS'].append('-fopenmp')
 +              env['CXXFLAGS'].append('-fopenmp')
 +
  #check for additional debug libnames
  
  if env.has_key('BF_DEBUG_LIBS'):
@@@ -413,7 -401,7 +413,7 @@@ if env['OURPLATFORM'] in ('win32-vc', '
                          '${LCGDIR}/zlib/lib/zlib.dll',
                          '${LCGDIR}/tiff/lib/libtiff.dll']
      if env['BF_DEBUG']:
-         dllsources.append('${LCGDIR}/python/lib/${BF_PYTHON_LIB}.dll')
+         dllsources.append('${LCGDIR}/python/lib/${BF_PYTHON_LIB}_d.dll')
      else:
          dllsources.append('${LCGDIR}/python/lib/${BF_PYTHON_LIB}.dll')
      if env['OURPLATFORM'] == 'win32-mingw':
index 428c136a7fe7bad1350af77fc54fd2e499e1e248,bd809a00ef00c517263cb989cc48ecafcaf03b41..d18d5ae3fd082f65aefa62cfbedc3e69f107c09f
@@@ -53,7 -53,6 +53,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"
@@@ -75,7 -74,6 +75,7 @@@
  #include "BKE_main.h"
  #include "BKE_anim.h"
  #include "BKE_bad_level_calls.h"
 +#include "BKE_cloth.h"
  #include "BKE_curve.h"
  #include "BKE_customdata.h"
  #include "BKE_global.h"
@@@ -90,7 -88,6 +90,7 @@@
  #include "BKE_object.h"
  #include "BKE_mesh.h"
  #include "BKE_softbody.h"
 +#include "BKE_cloth.h"
  #include "BKE_material.h"
  #include "BKE_particle.h"
  #include "BKE_pointcache.h"
@@@ -4941,263 -4938,6 +4941,263 @@@ 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");
 +      
 +      /* check for alloc failing */
 +      if(!clmd->sim_parms || !clmd->coll_parms)
 +              return;
 +      
 +      cloth_init (clmd);
 +}
 +
 +static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob,
 +               DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
 +{
 +      ClothModifierData *clmd = (ClothModifierData*) md;
 +      DerivedMesh *result=NULL;
 +      
 +      /* check for alloc failing */
 +      if(!clmd->sim_parms || !clmd->coll_parms)
 +              return derivedData;
 +
 +      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;
 +      
 +      /* TODO: this belongs to collision modifier */
 +      if(clmd)
 +      {
 +              for(base = G.scene->base.first; base; base= base->next) 
 +              {
 +                      Object *ob1= base->object;
 +                      if(ob1 != ob)
 +                      {
 +                              ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth);
 +                              if(coll_clmd)
 +                              {                                       
 +                                      if (coll_clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) 
 +                                      {
 +                                              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) 
 +      {
 +              
 +              cloth_free_modifier_extern (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->current_v = 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);
 +              if(collmd->current_v)
 +                      MEM_freeN(collmd->current_v);
 +              
 +              if(collmd->mfaces)
 +                      MEM_freeN(collmd->mfaces);
 +              
 +              collmd->x = NULL;
 +              collmd->xnew = NULL;
 +              collmd->current_x = NULL;
 +              collmd->current_xnew = NULL;
 +              collmd->current_v = NULL;
 +              collmd->time = -1;
 +              collmd->numverts = 0;
 +              collmd->tree = NULL;
 +              collmd->mfaces = 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 );
 +              
 +              // printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
 +              
 +              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->current_v = MEM_dupallocN(collmd->x); // inter-frame
 +
 +                              collmd->numverts = numverts;
 +                              
 +                              collmd->mfaces = dm->dupFaceArray(dm);
 +                              collmd->numfaces = dm->getNumFaces(dm);
 +                              
 +                              // TODO: epsilon
 +                              // create bounding box hierarchy
 +                              collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->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, collmd->x, numverts*sizeof(MVert));
 +                              memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
 +                              
 +                              /* happens on file load (ONLY when i decomment changes in readfile.c */
 +                              if(!collmd->tree)
 +                              {
 +                                      collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sbift);
 +                              }
 +                              else
 +                              {
 +                                      // recalc static bounding boxes
 +                                      bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
 +                              }
 +                      }
 +                      
 +                      collmd->time = current_time;
 +              }
 +              else
 +              {
 +                      collmd->time = current_time;
 +              }
 +      }
 +      
 +      if(dm)
 +              dm->release(dm);
 +}
 +
  /* Boolean */
  
  static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@@ -5513,7 -5253,7 +5513,7 @@@ static DerivedMesh * particleInstanceMo
        MVert *mvert, *orig_mvert;
        int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
        short track=ob->trackflag%3, trackneg;
-       float max_co=0.0, min_co=0.0, temp_co[3];
+       float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
  
        trackneg=((ob->trackflag>2)?1:0);
  
                        if(trackneg)
                                state.time=1.0f-state.time;
                        psys_get_particle_on_path(pimd->ob,psys,first_particle + i/totvert,&state,1);
+                       mv->co[0] = 0.0;
+                       Normalize(state.vel);
+                       
+                       if(state.vel[0] < -0.9999 || state.vel[0] > 0.9999) {
+                               state.rot[0] = 1.0;
+                               state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
+                       }
+                       else {
+                               /* a cross product of state.vel and a unit vector in x-direction */
+                               cross[0] = 0.0f;
+                               cross[1] = -state.vel[2];
+                               cross[2] = state.vel[1];
+                               /* state.vel[0] is the only component surviving from a dot product with a vector in x-direction*/
+                               VecRotToQuat(cross,saacos(state.vel[0]),state.rot);
+                       }
                }
                else{
                        state.time=-1.0;
                        psys_get_particle_state(pimd->ob,psys,i/totvert,&state,1);
-               }
-               /*displace vertice to path location*/
-               if(pimd->flag & eParticleInstanceFlag_Path)
-                       mv->co[0]=0.0;
+               }       
  
                QuatMulVecf(state.rot,mv->co);
                VECADD(mv->co,mv->co,state.co);
@@@ -7007,32 -6761,6 +7021,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;
@@@ -7292,13 -7020,6 +7306,13 @@@ int modifiers_isSoftbodyEnabled(Object 
        return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
  }
  
 +int modifiers_isClothEnabled(Object *ob)
 +{
 +      ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
 +
 +      return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
 +}
 +
  int modifiers_isParticleEnabled(Object *ob)
  {
        ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
index 14002daded534cb3514f38bd6ee2a3b58d0d6ab5,b22966e61d85dc3828e132ed1d74615cc6b373ab..6238b878c74118e8f934fb4f99a8af5155eff3a5
@@@ -64,7 -64,6 +64,6 @@@ typedef struct ThemeUI 
        char but_drawtype;
        char pad[3];
        char iconfile[80];      // FILE_MAXFILE length
  } ThemeUI;
  
  /* try to put them all in one, if needed a special struct can be created as well
@@@ -107,14 -106,20 +106,20 @@@ typedef struct ThemeSpace 
        char editmesh_active[4]; 
  } ThemeSpace;
  
  /* set of colors for use as a custom color set for Objects/Bones wire drawing */
  typedef struct ThemeWireColor {
-       char    unselected[3];
-       char    selected[3];
-       char    active[3];
-       char    pad[7];
+       char    solid[4];
+       char    select[4];
+       char    active[4];
+       
+       short   flag;
+       short   pad;
  } ThemeWireColor; 
  
+ /* flags for ThemeWireColor */
+ #define TH_WIRECOLOR_CONSTCOLS        (1<<0)
  /* A theme */
  typedef struct bTheme {
        struct bTheme *next, *prev;
@@@ -260,7 -265,6 +265,7 @@@ extern UserDef U; /* from usiblender.c 
  // old flag for #define USER_KEYINSERTNEED            (1 << 19)
  #define USER_ZOOM_TO_MOUSEPOS (1 << 20)
  #define USER_SHOW_FPS                 (1 << 21)
 +#define USER_UNDOSAVE         (1 << 22) // flag to signal a write_undo() call after a save (save on exit needed then)  
  
  /* Auto-Keying mode */
        /* AUTOKEY_ON is a bitflag */
index ddecbac1b8d3be0e8bea0dfb5706ff9c739d90fe,b1b948c56e8c451718d89ef80c3ceb0c7e4853e5..d3a474a57a5cb1e6a18f179c65bb68bf5c60a845
@@@ -985,8 -985,6 +985,8 @@@ static uiBlock *modifiers_add_menu(voi
  
                /* Only allow adding through appropriate other interfaces */
                if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
 +              
 +              if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
  
                if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
                   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@@ -1665,7 -1663,7 +1665,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");
                        but= 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);
        }
  
                                height += 20;
                } else if (md->type==eModifierType_Softbody) {
                        height = 31;
 +              } 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_Explode) {
                        height = 94;
                }
 -
                                                        /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
                uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
  
                y -= 18;
  
 -              if (!isVirtual) {
 +              if (!isVirtual && (md->type!=eModifierType_Collision)) {
                        uiBlockBeginAlign(block);
                        if (md->type==eModifierType_ParticleSystem) {
                                but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert",        lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
                                uiButSetFunc(but, modifiers_applyModifier, ob, md);
                        }
                        
 -                      if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
 +                      if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (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);
                        }
@@@ -3626,9 -3617,6 +3626,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);
                }
@@@ -4086,9 -4071,10 +4086,10 @@@ static void editing_panel_armature_type
        uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bone",   155, 87,70,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bones as boxes, showing subdivision and b-splines");
        uiDefButI(block, ROW, REDRAWVIEW3D, "Envelope", 225, 87,85,20, &arm->drawtype, 0, ARM_ENVELOPE, 0, 0, "Draw bones as extruded spheres, showing deformation influence volume");
  
-       uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 67,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
-       uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Draw Names", 110,67,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
-       uiDefButBitI(block, TOGN, ARM_NO_CUSTOM, REDRAWVIEW3D, "Draw Shapes", 210,67,100,20, &arm->flag, 0, 0, 0, 0, "Draw custom bone shapes");
+       uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Axes", 10, 67,75,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
+       uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Names", 85,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
+       uiDefButBitI(block, TOGN, ARM_NO_CUSTOM, REDRAWVIEW3D, "Shapes", 160,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw custom bone shapes");
+       uiDefButBitI(block, TOG, ARM_COL_CUSTOM, REDRAWVIEW3D, "Colors", 235,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw custom bone colors (colors are set per Bone Group)");
        
        uiBlockEndAlign(block);
        
@@@ -5182,7 -5168,19 +5183,19 @@@ static void editing_panel_links(Object 
                                                uiDefIconBut(block, BUT, B_POSEGRP_REMOVE, VICON_X, xco+140-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Pose Group");
                                                
                                                /* set custom color set */
-                                               uiDefButI(block, MENU,B_POSEGRP_RECALC, "Custom Color Set%t|GrpCol: [None]%x0", xco,65,140,19, &grp->customCol, 0.0, 0.0, 0.0, 0.0, "Set of Custom Colors to shade Group's bones with. (NOT YET FUNCTIONAL)");
+                                               uiDefButI(block, NUM,B_POSEGRP_RECALC, "GroupColor: ", xco,65,110,19, &grp->customCol, 0, 20, 0.0, 0.0, "Index of set of Custom Colors to shade Group's bones with. 0 = Use Default Color Scheme");                                             
+                                               if (grp->customCol) {
+                                                       bTheme *btheme= U.themes.first;
+                                                       ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)];
+                                                       
+                                                       uiSetButLock(1, "To change these colors, see Themes -> Bone Color Sets");
+                                                       
+                                                       uiDefButC(block, COL, B_POSEGRP_RECALC, "",             xco+110, 65, 10, 19, col_set->solid, 0, 0, 0, 0, "Color to use for surface of bones. See current theme in Info Window.");
+                                                       uiDefButC(block, COL, B_POSEGRP_RECALC, "",             xco+120, 65, 10, 19, col_set->select, 0, 0, 0, 0, "Color to use for 'selected' bones. See current theme in Info Window.");
+                                                       uiDefButC(block, COL, B_POSEGRP_RECALC, "",             xco+130, 65, 10, 19, col_set->active, 0, 0, 0, 0, "Color to use for 'active' bones. See current theme in Info Window.");
+                                                       
+                                                       uiClearButLock();
+                                               }
                                        }
                                uiBlockEndAlign(block);
                        }
index a064e266d6d8c15aa2394f5e9ee80f9f91983ab5,1e90c623498e25bf1f4b314e8af7d2a0d328bc60..0b30f0b3cbaa846acf8600ad6126faa12a21d3a6
@@@ -47,7 -47,6 +47,7 @@@
  #include "DNA_scene_types.h"
  
  #include "BKE_action.h"
 +#include "BKE_cloth.h"
  #include "BKE_global.h"
  #include "BKE_main.h"
  #include "BKE_library.h"
@@@ -90,7 -89,6 +90,7 @@@
  #include "DNA_action_types.h"
  #include "DNA_armature_types.h"
  #include "DNA_camera_types.h"
 +#include "DNA_cloth_types.h"
  #include "DNA_constraint_types.h"
  #include "DNA_curve_types.h"
  #include "DNA_effect_types.h"
@@@ -604,13 -602,27 +604,27 @@@ static void draw_constraint (uiBlock *b
                uiBlockBeginAlign(block);
                        uiBlockSetEmboss(block, UI_EMBOSS);
                        
-                       if (prev_proxylock == 0) {
+                       if ((prev_proxylock) || (con->prev==NULL)) {
+                               /* don't draw 'button' behind arrow if disabled (and button doesn't do anything anyways) */
+                               uiBlockSetEmboss(block, UI_EMBOSSN);
+                               uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
+                               uiBlockSetEmboss(block, UI_EMBOSS);
+                       }
+                       else {
                                but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
                                uiButSetFunc(but, constraint_moveUp, ob, con);
                        }
                        
-                       but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
-                       uiButSetFunc(but, constraint_moveDown, ob, con);
+                       if (con->next) {
+                               but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
+                               uiButSetFunc(but, constraint_moveDown, ob, con);
+                       }
+                       else {
+                               /* don't draw 'button' behind arrow if no next constraint (it doesn't do anything anyways) */
+                               uiBlockSetEmboss(block, UI_EMBOSSN);
+                               uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
+                               uiBlockSetEmboss(block, UI_EMBOSS);
+                       }
                uiBlockEndAlign(block);
                
                
@@@ -2287,56 -2299,6 +2301,56 @@@ void do_object_panels(unsigned short ev
                if(ob->ipo) ob->ipo->showkey= (ob->ipoflag & OB_DRAWKEY)?1:0;
                allqueue(REDRAWVIEW3D, 0);
                break;
 +      case B_CLOTH_CLEARCACHEALL:
 +      {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +              if(clmd)
 +              {
 +                      CFRA= 1;
 +                      update_for_newframe_muted();
 +                      DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); 
 +                      cloth_clear_cache(ob, clmd, 1); 
 +                      allqueue(REDRAWBUTSOBJECT, 0);
 +                      allqueue(REDRAWVIEW3D, 0);
 +              }       
 +      }
 +      break;  
 +      case B_CLOTH_CLEARCACHEFRAME:
 +      {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +              if(clmd)
 +              {
 +                      cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra + 1.0));
 +                      allqueue(REDRAWBUTSOBJECT, 0);
 +              }
 +      }
 +      break;  
 +      case B_CLOTH_CHANGEPREROLL:
 +      {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +              if(clmd)
 +              {
 +                      if(clmd->sim_parms->cache)
 +                      {
 +                              CFRA= 1;
 +                              update_for_newframe_muted();
 +                              DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); 
 +                              allqueue(REDRAWBUTSOBJECT, 0);
 +                              allqueue(REDRAWVIEW3D, 0);
 +                      }
 +              }
 +      }
 +      break;  
 +      case B_CLOTH_RENEW:
 +      {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +      
 +              if(clmd)
 +              {
 +                      clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
 +              }
 +      }
 +      break;
                
        default:
                if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
@@@ -3154,31 -3116,10 +3168,31 @@@ static void field_testTexture(char *nam
        }
        *idpp = 0;
  }
 +
 +/* Panel for collision */
 +static void object_collision__enabletoggle ( void *ob_v, void *arg2 )
 +{
 +      Object *ob = ob_v;
 +      ModifierData *md = modifiers_findByType ( ob, eModifierType_Collision );
 +
 +      if ( !md )
 +      {
 +              md = modifier_new ( eModifierType_Collision );
 +              BLI_addhead ( &ob->modifiers, md );
 +      }
 +      else
 +      {
 +              BLI_remlink ( &ob->modifiers, md );
 +              modifier_free ( md );
 +              allqueue(REDRAWBUTSEDIT, 0);
 +      }
 +}
 +
  /* Panels for particle interaction settings */
  static void object_panel_deflection(Object *ob)
  {
        uiBlock *block;
 +      uiBut *but;
  
        block= uiNewBlock(&curarea->uiblocks, "object_panel_deflection", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Deflection", "Physics", 0, 0, 318, 204)==0) return;
        if(ob->pd && ob->type==OB_MESH) {
                PartDeflect *pd= ob->pd;
                
 -              uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
 +              but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
 +              uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
 +              
                if(pd->deflect) {
                        uiDefBut(block, LABEL, 0, "Particles",                  160,140,75,20, NULL, 0.0, 0, 0, 0, "");
                        uiDefButBitS(block, TOG, PDEFLE_KILL_PART, B_DIFF, "Kill",235,140,75,20, &pd->flag, 0, 0, 0, 0, "Kill collided particles");
@@@ -3472,7 -3411,7 +3486,7 @@@ static char sbsolvers[] = "SIF  semi im
  static char sbsolvers[] = "SOFT  step size controlled midpoint(1rst choice for real softbodies)%x0";
  #endif
  
- static void object_softbodies_II(Object *ob)
+ static void object_softbodies_collision(Object *ob)
  {
        SoftBody *sb=ob->soft;
        uiBlock *block;
                ob->pd->pdef_sbift  = 0.2f;
                ob->pd->pdef_sboft  = 0.02f;
        }
-       block= uiNewBlock(&curarea->uiblocks, "object_softbodies_II", UI_EMBOSS, UI_HELV, curarea->win);
-       uiNewPanelTabbed("Soft Body", "Physics");
-       if(uiNewPanel(curarea, block, "Soft Body Col&Solv", "Physics", 651, 0, 318, 204)==0) return;
+       block= uiNewBlock(&curarea->uiblocks, "object_softbodies_collision", UI_EMBOSS, UI_HELV, curarea->win);
+       // uiNewPanelTabbed("Soft Body", "Physics"); /*don't really want it tabbed first */
+       if(uiNewPanel(curarea, block, "Soft Body Collision", "Physics", 651, 0, 318, 204)==0) return;
  
        uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
  
                        uiBlockEndAlign(block);
                        /*SOLVER SETTINGS*/
                        uiBlockBeginAlign(block);
+                       /* done in another panel now*/
+                       /*
                        uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver");
-                       /*some have adapive step size - some not*/
-                       sb->solver_ID = 0; /* ugly hack to prepare peach freeze */
+                       sb->solver_ID = 0; 
                        switch (sb->solver_ID) {
                        case 0:
                        case 1:
                                uiDefButS(block, NUM, B_DIFF, "Steps:", 10,80,100,20, &sb->minloops,  1.00,  30000.0, 10, 0, "Solver steps/frame ");
                                uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
                        }
+                       */
  
  
                }
        }
        uiBlockEndAlign(block);
  }
+ static void object_softbodies_solver(Object *ob)
+ {
+       SoftBody *sb=ob->soft;
+       uiBlock *block;
+       static int val;
+       short *softflag=&ob->softflag, psys_cur=0, adaptive_mode=0;
+       int ob_has_hair=psys_ob_has_hair(ob);
+     if(!_can_softbodies_at_all(ob)) return;
+       block= uiNewBlock(&curarea->uiblocks, "object_softbodies_solver", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Soft Body Solver", "Physics", 651, 0, 318, 204)==0) return;
+       uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+     /* doubt that is really needed here but for now */ 
+       if(ob_has_hair) {
+               if(PE_get_current_num(ob) >= 0) {
+                       ParticleSystem *psys = PE_get_current(ob);
+                       if(psys) {
+                               sb = psys->soft;
+                               softflag = &psys->softflag;
+                               psys_cur = 1;
+                       }
+               }
+       }
+       if(psys_cur) {
+               if(*softflag & OB_SB_ENABLE)
+                       val = 1;
+               else
+                       val = 0;
+       }
+       else
+               val = modifiers_isSoftbodyEnabled(ob);
+       if(!val) { 
+               uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
+               if(psys_cur){
+                       uiDefBut(block, LABEL, 0, "Hair is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); 
+               }
+               else {
+                       uiDefBut(block, LABEL, 0, "Object is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); 
+               }
+       }
+       else{ 
+               if ((ob->type==OB_MESH)||(ob->type==OB_CURVE) ) {
+                       /*SOLVER SETTINGS*/
+                       uiBlockBeginAlign(block);
+                       uiDefBut(block, LABEL, 0, "Solver select",10,200,300,20, NULL, 0.0, 0, 0, 0, ""); 
+                       uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver (choose 1 of 1 i was working on some other but failed *sigh* BM) ");
+                       uiBlockEndAlign(block);
+                       
+                       /*some have adapive step size - some not*/
+                       sb->solver_ID = 0; /* ugly hack to prepare peach freeze */
+                       switch (sb->solver_ID) {
+                       case 0:
+                       case 1:
+                               {adaptive_mode = 1; break;}
+                       case 3:
+                               {adaptive_mode = 0; break;}
+                       default: printf("SB_solver?\n"); // should never happen
+                       }
+                       if(adaptive_mode){
+                               uiBlockBeginAlign(block);
+                           uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefButF(block, NUM, B_DIFF, "Error Lim:",     10,140,280,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed");
+                               uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"V", 290,140,20,20, &sb->solverflags,  0,  0, 0, 0, "Use velocities for automagic step sizes");
+                               uiDefButS(block, NUM, B_DIFF, "MinS:", 10,120,150,20, &sb->minloops,  0.00,  30000.0, 10, 0, "Minimal # solver steps/frame ");
+                               uiDefButS(block, NUM, B_DIFF, "MaxS:", 160,120,150,20, &sb->maxloops,  0.00,  30000.0, 10, 0, "Maximal # solver steps/frame ");
+                               uiBlockEndAlign(block);
+                               uiBlockBeginAlign(block);
+                       uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefButS(block, NUM, B_DIFF, "Choke:", 10,80,150,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
+                               uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,80,150,20, &sb->fuzzyness,  1.00,  100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable");
+                               uiBlockEndAlign(block);
+                               
+                               uiBlockBeginAlign(block);
+                               uiDefBut(block, LABEL, 0, "Diagnosis stuff",10,60,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"Print Performance to Console", 10,40,300,20, &sb->solverflags,  0,  0, 0, 0, "Turn on SB diagnose console prints");                              
+                               uiBlockEndAlign(block);
+                       } 
+                       else{
+                               uiBlockEndAlign(block);
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness,  1.00,  100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable");
+                               uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags,  0,  0, 0, 0, "Turn on SB diagnose console prints");
+                               uiBlockEndAlign(block);
+                               uiDefButS(block, NUM, B_DIFF, "Steps:", 10,80,100,20, &sb->minloops,  1.00,  30000.0, 10, 0, "Solver steps/frame ");
+                               uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
+                       }
+       uiBlockEndAlign(block);
+               }
+               //uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
+       }
+       uiBlockEndAlign(block);
+ }
  
  static void sb_clear_cache(void *ob_v, void *actsoft_v)
  {
@@@ -4908,220 -4946,6 +5021,220 @@@ errMessage
  #endif // DISABLE_ELBEEM
  }
  
 +/* Panel for cloth */
 +static void object_cloth__enabletoggle(void *ob_v, void *arg2)
 +{
 +      Object *ob = ob_v;
 +      ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
 +
 +      if (!md) {
 +              md = modifier_new(eModifierType_Cloth);
 +              BLI_addhead(&ob->modifiers, md);
 +      }
 +      else {
 +              BLI_remlink(&ob->modifiers, md);
 +              modifier_free(md);
 +      }
 +
 +      allqueue(REDRAWBUTSEDIT, 0);
 +}
 +
 +
 +static void object_panel_cloth(Object *ob)
 +{
 +      uiBlock *block;
 +      uiBut *but;
 +      static int val, val2;
 +      ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +      
 +      block= uiNewBlock(&curarea->uiblocks, "object_cloth", UI_EMBOSS, UI_HELV, curarea->win);
 +      if(uiNewPanel(curarea, block, "Cloth ", "Physics", 640, 0, 318, 204)==0) return;
 +      uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
 +      
 +      val = (clmd ? 1:0);
 +
 +      but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth",  10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth");
 +
 +      uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL);
 +      uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
 +      
 +      if(clmd)
 +      {
 +              int defCount;
 +              char *clvg1, *clvg2;
 +              char clmvg [] = "Weight Paint Groups%t|";
 +
 +              val2=0;
 +              
 +              /* GENERAL STUFF */
 +              uiClearButLock();
 +              uiBlockBeginAlign(block);
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:",       10,170,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:",         160,170,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)");
 +              uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:",           10,150,150,20, &clmd->sim_parms->stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
 +              uiBlockEndAlign(block);
 +              uiBlockBeginAlign(block);
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:",       160,150,150,20, &clmd->sim_parms->Cdis, 0.0, 10.0, 10, 0, "Spring damping");
 +              uiDefButF(block, NUM, B_DIFF, "Air Damp:",         10,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down");
 +              uiBlockEndAlign(block);                 
 +              
 +              uiClearButLock();
 +              
 +              uiBlockBeginAlign(block);
 +              uiDefBut(block, LABEL, 0, "Gravity:",  10,100,60,20, NULL, 0.0, 0, 0, 0, "");
 +              // uiClearButLock();
 +              
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "X:",         70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:",         150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
 +              uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:",         230,100,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
 +              uiBlockEndAlign(block);
 +              
 +              /* GOAL STUFF */
 +              uiBlockBeginAlign(block);
 +              
 +              
 +              uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Pinning of cloth", 10,70,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
 +              
 +              if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (BLI_countlist (&ob->defbase) > 0))
 +              {
 +                      if(ob->type==OB_MESH) 
 +                      {
 +                              
 +                              defCount = sizeof (clmvg);
 +                              clvg1 = get_vertexgroup_menustr (ob);
 +                              clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgMS");
 +                              if (! clvg2) {
 +                                      printf ("draw_modifier: error allocating memory for cloth vertex group menu string.\n");
 +                                      return;
 +                              }
 +                              defCount = BLI_countlist (&ob->defbase);
 +                              if (defCount == 0) 
 +                              {
 +                                      clmd->sim_parms->vgroup_mass = 0;
 +                              }
 +                              else
 +                              {
 +                                      if(!clmd->sim_parms->vgroup_mass)
 +                                              clmd->sim_parms->vgroup_mass = 1;
 +                                      else if(clmd->sim_parms->vgroup_mass > defCount)
 +                                              clmd->sim_parms->vgroup_mass = defCount;
 +                              }
 +                                                      
 +                              sprintf (clvg2, "%s%s", clmvg, clvg1);
 +                              
 +                              uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2,    160,70,150,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");
 +                              MEM_freeN (clvg1);
 +                              MEM_freeN (clvg2);
 +                      }
 +                      
 +                      uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:",      10,50,150,20, &clmd->sim_parms->goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness");
 +                      uiDefBut(block, LABEL, 0, " ",  160,50,150,20, NULL, 0.0, 0, 0, 0, "");
 +                      /*
 +                      // nobody is changing these ones anyway
 +                      uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict  , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction");
 +                      uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:",          10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range");
 +                      uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:",          160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range");
 +                      */
 +              }
 +              else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
 +              {
 +                      uiDefBut(block, LABEL, 0, " ",  160,70,150,20, NULL, 0.0, 0, 0, 0, "");
 +                      uiDefBut(block, LABEL, 0, "No vertex group for pinning available.",  10,50,300,20, NULL, 0.0, 0, 0, 0, "");
 +              }
 +              
 +              uiBlockEndAlign(block); 
 +              
 +              /*
 +              // no tearing supported anymore since modifier stack restrictions 
 +              uiBlockBeginAlign(block);
 +              uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing",        10,0,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object");
 +              
 +              if (clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)
 +              {
 +              uiDefButI(block, NUM, B_DIFF, "Max extent:",       160,0,150,20, &clmd->sim_parms->maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut");
 +      }
 +              
 +              uiBlockEndAlign(block); 
 +              */
 +      }
 +      
 +      uiBlockEndAlign(block);
 +      
 +      uiBlockEndAlign(block);
 +}
 +
 +static void object_panel_cloth_II(Object *ob)
 +{
 +      uiBlock *block;
 +      ClothModifierData *clmd = NULL;
 +
 +      block= uiNewBlock(&curarea->uiblocks, "object_cloth_II", UI_EMBOSS, UI_HELV, curarea->win);
 +      uiNewPanelTabbed("Cloth ", "Physics");
 +      if(uiNewPanel(curarea, block, "Cloth Cache/Collisions", "Physics", 651, 0, 318, 204)==0) return;
 +
 +      uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
 +      
 +      clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +      
 +      if(clmd)
 +      {
 +              // char str[128];
 +              
 +              uiDefButI(block, NUM, B_DIFF, "First Frame:",           10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts");
 +              uiDefButI(block, NUM, B_DIFF, "Last Frame:",            160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops");
 +              
 +              uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, "");
 +              
 +              /* correct spelling if only 1 frame cacheed --> only gimmick  */
 +              /*
 +              if(length-clmd->sim_parms->preroll>1)
 +              sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length);
 +              else
 +              sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length);
 +              */
 +              
 +              if (!G.relbase_valid)
 +              {
 +                      uiDefBut(block, LABEL, 0, "Cache deactivated until file is saved.",  10,120,300,20, NULL, 0.0, 0, 0, 0, "");
 +                      uiDefBut(block, LABEL, 0, " ",  10,100,300,40, NULL, 0.0, 0, 0, 0, "");
 +              }
 +              else
 +              {
 +                      uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache & Enable Cache Editing",   10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed. This also enabled the cache beeing edited in editmode.");
 +                      
 +                      if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT))
 +                      {
 +                              uiDefBut(block, LABEL, 0, "Clear cache:",  10,100,90,20, NULL, 0.0, 0, 0, 0, "");
 +                              uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 100, 100,100,20, NULL, 0.0, 0.0, 10, 0, "Free ALL cloth cache without preroll");
 +                              uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 200, 100,110,20, NULL, 0.0, 0.0, 10, 0, "Free cloth cache starting from next frame");  
 +                              uiDefBut(block, LABEL, 0, " ",  10,80,300,20, NULL, 0.0, 0, 0, 0, "");
 +                      }
 +                      else
 +                      {
 +                              uiDefBut(block, LABEL, 0, " ",  10,100,300,40, NULL, 0.0, 0, 0, 0, "");
 +                      }
 +              }
 +
 +              /*
 +              if(length>1) // B_CLOTH_CHANGEPREROLL
 +              uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms->preroll, 0, length-1, 1, 0, "Simulation starts on this frame");        
 +              else
 +              uiDefBut(block, LABEL, 0, " ",  10,80,145,20, NULL, 0.0, 0, 0, 0, "");
 +              */
 +
 +              uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions",       10,60,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object");
 +              if (clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED)
 +              {
 +                      uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:",      160,60,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in");
 +              }
 +              else
 +                      uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, "");    
 +      }
 +      
 +      uiBlockEndAlign(block);
 +      
 +}
 +
  void object_panels()
  {
        Object *ob;
@@@ -5149,9 -4973,8 +5262,10 @@@ void physics_panels(
                        object_panel_deflection(ob);
                object_panel_fields(ob);
                object_softbodies(ob);
-               object_softbodies_II(ob);
+               object_softbodies_collision(ob);
+               object_softbodies_solver(ob);
 +              object_panel_cloth(ob);
 +              object_panel_cloth_II(ob);
                object_panel_fluidsim(ob);
        }
  }
index 5d2e7cd741054480e49e278f0011f3ea26e36d52,12419c94c0f2f2ae65f8e8e3805bda6f4ae289c2..e69fabdd926db836560cb327c6f609724e14ba15
@@@ -77,7 -77,6 +77,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"
@@@ -561,7 -560,7 +561,7 @@@ static void add_pose_transdata(TransInf
                if (constraints_list_needinv(t, &pchan->constraints)) {
                        Mat3CpyMat4(tmat, pchan->constinv);
                        Mat3Inv(cmat, tmat);
-                       Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, cmat, omat, 0,0,0,0);    // dang mulserie swaps args
+                       Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0);    // dang mulserie swaps args
                }
                else
                        Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0);    // dang mulserie swaps args
                if (constraints_list_needinv(t, &pchan->constraints)) {
                        Mat3CpyMat4(tmat, pchan->constinv);
                        Mat3Inv(cmat, tmat);
-                       Mat3MulSerie(td->mtx, pchan->bone->bone_mat, cmat, omat, 0, 0,0,0,0);    // dang mulserie swaps args
+                       Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0);    // dang mulserie swaps args
                }
                else 
                        Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat);  // Mat3MulMat3 has swapped args! 
@@@ -3396,18 -3395,13 +3396,18 @@@ void special_aftertrans_update(TransInf
        }
        else {
                base= FIRSTBASE;
 -              while (base) {  
 -                      
 +
 +              while (base) {                  
 +
                        if(base->flag & BA_DO_IPO) redrawipo= 1;
                        
                        ob= base->object;
                        
                        if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
 +                      else if((ob == OBACT) && modifiers_isClothEnabled(ob)) {
 +                              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +                              clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
 +                      }
                        
                        /* Set autokey if necessary */
                        if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {