Cloth: fixed completely useless/wrong friction force; changed some initial settings
[blender.git] / source / blender / src / buttons_object.c
index fc562229d7e0fcd9a5a006b7af659b1049ba00fa..da06351404ec9203050f29ad1eaf1cfa8f6b6fb4 100644 (file)
@@ -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"
@@ -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"
@@ -582,12 +584,14 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                uiBlockSetEmboss(block, UI_EMBOSS);
        }
        else {
-               short prev_proxylock;
+               short prev_proxylock, show_upbut, show_downbut;
                
                /* Up/Down buttons: 
                 *      Proxy-constraints are not allowed to occur after local (non-proxy) constraints
                 *      as that poses problems when restoring them, so disable the "up" button where
-                *      it may cause this situation.
+                *      it may cause this situation. 
+                *
+                *      Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 
                 */
                if (proxylocked_constraints_owner(ob, pchan)) {
                        if (con->prev) {
@@ -598,21 +602,25 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                }
                else
                        prev_proxylock= 0;
-                
-               uiBlockBeginAlign(block);
-                       uiBlockSetEmboss(block, UI_EMBOSS);
-                       
-                       /* only show buttons that will do anything valid */
-                       if ((prev_proxylock==0) && (con->prev)) {
-                               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);
-                       }
                        
-                       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);
-                       }
-               uiBlockEndAlign(block);
+               show_upbut= ((prev_proxylock == 0) && (con->prev));
+               show_downbut= (con->next) ? 1 : 0;
+               
+               if (show_upbut || show_downbut) {
+                       uiBlockBeginAlign(block);
+                               uiBlockSetEmboss(block, UI_EMBOSS);
+                               
+                               if (show_upbut) {
+                                       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);
+                               }
+                               
+                               if (show_downbut) {
+                                       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);
+                               }
+                       uiBlockEndAlign(block);
+               }
                
                
                /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
@@ -653,7 +661,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                menustr = buildmenu_pyconstraints(data->text, &pyconindex);
                                but2 = uiDefButI(block, MENU, B_CONSTRAINT_TEST, menustr,
                                      *xco+120, *yco-24, 150, 20, &pyconindex,
-                                     0.0, 1.0, 0, 0, "Set the Script Constraint to use");
+                                     00, 0, 0, "Set the Script Constraint to use");
                                uiButSetFunc(but2, validate_pyconstraint_cb, data, &pyconindex);
                                MEM_freeN(menustr);     
                                
@@ -665,8 +673,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                                short yoffset= ((tarnum-1) * 38);
                                                
                                                /* target label */
-                                               sprintf(tarstr, "Target %02d:", tarnum);
-                                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, tarstr, *xco+45, *yco-(48+yoffset), 80, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                                               sprintf(tarstr, "Target %d:", tarnum);
+                                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, tarstr, *xco+45, *yco-(48+yoffset), 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
                                                
                                                /* target space-selector - per target */
                                                if (is_armature_target(ct->tar)) {
@@ -1267,12 +1275,12 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                
                                uiBlockBeginAlign(block);
                                        if (is_armature_target(data->tar)) {
-                                               uiDefButF(block, BUTM, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->orglength, 0.0, 0, 0, 0, "Recalculate RLength");
+                                               uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->orglength, 0.0, 0, 0, 0, "Recalculate RLength");
                                                uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Rest Length:", *xco+18, *yco-60,139,18, &data->orglength, 0.0, 100, 0.5, 0.5, "Length at Rest Position");
-                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Head/Tail:", *xco+155, *yco-60,97,18, &con->headtail, 0.0, 1, 0.1, 0.1, "Target along length of bone: Head=0, Tail=1");
+                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Head/Tail:", *xco+155, *yco-60,98,18, &con->headtail, 0.0, 1, 0.1, 0.1, "Target along length of bone: Head=0, Tail=1");
                                        }
                                        else {
-                                               uiDefButF(block, BUTM, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->orglength, 0.0, 0, 0, 0, "Recalculate RLength");
+                                               uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->orglength, 0.0, 0, 0, 0, "Recalculate RLength");
                                                uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Rest Length:", *xco+18, *yco-60, 237, 18, &data->orglength, 0.0, 100, 0.5, 0.5, "Length at Rest Position");
                                        }
                                uiBlockEndAlign(block);
@@ -1626,7 +1634,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                                uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
                                        }
                                        else if (is_geom_target(data->tar)) {
-                                               but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+                                               but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
                                                uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
                                        }
                                        else {
@@ -2214,7 +2222,7 @@ void do_object_panels(unsigned short event)
        case B_DUPLI_VERTS:
                ob->transflag &= ~(OB_DUPLIFRAMES|OB_DUPLIFACES|OB_DUPLIGROUP);
                DAG_scene_sort(G.scene);
-               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA|OB_RECALC_OB);
                allqueue(REDRAWVIEW3D, 0);
                allqueue(REDRAWBUTSOBJECT, 0);
                break;
@@ -2345,6 +2353,78 @@ void do_object_panels(unsigned short event)
                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)
+               {
+                       // do nothing in editmode
+                       if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
+                               break;
+                       
+                       /* force freeing because user wants */
+                       clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE;
+                       
+                       /*user wants to free all, so free whole cloth, this helps to start sim at later frame */
+                       clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
+                       
+                       CFRA= 1;
+                       update_for_newframe_muted();
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); 
+                       cloth_clear_cache(ob, clmd, 0); 
+                       allqueue(REDRAWBUTSOBJECT, 0);
+                       allqueue(REDRAWVIEW3D, 0);
+               }       
+       }
+       break;  
+       case B_CLOTH_CLEARCACHEFRAME:
+       {
+               ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+               if(clmd)
+               {
+                       // do nothing in editmode
+                       if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
+                               break;
+                       
+                       /* force freeing because user wants */
+                       clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE;
+                       
+                       cloth_clear_cache(ob, clmd, MAX2(0.0,G.scene->r.cfra)); 
+                       // 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)
+               {
+                       // do nothing in editmode
+                       if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
+                               break;
+                       
+                       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;
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); 
+                       allqueue(REDRAWBUTSOBJECT, 0);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+       }
+       break;
                
        default:
                if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
@@ -2412,8 +2492,7 @@ static void group_ob_rem(void *gr_v, void *ob_v)
 {
        Object *ob= OBACT;
        
-       rem_from_group(gr_v, ob);
-       if(find_group(ob, NULL)==NULL) {
+       if(rem_from_group(gr_v, ob) && find_group(ob, NULL)==NULL) {
                ob->flag &= ~OB_FROMGROUP;
                BASACT->flag &= ~OB_FROMGROUP;
        }
@@ -3012,6 +3091,10 @@ void do_effects_panels(unsigned short event)
                        allqueue(REDRAWOOPS, 0);
                }
                /* no break! */
+       case B_PART_REDRAW_DEPS:
+               if(event == B_PART_REDRAW_DEPS)
+                       DAG_scene_sort(G.scene);
+               /* no break! */
        case B_PART_REDRAW:
                nr=0;
                for(psys=ob->particlesystem.first; psys; psys=psys->next){
@@ -3162,10 +3245,38 @@ static void field_testTexture(char *name, ID **idpp)
        }
        *idpp = 0;
 }
+
+/* Panel for collision */
+static void object_collision__enabletoggle ( void *ob_v, void *arg2 )
+{
+       Object *ob = ob_v;
+       PartDeflect *pd= ob->pd;
+       ModifierData *md = modifiers_findByType ( ob, eModifierType_Collision );
+       
+       if ( !md )
+       {
+               if(pd && (pd->deflect))
+               {
+                       md = modifier_new ( eModifierType_Collision );
+                       BLI_addhead ( &ob->modifiers, md );
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       allqueue(REDRAWBUTSEDIT, 0);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+       }
+       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;
@@ -3185,7 +3296,9 @@ static void object_panel_deflection(Object *ob)
        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");
@@ -3198,7 +3311,7 @@ static void object_panel_deflection(Object *ob)
                        uiDefButF(block, NUM, B_DIFF, "Permeability: ", 160,80,150,20, &pd->pdef_perm, 0.0, 1.0, 10, 0, "Chance that the particle will pass through the mesh");
                        uiBlockEndAlign(block);
                        
-                       uiDefBut(block, LABEL, 0, "Soft Body",                  160,60,150,20, NULL, 0.0, 0, 0, 0, "");
+                       uiDefBut(block, LABEL, 0, "Soft Body / Cloth",                  160,60,150,20, NULL, 0.0, 0, 0, 0, "");
 
                        uiBlockBeginAlign(block);
                        uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:",       160,40,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision");
@@ -3262,9 +3375,9 @@ static void object_panel_fields(Object *ob)
                        sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d", 
                                        PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC);
 
-                       if(pd->forcefield==PFIELD_FORCE) tipstr= "Particle attracts or repels particles";
-                       else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of particle Z axis";
-                       else if(pd->forcefield==PFIELD_VORTEX) tipstr= "Particles swirl around Z-axis of the particle";
+                       if(pd->forcefield==PFIELD_FORCE) tipstr= "Particle attracts or repels particles (On shared object layers)";
+                       else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of particle Z axis (On shared object layers)";
+                       else if(pd->forcefield==PFIELD_VORTEX) tipstr= "Particles swirl around Z-axis of the particle (On shared object layers)";
                }
                else{
                        if(ob->type==OB_CURVE)
@@ -3274,10 +3387,10 @@ static void object_panel_fields(Object *ob)
                                sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d", 
                                                PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
 
-                       if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles";
-                       else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis";
-                       else if(pd->forcefield==PFIELD_VORTEX) tipstr= "Particles swirl around Z-axis of the Object";
-                       else if(pd->forcefield==PFIELD_GUIDE) tipstr= "Use a Curve Path to guide particles";
+                       if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles (On shared object layers)";
+                       else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis (On shared object layers)";
+                       else if(pd->forcefield==PFIELD_VORTEX) tipstr= "Particles swirl around Z-axis of the Object (On shared object layers)";
+                       else if(pd->forcefield==PFIELD_GUIDE) tipstr= "Use a Curve Path to guide particles (On shared object layers)";
                }
                
                if(ob->particlesystem.first)
@@ -3299,12 +3412,13 @@ static void object_panel_fields(Object *ob)
                                uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      50,80,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
                        }
                        else {
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Strength: ",     10,140,140,20, &pd->f_strength, -1000, 1000, 10, 0, "Strength of force field");
+                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Strength: ",     10,140,140,20, &pd->f_strength, -1000, 1000, 10, 3, "Strength of force field");
                                
                                if(pd->forcefield == PFIELD_TEXTURE){
                                        uiDefIDPoinBut(block, field_testTexture, ID_TE, B_FIELD_CHANGE, "Texture: ", 10, 120, 140, 20, &pd->tex, "Texture to use as force");
                                        uiDefButBitS(block, TOG, PFIELD_TEX_OBJECT, B_FIELD_CHANGE, "Use Object Co",    10,100,140,20, &pd->flag, 0.0, 0, 0, 0, "Use object/global coordinates for texture");
-                                       uiDefButBitS(block, TOG, PFIELD_TEX_2D, B_FIELD_CHANGE, "2D",   10,80,140,20, &pd->flag, 0.0, 0, 0, 0, "Apply force only in 2d");
+                                       uiDefButBitS(block, TOG, PFIELD_TEX_ROOTCO, B_FIELD_CHANGE, "Root TexCo",       10,80,120,20, &pd->flag, 0.0, 0, 0, 0, "Texture coords from root particle locations");
+                                       uiDefButBitS(block, TOG, PFIELD_TEX_2D, B_FIELD_CHANGE, "2D",   130,80,20,20, &pd->flag, 0.0, 0, 0, 0, "Apply force only in 2d");
                                }
                                else if(pd->forcefield == PFIELD_HARMONIC) 
                                        uiDefButF(block, NUM, B_FIELD_CHANGE, "Damp: ", 10,120,140,20, &pd->f_damp, 0, 10, 10, 0, "Damping of the harmonic force");     
@@ -3316,7 +3430,7 @@ static void object_panel_fields(Object *ob)
                                uiDefButBitS(block, TOG, PFIELD_GUIDE_PATH_ADD, B_FIELD_CHANGE, "Additive",     10,40,140,20, &pd->flag, 0.0, 0, 0, 0, "Based on distance/falloff it adds a portion of the entire path");
                        }
                        else if(pd->forcefield==PFIELD_TEXTURE){
-                               uiDefButS(block, MENU, B_FIELD_CHANGE, "Texture mode%t|RGB%x0|Gradient%x1|Curl%x2",     10,40,140,20, &pd->tex_mode, 0.0, 0.0, 0, 0, "How the texture effect is calculated (RGB & Curl need a RGB texture)");
+                               uiDefButS(block, MENU, B_FIELD_CHANGE, "Texture mode%t|RGB%x0|Gradient%x1|Curl%x2",     10,40,140,20, &pd->tex_mode, 0.0, 0.0, 0, 0, "How the texture effect is calculated (RGB & Curl need a RGB texture else Gradient will be used instead)");
        
                                uiDefButF(block, NUM, B_FIELD_CHANGE, "Nabla:", 10,20,140,20, &pd->tex_nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient and curl calculation");
                        }
@@ -3461,8 +3575,9 @@ static void object_softbodies_collision(Object *ob)
 {
        SoftBody *sb=ob->soft;
        uiBlock *block;
+       uiBut *but = NULL;
        static int val;
-       short *softflag=&ob->softflag, psys_cur=0, adaptive_mode=0;
+       short *softflag=&ob->softflag, psys_cur=0;
        int ob_has_hair=psys_ob_has_hair(ob);
     if(!_can_softbodies_at_all(ob)) return;
        /*bah that is ugly! creating missing data members in UI code*/
@@ -3512,7 +3627,8 @@ static void object_softbodies_collision(Object *ob)
                /* OTHER OBJECTS COLLISION STUFF */
                if (ob->type==OB_MESH){
                        uiBlockBeginAlign(block);
-                       uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to softbody objects");
+                       but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to softbody objects");
+                       uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
                        if(ob->pd->deflect) {
                                uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:",       160,50,150,20, &ob->pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision");
                                uiDefButBitS(block, TOG,OB_SB_COLLFINAL , B_DIFF, "Ev.M.Stack",10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack");
@@ -3546,46 +3662,12 @@ static void object_softbodies_collision(Object *ob)
 
                        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");
-                       sb->solver_ID = 0; 
-                       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){
-                               uiDefButF(block, NUM, B_DIFF, "Error Lim:",     60,100,120,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,"O", 180,100,20,20, &sb->solverflags,  0,  0, 0, 0, "Old Error Calculation");
-                               uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 200,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, "MinS:", 10,80,100,20, &sb->minloops,  0.00,  30000.0, 10, 0, "Minimal # solver steps/frame ");
-                               uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops,  0.00,  30000.0, 10, 0, "Maximal # 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 ");
-                       } 
-                       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 ");
-                       }
-                       */
-
-
                }
                /* OTHER OBJECTS COLLISION STUFF */
                if (ob->type==OB_MESH){
-                       uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to other softbody objects");
+                       but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to other softbody objects");
+                       uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
                        if(ob->pd->deflect) {
                                uiDefButF(block, NUM, B_DIFF, "Damping:",       160,50,150,20, &ob->pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision");
                            uiDefButBitS(block, TOG,OB_SB_COLLFINAL , B_DIFF, "Ev.M.Stack",10,30,150,20, softflag, 0, 0, 0, 0, "Pick collision object from modifier stack");
@@ -3604,12 +3686,12 @@ static void object_softbodies_solver(Object *ob)
        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;
+       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 */ 
+       /* 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);
@@ -3646,9 +3728,8 @@ static void object_softbodies_solver(Object *ob)
                        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");
                        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:
@@ -3659,7 +3740,7 @@ static void object_softbodies_solver(Object *ob)
                        }
                        if(adaptive_mode){
                                uiBlockBeginAlign(block);
-                           uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, "");
+                               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 ");
@@ -3667,13 +3748,13 @@ static void object_softbodies_solver(Object *ob)
                                uiBlockEndAlign(block);
 
                                uiBlockBeginAlign(block);
-                       uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, "");
+                               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, "");
+                               uiDefBut(block, LABEL, 0, "Diagnosis",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);
                        } 
@@ -3687,10 +3768,9 @@ static void object_softbodies_solver(Object *ob)
                                uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
                        }
 
-       uiBlockEndAlign(block);
+                       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);
 }
@@ -3814,7 +3894,7 @@ static void object_softbodies(Object *ob)
                        uiBlockBeginAlign(block);
                        uiDefButF(block, NUM, B_DIFF, "Friction:", 10, 170,150,20, &sb->mediafrict, 0.0, 50.0, 10, 0, "General media friction for point movements");
                        uiDefButF(block, NUM, B_DIFF, "Mass:",     160, 170,150,20, &sb->nodemass , 0.001, 50000.0, 10, 0, str);
-                       uiDefButF(block, NUM, B_DIFF, "Grav:",     10,150,150,20, &sb->grav , 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
+                       uiDefButF(block, NUM, B_DIFF, "Grav:",     10,150,150,20, &sb->grav , -10.0, 10.0, 10, 0, "Apply gravitation to point movement");
                        uiDefButF(block, NUM, B_DIFF, "Speed:",    160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed");
                        uiBlockEndAlign(block);
 
@@ -3860,15 +3940,17 @@ static void object_softbodies(Object *ob)
                                uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads",         110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
                                uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_DIFF, "CEdge",               220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too"); 
                                uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_DIFF, "CFace",               265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning "); 
-                               uiDefButF(block, NUM, B_DIFF, "E Pull:",        10,30,100,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness");
-                               uiDefButF(block, NUM, B_DIFF, "E Push:",        110,30,100,20, &sb->inpush, 0.0,  0.999, 10, 0, "Edge spring stiffness");
+                               uiDefButF(block, NUM, B_DIFF, "E Pull:",        10,30,100,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness when longer than rest length");
+                               uiDefButF(block, NUM, B_DIFF, "E Push:",        110,30,100,20, &sb->inpush, 0.0,  0.999, 10, 0, "Edge spring stiffness when shorter than rest length");
                                uiDefButF(block, NUM, B_DIFF, "E Damp:",        210,30,100,20, &sb->infrict, 0.0,  50.0, 10, 0, "Edge spring friction");
-                               uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and lenght)");
-                               uiDefButS(block, NUM, B_DIFF, "Aero:",     30,10,80,20, &sb->aeroedge,  0.00,  30000.0, 10, 0, "Make edges 'sail'");
+                               
+                               uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and length)");
+                               uiDefButS(block, NUM, B_DIFF, "Aero:",     30,10,60,20, &sb->aeroedge,  0.00,  30000.0, 10, 0, "Make edges 'sail'");
+                           uiDefButS(block, NUM, B_SOFTBODY_CHANGE, "Plas:", 90,10,60,20, &sb->plastic, 0.0,  100.0, 10, 0, "Permanent deform");
                                if(ob->type==OB_MESH) {
-                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Bend:", 110,10,100,20, &sb->secondspring, 0.0,  10.0, 10, 0, "Strenght of Springs over 2 Edges");
+                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Be:", 150,10,80,20, &sb->secondspring, 0.0,  10.0, 10, 0, "Bendig Stiffness");
                                        if (*softflag & OB_SB_QUADS){ 
-                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0,  1.0, 10, 0, "Strenght of Springs over 2 Edges");
+                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Sh:", 230,10,80,20, &sb->shearstiff, 0.0,  1.0, 10, 0, "Shear Stiffness");
                                        }
                                }
                                else sb->secondspring = 0;
@@ -3902,7 +3984,7 @@ static void object_panel_particle_children(Object *ob)
 
        if(part->childtype==0) return;
 
-       if((psys->flag&(PSYS_HAIR_DONE|PSYS_KEYED))==0) {
+       if(part->childtype==PART_CHILD_FACES && (psys->flag&(PSYS_HAIR_DONE|PSYS_KEYED))==0) {
                uiDefBut(block, LABEL, 0, "Hair or keyed",      butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
                uiDefBut(block, LABEL, 0, "particles needed!",  butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
                return;
@@ -3913,7 +3995,9 @@ static void object_panel_particle_children(Object *ob)
        buty -= buth/2;
        
        uiDefButI(block, NUM, B_PART_ALLOC_CHILD, "Amount:", butx,(buty-=buth),butw,buth, &part->child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent");
-       uiDefButI(block, NUM, B_DIFF, "Render Amount:", butx,(buty-=buth),butw,buth, &part->ren_child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent for rendering");
+       if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED))
+               uiDefButI(block, NUM, B_DIFF, "Render Amount:", butx,(buty-=buth),butw,buth, &part->ren_child_nbr, 0.0, MAX_PART_CHILDREN, 0, 0, "Amount of children/parent for rendering");
+
        if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
                uiDefButF(block, NUMSLI, B_PART_DISTR_CHILD, "VParents:",               butx,(buty-=buth),butw,buth, &part->parents, 0.0, 1.0, 1, 3, "Relative amount of virtual parents");
                }
@@ -3934,9 +4018,11 @@ static void object_panel_particle_children(Object *ob)
        buty -= buth/2;
 
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_PART_REDRAW, "Size:",           butx,(buty-=buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size");
-       uiDefButF(block, NUM, B_PART_REDRAW, "Rand:",           butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles");
-       if(part->childtype==PART_CHILD_FACES) {
+       if(part->draw_as != PART_DRAW_PATH) {
+               uiDefButF(block, NUM, B_PART_REDRAW, "Size:",           butx,(buty-=buth),butw/2,buth, &part->childsize, 0.01, 100, 10, 1, "A multiplier for the child particle size");
+               uiDefButF(block, NUM, B_PART_REDRAW, "Rand:",           butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles");
+       }
+       if(part->childtype == PART_CHILD_FACES) {
                uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces");
                uiDefButBitI(block, TOG, PART_CHILD_SEAMS, B_PART_DISTR_CHILD, "Use Seams",      butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Use seams to determine parents");
        }
@@ -3945,27 +4031,30 @@ static void object_panel_particle_children(Object *ob)
        butx=160;
        buty=180;
 
-       uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch",        butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options");
+       if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED))
+               uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch",        butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options");
+       else
+               buty-=buth;
 
-       if(kink_ui) {
+       if(kink_ui || (psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) == 0) {
                buty -= buth/2;
 
                /* kink */
                uiBlockBeginAlign(block);
                if(part->kink) {
-                       uiDefButS(block, MENU, B_PART_RECALC_CHILD, "Kink:%t|Roll%x6|Rotation%x5|Braid%x4|Wave%x3|Radial%x2|Curl%x1|Nothing%x0", butx,(buty-=buth),butw/2,buth, &part->kink, 14.0, 0.0, 0, 0, "Type of periodic offset on the path");
+                       uiDefButS(block, MENU, B_PART_RECALC_CHILD, "Kink:%t|Braid%x4|Wave%x3|Radial%x2|Curl%x1|Nothing%x0", butx,(buty-=buth),butw/2,buth, &part->kink, 14.0, 0.0, 0, 0, "Type of periodic offset on the path");
                        uiDefButS(block, MENU, B_PART_RECALC_CHILD, "Axis %t|Z %x2|Y %x1|X %x0", butx+butw/2,buty,butw/2,buth, &part->kink_axis, 14.0, 0.0, 0, 0, "Which axis to use for offset");
                        uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Freq:",                     butx,(buty-=buth),butw,buth, &part->kink_freq, 0.0, 10.0, 1, 3, "The frequency of the offset (1/total length)");
                        uiDefButF(block, NUMSLI, B_PART_RECALC_CHILD, "Shape:",         butx,(buty-=buth),butw,buth, &part->kink_shape, -0.999, 0.999, 1, 3, "Adjust the offset to the beginning/end");
                        uiDefButF(block, NUM, B_PART_RECALC_CHILD, "Amplitude:",        butx,(buty-=buth),butw,buth, &part->kink_amp, 0.0, 10.0, 1, 3, "The amplitude of the offset");
                }
                else {
-                       uiDefButS(block, MENU, B_PART_RECALC_CHILD, "Kink:%t|Roll%x6|Rotation%x5|Braid%x4|Wave%x3|Radial%x2|Curl%x1|Nothing%x0", butx,(buty-=buth),butw,buth, &part->kink, 14.0, 0.0, 0, 0, "Type of periodic offset on the path");
+                       uiDefButS(block, MENU, B_PART_RECALC_CHILD, "Kink:%t|Braid%x4|Wave%x3|Radial%x2|Curl%x1|Nothing%x0", butx,(buty-=buth),butw,buth, &part->kink, 14.0, 0.0, 0, 0, "Type of periodic offset on the path");
                        buty-=3*buth;
                }
                uiBlockEndAlign(block);
 
-               if(part->childtype==PART_CHILD_PARTICLES) {
+               if(part->childtype==PART_CHILD_PARTICLES && psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) {
                        if(part->flag & PART_BRANCHING) {
                                uiDefButBitI(block, TOG, PART_BRANCHING, B_PART_RECALC_CHILD, "Branching",      butx,(buty-=2*buth),butw,buth, &part->flag, 0, 0, 0, 0, "Branch child paths from eachother");
                                uiDefButBitI(block, TOG, PART_ANIM_BRANCHING, B_PART_RECALC_CHILD, "Animated",  butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Animate branching");
@@ -4055,11 +4144,11 @@ static void object_panel_particle_extra(Object *ob)
        uiDefButBitI(block, TOG, PART_GLOB_TIME, B_PART_RECALC, "Global",        butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Set all ipos that work on particles to be calculated in global/object time");
        uiDefButBitI(block, TOG, PART_ABS_TIME, B_PART_RECALC, "Absolute",       butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Set all ipos that work on particles to be calculated in absolute/relative time");
 
-       if(part->flag & PART_LOOP){
-               uiDefButBitI(block, TOG, PART_LOOP, B_PART_RECALC, "Loop",       butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Loop particle lives");
-               uiDefButBitI(block, TOG, PART_LOOP_INSTANT, B_PART_RECALC, "Instantly",  butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Loop particle life at time of death");
-       }
-       else
+       //if(part->flag & PART_LOOP){
+       //      uiDefButBitI(block, TOG, PART_LOOP, B_PART_RECALC, "Loop",       butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Loop particle lives");
+       //      uiDefButBitI(block, TOG, PART_LOOP_INSTANT, B_PART_RECALC, "Instantly",  butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Loop particle life at time of death");
+       //}
+       //else
                uiDefButBitI(block, TOG, PART_LOOP, B_PART_RECALC, "Loop",       butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Loop particle lives");
 
        uiDefButF(block, NUM, B_PART_RECALC, "Tweak:",  butx,(buty-=buth),butw,buth, &part->timetweak, 0.0, 10.0, 1, 0, "A multiplier for physics timestep (1.0 means one frame = 1/25 seconds)");
@@ -4075,12 +4164,12 @@ static void object_panel_particle_extra(Object *ob)
                uiBlockBeginAlign(block);
                
                uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|Effector%x11|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group");
-               but=uiDefButBitS(block, TOG, (1<<vgnum), B_PART_REDRAW, "Neg",  butx+butw-40,buty,40,buth, &psys->vg_neg, 0, 0, 0, 0, "Negate the effect of the vertex group");
+               but=uiDefButBitS(block, TOG, (1<<vgnum), B_PART_RECALC, "Neg",  butx+butw-40,buty,40,buth, &psys->vg_neg, 0, 0, 0, 0, "Negate the effect of the vertex group");
                uiButSetFunc(but, particle_set_vg, (void *)ob, (void *)(&vgnum));
                
                butx+=butw;
 
-               but= uiDefButS(block, MENU, B_PART_REDRAW, menustr,     butx,buty,buth,buth, psys->vgroup+vgnum, 0, defCount, 0, 0, "Browses available vertex groups");
+               but= uiDefButS(block, MENU, B_PART_RECALC, menustr,     butx,buty,buth,buth, psys->vgroup+vgnum, 0, defCount, 0, 0, "Browses available vertex groups");
                uiButSetFunc(but, particle_set_vg, (void *)ob, (void *)(&vgnum));
                MEM_freeN (menustr);
 
@@ -4091,7 +4180,7 @@ static void object_panel_particle_extra(Object *ob)
                        else{
                                uiDefBut(block, BUT, B_PART_REDRAW, "(no group)",       butx+buth,buty,butw-2*buth,buth, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
                        }
-                       but=uiDefIconBut(block, BUT, B_PART_REDRAW, ICON_X, butx+butw-buth,buty,buth,buth, 0, 0, 0, 0, 0, "Disable use of vertex group");
+                       but=uiDefIconBut(block, BUT, B_PART_RECALC, ICON_X, butx+butw-buth,buty,buth,buth, 0, 0, 0, 0, 0, "Disable use of vertex group");
                        uiButSetFunc(but, particle_del_vg, (void *)ob, (void *)(&vgnum));
                }
 
@@ -4101,8 +4190,12 @@ static void object_panel_particle_extra(Object *ob)
        buty=butx=160;
 
        uiDefButI(block, NUM, B_PART_DISTR, "Seed:",                            butx,(buty-=buth),butw,buth, &psys->seed, 0.0, 255.0, 1, 0, "Set an offset in the random table");
-       if(part->type == PART_HAIR && psys->flag & PSYS_EDITED)
-               uiDefButF(block, NUM, B_PART_RECALC, "Stiff:",  butx,(buty-=buth),butw,buth, &part->eff_hair, 0.0, 1.0, 0, 0, "Hair stiffness for effectors");
+       if(part->type == PART_HAIR) {
+               uiBlockBeginAlign(block);
+               uiDefButF(block, NUM, B_PART_RECALC, "Stiff:",  butx,(buty-=buth),(butw*3)/5,buth, &part->eff_hair, 0.0, 1.0, 0, 0, "Hair stiffness for effectors");
+               uiDefButBitI(block, TOG, PART_CHILD_EFFECT, B_PART_RECALC, "Children", butx+(butw*3)/5,buty,(butw*2)/5,buth, &part->flag, 0, 0, 0, 0, "Apply effectors to children");
+               uiBlockEndAlign(block);
+       }
        else
                buty-=buth;
 
@@ -4163,7 +4256,7 @@ static void object_panel_particle_visual(Object *ob)
        uiDefButBitS(block, TOG, PART_DRAW_SIZE, B_PART_REDRAW, "Size", butx+butw/3,buty,butw/3,buth, &part->draw, 0, 0, 0, 0, "Show particle size");
        uiDefButBitS(block, TOG, PART_DRAW_NUM, B_PART_REDRAW, "Num",   butx+2*butw/3,buty,butw/3,buth, &part->draw, 0, 0, 0, 0, "Show particle number");
        uiDefButS(block, NUM, B_PART_REDRAW, "Draw Size:", butx,(buty-=buth),butw,buth, &part->draw_size, 0.0, 10.0, 0, 0, "Size of particles on viewport in pixels (0=default)");
-       uiDefButS(block, NUM, B_PART_RECALC, "Disp:",           butx,(buty-=buth),butw,buth, &part->disp, 0.0, 100.0, 10, 0, "Percentage of particles to calculate for 3d view");
+       uiDefButS(block, NUM, B_PART_RECALC_CHILD, "Disp:",             butx,(buty-=buth),butw,buth, &part->disp, 0.0, 100.0, 10, 0, "Percentage of particles to display in 3d view");
        uiBlockEndAlign(block);
 
        uiDefBut(block, LABEL, 0, "Render:",    butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
@@ -4184,10 +4277,10 @@ static void object_panel_particle_visual(Object *ob)
 
        switch(part->draw_as) {
                case PART_DRAW_OB:
-                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_PART_REDRAW, "OB:",     butx,(buty-=buth),butw,buth, &part->dup_ob, "Show this Object in place of particles"); 
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_PART_REDRAW_DEPS, "OB:",        butx,(buty-=buth),butw,buth, &part->dup_ob, "Show this Object in place of particles"); 
                        break;
                case PART_DRAW_GR:
-                       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_PART_REDRAW, "GR:",  butx,(buty-=buth),butw,buth, &part->dup_group, "Show Objects in this Group in place of particles"); 
+                       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_PART_REDRAW_DEPS, "GR:",     butx,(buty-=buth),butw,buth, &part->dup_group, "Show Objects in this Group in place of particles"); 
                        uiDefButBitS(block, TOG, PART_DRAW_WHOLE_GR, B_PART_REDRAW, "Dupli Group",      butx,(buty-=buth),butw,buth, &part->draw, 0, 0, 0, 0, "Use whole group at once");
                        if((part->draw & PART_DRAW_WHOLE_GR)==0)
                                uiDefButBitS(block, TOG, PART_DRAW_RAND_GR, B_PART_REDRAW, "Pick Random",       butx,(buty-=buth),butw,buth, &part->draw, 0, 0, 0, 0, "Pick objects from group randomly");
@@ -4238,7 +4331,7 @@ static void object_panel_particle_visual(Object *ob)
                                }
                        }
                        else {
-                               uiDefBut(block, LABEL, 0, "Baked or keyed",     butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
+                               uiDefBut(block, LABEL, 0, "Hair or keyed",      butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
                                uiDefBut(block, LABEL, 0, "particles needed!",  butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
                        }
                        break;
@@ -4432,7 +4525,7 @@ static void object_panel_particle_physics(Object *ob)
                uiDefButF(block, NUM, B_PART_RECALC, "Rand:",                   butx+butw/2,buty,butw/2,buth*4/5, &part->randphasefac, 0.0, 1.0, 1, 3, "Randomize rotation phase");
                uiBlockSetCol(block, TH_AUTO);
 
-               uiDefButS(block, MENU, B_PART_RECALC, "Angular v %t|Velocity%x3|Random%x2|Spin%x1|None%x0", butx,(buty-=buth*4/5),butw,buth*4/5, &part->avemode, 14.0, 0.0, 0, 0, "Select particle angular velocity mode");
+               uiDefButS(block, MENU, B_PART_RECALC, "Angular v %t|Random%x2|Spin%x1|None%x0", butx,(buty-=buth*4/5),butw,buth*4/5, &part->avemode, 14.0, 0.0, 0, 0, "Select particle angular velocity mode");
                uiBlockSetCol(block, TH_BUT_SETTING2);
                if(ELEM(part->avemode,PART_AVE_RAND,PART_AVE_SPIN))
                        uiDefButF(block, NUM, B_PART_RECALC, "Angular v:",              butx,(buty-=buth*4/5),butw,buth*4/5, &part->avefac, -200.0, 200.0, 1, 3, "Angular velocity amount");
@@ -4992,6 +5085,379 @@ 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);
+               
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+               allqueue(REDRAWBUTSEDIT, 0);
+               allqueue(REDRAWVIEW3D, 0);
+       }
+       else {
+               Object *ob = ob_v;
+               ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
+       
+               if (!md)
+                       return;
+
+               BLI_remlink(&ob->modifiers, md);
+
+               modifier_free(md);
+
+               BIF_undo_push("Del modifier");
+               
+               ob->softflag |= OB_SB_RESET;
+               allqueue(REDRAWBUTSEDIT, 0);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWIMAGE, 0);
+               allqueue(REDRAWOOPS, 0);
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+               object_handle_update(ob);
+               countall();
+       }
+}
+
+static int _can_cloth_at_all(Object *ob)
+{
+       // list of Yes
+       if ((ob->type==OB_MESH)) return 1;
+       // else deny
+       return 0;
+}
+
+static void object_panel_cloth(Object *ob)
+{
+       uiBlock *block=NULL;
+       uiBut *but=NULL;
+       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);
+       
+       if(!_can_cloth_at_all(ob))
+       {
+               uiDefBut(block, LABEL, 0, "Cloth can be activated on mesh only.",  10,200,300,20, NULL, 0.0, 0, 0, 0, "");
+       }
+       else    
+       {
+               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 [] = "Vertex Groups%t|";
+
+               val2=0;
+               
+               /* GENERAL STUFF */
+               uiClearButLock();
+               if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected");
+               
+               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, 4.0, 80.0, 5, 0, "Quality of the simulation (higher=better=slower)");
+
+               uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms->Cdis, 0.0, 1.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");
+               
+               uiDefBut(block, LABEL, 0, "Gravity:",  10,100,60,20, NULL, 0.0, 0, 0, 0, "");
+               
+               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, B_CLOTH_RENEW, "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, 50.0, 50, 0, "Pin (vertex target position) spring stiffness");
+                       uiDefBut(block, LABEL, 0, "",160,50,150,20, NULL, 0.0, 0, 0, 0, "");    
+                       // uiDefButI(block, NUM, B_CLOTH_RENEW, "Pin Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 1.0, 100.0, 10, 0, "Pined damping (higher = doesn't oszilate so much)");
+                       /*
+                       // nobody is changing these ones anyway
+                       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_cloth__protecttoggle(void *ob_v, void *arg2)
+{
+       Object *ob = ob_v;
+       int cageIndex, stack_index;
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       
+       // automatically enable modifier in editmode when we havee a protected cache
+       if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)
+       {
+               cageIndex = modifiers_getCageIndex(ob_v, NULL );
+               stack_index = modifiers_indexInObject(ob_v, (ModifierData *)clmd);
+               if( stack_index >= cageIndex )
+                       ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage;
+       }
+       else
+       {
+               ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage;
+       }
+       
+}
+
+
+static void object_panel_cloth_II(Object *ob)
+{
+       uiBlock *block;
+       uiBut *but = NULL;
+       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)
+       {       
+               uiClearButLock();
+               if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected");
+               
+               uiDefButI(block, NUM, B_CLOTH_RENEW, "First Frame:",10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts");
+               uiDefButI(block, NUM, B_CLOTH_RENEW, "Last Frame:",160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation stops");
+               
+               uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, "");
+               uiClearButLock();
+               if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) uiSetButLock(1, "Please leave editmode.");
+               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
+               {
+                       but = 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.");
+                       uiButSetFunc(but, object_cloth__protecttoggle, ob, NULL);
+                       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, "");
+               }
+               
+               uiClearButLock();
+               if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected");
+               
+               /*
+               TODO: implement this again in cloth!
+               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, "");
+               */
+#if WITH_BULLET == 1
+               uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, B_CLOTH_RENEW, "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_COLLSETTINGS_FLAG_ENABLED)
+               {
+                       uiDefButF(block, NUM, REDRAWBUTSOBJECT, "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, can be changed for each frame");
+                       uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:",      10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 20.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), can be changed for each frame");
+                       uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Friction:",       160,40,150,20, &clmd->coll_parms->friction, 0.0, 80.0, 1.0, 0, "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
+                       
+                       uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_SELF, B_CLOTH_RENEW, "Enable selfcollisions",  10,20,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable selfcollisions with this object");
+                       if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF)     
+                       {
+                               uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Min Distance:",           160,20,150,20, &clmd->coll_parms->selfepsilon, 0.5f, 1.0, 0.01f, 0, "0.5 means no distance at all, 1.0 is maximum distance");
+                               // self_loop_count
+                               uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Selfcoll Quality:",       10,0,150,20, &clmd->coll_parms->self_loop_count, 1.0, 10.0, 1.0, 0, "How many selfcollision iterations should be done. (higher = better = slower), can be changed for each frame");
+                       }
+                       else
+                               uiDefBut(block, LABEL, 0, "",160,20,150,20, NULL, 0.0, 0, 0, 0, "");    
+               }
+               else
+                       uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, "");    
+#else
+               uiDefBut(block, LABEL, 0, "No collisions available (compile with bullet).",10,60,300,20, NULL, 0.0, 0, 0, 0, "");
+#endif
+       }
+       
+       uiBlockEndAlign(block);
+       
+}
+
+static void object_panel_cloth_III(Object *ob)
+{
+       uiBlock *block;
+       ClothModifierData *clmd = NULL;
+
+       block= uiNewBlock(&curarea->uiblocks, "object_cloth_III", UI_EMBOSS, UI_HELV, curarea->win);
+       uiNewPanelTabbed("Cloth ", "Physics");
+       if(uiNewPanel(curarea, block, "Cloth Advanced", "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)
+       {
+               int defCount;
+               char *clvg1, *clvg2;
+               char clmvg [] = "Vertex Groups%t|None%x0|";
+               char clmvg2 [] = "Vertex Groups%t|None%x0|";
+               
+               uiClearButLock();
+               if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected");
+               
+               
+               uiDefButI(block, NUM, B_DIFF, "Autoprotect Cache From:",10,160,300,20, &clmd->sim_parms->autoprotect, 0.0, MAXFRAME + 1, 1, 0, "Frame on which the simulation gets cache protection enabled automatically (To prevent accidently cleaning it).");
+                               
+               uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_SCALING, B_CLOTH_RENEW, "Enable stiffness scaling",10,130,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "If enabled, stiffness can be scaled along a weight painted vertex group.");
+               
+               if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)&& (BLI_countlist (&ob->defbase) > 0))
+               {       
+                       uiDefBut(block, LABEL, 0, "StructStiff VGroup:",10,110,150,20, NULL, 0.0, 0, 0, 0, "");
+                       uiDefBut(block, LABEL, 0, "BendStiff VGroup:",160,110,150,20, NULL, 0.0, 0, 0, 0, "");
+                       
+                       defCount = sizeof (clmvg);
+                       clvg1 = get_vertexgroup_menustr (ob);
+                       clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgST");
+                       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_struct = 0;
+                       }
+                       else
+                       {
+                               if(clmd->sim_parms->vgroup_struct > defCount)
+                                       clmd->sim_parms->vgroup_struct = 0;
+                       }
+                                               
+                       sprintf (clvg2, "%s%s", clmvg, clvg1);
+                       
+                       uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2,    10,90,150,20, &clmd->sim_parms->vgroup_struct, 0, defCount, 0, 0, "Browses available vertex groups");
+                       MEM_freeN (clvg1);
+                       MEM_freeN (clvg2);
+                       
+                       defCount = sizeof (clmvg);
+                       clvg1 = get_vertexgroup_menustr (ob);
+                       clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgBD");
+                       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_bend = 0;
+                       }
+                       else
+                       {
+                               if(clmd->sim_parms->vgroup_bend > defCount)
+                                       clmd->sim_parms->vgroup_bend = 0;
+                       }
+                                               
+                       sprintf (clvg2, "%s%s", clmvg2, clvg1);
+                       
+                       uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,90,150,20, &clmd->sim_parms->vgroup_bend, 0, defCount, 0, 0, "Browses available vertex groups");
+                       MEM_freeN (clvg1);
+                       MEM_freeN (clvg2);
+                       
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff Max:",10,70,150,20, &clmd->sim_parms->max_struct, clmd->sim_parms->structural, 10000.0, 0.01f, 0, "Maximum structural stiffness value");
+                       
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff Max:",160,70,150,20, &clmd->sim_parms->max_bend, clmd->sim_parms->bending, 10000.0, 0.01f, 0, "Maximum bending stiffness value");
+
+               }
+               else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)
+               {
+                       uiDefBut(block, LABEL, 0, " ",  10,110,300,20, NULL, 0.0, 0, 0, 0, "");
+                       uiDefBut(block, LABEL, 0, "No vertex group for pinning available.",  10,90,300,20, NULL, 0.0, 0, 0, 0, "");
+               }
+       
+               
+               
+       }
+       
+       uiBlockEndAlign(block);
+       
+}
+
 void object_panels()
 {
        Object *ob;
@@ -5021,6 +5487,9 @@ void physics_panels()
                object_softbodies(ob);
                object_softbodies_collision(ob);
                object_softbodies_solver(ob);
+               object_panel_cloth(ob);
+               object_panel_cloth_II(ob);
+               object_panel_cloth_III(ob);
                object_panel_fluidsim(ob);
        }
 }