svn merge -r 13415:13452 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Tue, 29 Jan 2008 16:42:57 +0000 (16:42 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Tue, 29 Jan 2008 16:42:57 +0000 (16:42 +0000)
1  2 
source/blender/blenloader/intern/readfile.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/drawobject.c
source/blender/src/editobject.c
source/blender/src/transform_conversions.c

index 4feb8c00659d5f76f398f757b9911c1817335b08,3d1a9822ecbc4e7286d7b0082db134e3d73c26d0..f6c5264efc41106e39160daeccb63c3e3a745b1a
@@@ -60,7 -60,6 +60,7 @@@
  #include "DNA_actuator_types.h"
  #include "DNA_brush_types.h"
  #include "DNA_camera_types.h"
 +#include "DNA_cloth_types.h"
  #include "DNA_color_types.h"
  #include "DNA_controller_types.h"
  #include "DNA_constraint_types.h"
  
  #include "BKE_action.h"
  #include "BKE_armature.h"
 +#include "BKE_cloth.h"
  #include "BKE_colortools.h"
  #include "BKE_constraint.h"
  #include "BKE_curve.h"
@@@ -3006,46 -3004,7 +3006,46 @@@ static void direct_link_modifiers(FileD
                        SubsurfModifierData *smd = (SubsurfModifierData*) md;
  
                        smd->emCache = smd->mCache = 0;
 -              } else if (md->type==eModifierType_Hook) {
 +              }
 +              else if (md->type==eModifierType_Cloth) {
 +                      ClothModifierData *clmd = (ClothModifierData*) md;
 +                      
 +                      clmd->clothObject = NULL;
 +                      
 +                      clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
 +                      clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
 +                      
 +                      clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_LOADED;
 +                      clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
 +                      
 +              }
 +              else if (md->type==eModifierType_Collision) {
 +                      
 +                      CollisionModifierData *collmd = (CollisionModifierData*) md;
 +                      /*
 +                      // TODO: CollisionModifier should use pointcache 
 +                      // + have proper reset events before enabling this
 +                      collmd->x = newdataadr(fd, collmd->x);
 +                      collmd->xnew = newdataadr(fd, collmd->xnew);
 +                      collmd->mfaces = newdataadr(fd, collmd->mfaces);
 +                      
 +                      collmd->current_x = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_x");
 +                      collmd->current_xnew = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_xnew");
 +                      collmd->current_v = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_v");
 +                      */
 +                      
 +                      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;
 +                      
 +              }
 +              else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
  
                        hmd->indexar= newdataadr(fd, hmd->indexar);
@@@ -3190,6 -3149,7 +3190,6 @@@ static void direct_link_object(FileDat
                sb->bpoint= NULL;       // init pointers so it gets rebuilt nicely
                sb->bspring= NULL;
                sb->scratch= NULL;
 -
                /* although not used anymore */
                /* still have to be loaded to be compatible with old files */
                sb->keys= newdataadr(fd, sb->keys);
@@@ -3436,6 -3396,8 +3436,8 @@@ static void direct_link_scene(FileData 
                        if(seq->strip && seq->strip->done==0) {
                                seq->strip->done= 1;
                                seq->strip->tstripdata = 0;
+                               seq->strip->tstripdata_startstill = 0;
+                               seq->strip->tstripdata_endstill = 0;
  
                                if(seq->type == SEQ_IMAGE ||
                                   seq->type == SEQ_MOVIE ||
index 3ea7788f87cee9b5bb9255702ab1ec53de7c6c40,5636c232a6d3cc2d62a2979f2cb55c9689a97ad8..c5087bd2ba5b9ed70f33b53db98436ce71ae479b
@@@ -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 = 31;
 +              } 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);
                }
@@@ -4067,13 -4052,13 +4067,13 @@@ static void editing_panel_armature_type
        uiBlockBeginAlign(block);
        for(a=0; a<8; a++) {
                short dx= 18;
-               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "Armature layer (Hold Ctrl for locking in a proxy instance)");
                uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
        }
        uiBlockBeginAlign(block);
        for(a=8; a<16; a++) {
                short dx= 18;
-               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "Armature layer (Hold Ctrl for locking in a proxy instance)");
                uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
        }
        /* quite bad here, but I don't know a better place for copy... */
index e6046203c4f25c1234d6d6ee06ad7484c9c60e26,7ed33998dc63e9914ac244e0f8d86046d01d11ea..0ec606859818a5a24a31cdd2146ff88452e32042
@@@ -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"
@@@ -584,12 -582,14 +584,14 @@@ static void draw_constraint (uiBlock *b
                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) {
                }
                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 */
@@@ -2347,78 -2351,6 +2353,78 @@@ 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)
 +              {
 +                      // 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) {
@@@ -3236,31 -3168,10 +3242,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");
@@@ -3734,7 -3643,7 +3740,7 @@@ static void object_softbodies_solver(Ob
                                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);
                        } 
@@@ -3920,15 -3829,15 +3926,15 @@@ static void object_softbodies(Object *o
                                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)");
+                               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,80,20, &sb->aeroedge,  0.00,  30000.0, 10, 0, "Make edges 'sail'");
                                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");
                                        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, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0,  1.0, 10, 0, "Strenght of diagonal Springs");
                                        }
                                }
                                else sb->secondspring = 0;
@@@ -5052,316 -4961,6 +5058,316 @@@ 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 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 [] = "Vertex 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, 4.0, 100.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, 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");
 +              
 +              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, 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)
 +      {       
 +              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, "");
 +              
 +              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.");
 +                      
 +                      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, "");
 +              }
 +
 +              /*
 +              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, "");
 +              */
 +
 +              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,300,20, &clmd->coll_parms->loop_count, 1.0, 100.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), can be changed for each frame");
 +                      uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Friction:",       10,40,300,20, &clmd->coll_parms->friction, 1.0, 100.0, 1.0, 0, "Friction force if a collision happened");
 +              }
 +              else
 +                      uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, "");    
 +      }
 +      
 +      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|";
 +              
 +              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;
@@@ -5391,9 -4990,6 +5397,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);
        }
  }
index 6696fd3cfe3e672388877e2d26a3047ff0928d2b,e0bfa8d90d69b06ec4e6b97a7f45989f8f9ae027..349432d87a1fef015a7c71f55dac1640d41d436d
@@@ -78,7 -78,6 +78,7 @@@
  #include "BLI_rand.h"
  
  #include "BKE_utildefines.h"
 +#include "BKE_cloth.h"
  #include "BKE_curve.h"
  #include "BKE_constraint.h" // for the get_constraint_target function
  #include "BKE_DerivedMesh.h"
@@@ -2175,285 -2174,6 +2175,285 @@@ static void draw_em_fancy(Object *ob, E
  
  /* Mesh drawing routines */
  
 +
 +
 +#define AMBIENT 50
 +#define DECAY 0.04f
 +#define ALMOST_EQUAL(a, b) ((fabs(a-b)<0.00001f)?1:0)
 +
 +      // cube vertices
 +GLfloat cv[][3] = {
 +      {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
 + {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
 +};
 +
 +      // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
 +float edges[12][2][3] = {
 +      {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
 + {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
 + {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
 + {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
 +
 + {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
 + {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
 + {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
 + {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
 +
 + {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
 + {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
 + {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}},
 + {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}
 +};
 +
 +void light_ray(unsigned char* _texture_data, int _ray_templ[4096][3], int x, int y, int z, int n, float decay)
 +{
 +      int xx = x, yy = y, zz = z, i = 0;
 +      int offset;
 +
 +      int l = 255;
 +      float d;
 +
 +      do {
 +              offset = ((((zz*n) + yy)*n + xx) << 2);
 +              if (_texture_data[offset + 2] > 0)
 +                      _texture_data[offset + 2] = (unsigned char) ((_texture_data[offset + 2] + l)*0.5f);
 +              else
 +                      _texture_data[offset + 2] = (unsigned char) l;
 +              d = _texture_data[offset+1];
 +              if (l > AMBIENT) {
 +                      l -= d*decay;
 +                      if (l < AMBIENT)
 +                              l = AMBIENT;
 +              }
 +
 +              i++;
 +              xx = x + _ray_templ[i][0];
 +              yy = y + _ray_templ[i][1];
 +              zz = z + _ray_templ[i][2];
 +              
 +      } while ((xx>=0)&&(xx<n)&&(yy>=0)&&(yy<n)&&(zz>=0)&&(zz<n));
 +}
 +
 +void cast_light(unsigned char* _texture_data, int _ray_templ[4096][3], float *_light_dir, int n /*edgelen*/)
 +{
 +      int i,j;
 +      int sx = (_light_dir[0]>0) ? 0 : n-1;
 +      int sy = (_light_dir[1]>0) ? 0 : n-1;
 +      int sz = (_light_dir[2]>0) ? 0 : n-1;
 +
 +      float decay = 1.0f/(n*DECAY);
 +
 +      for (i=0; i<n; i++)
 +              for (j=0; j<n; j++) {
 +              if (!ALMOST_EQUAL(_light_dir[0], 0))
 +                      light_ray(_texture_data, _ray_templ, sx,i,j,n,decay);
 +              if (!ALMOST_EQUAL(_light_dir[1], 0))
 +                      light_ray(_texture_data, _ray_templ, i,sy,j,n,decay);
 +              if (!ALMOST_EQUAL(_light_dir[2], 0))
 +                      light_ray(_texture_data, _ray_templ, i,j,sz,n,decay);
 +              }
 +}
 +
 +void gen_ray_templ(int _ray_templ[4096][3], float *_light_dir, int edgelen)
 +{
 +      float fx = 0.0f, fy = 0.0f, fz = 0.0f;
 +      int x = 0, y = 0, z = 0;
 +      float lx = _light_dir[0] + 0.000001f, ly = _light_dir[1] + 0.000001f, lz = _light_dir[2] + 0.000001f;
 +      int xinc = (lx > 0) ? 1 : -1;
 +      int yinc = (ly > 0) ? 1 : -1;
 +      int zinc = (lz > 0) ? 1 : -1;
 +      float tx, ty, tz;
 +      int i = 1;
 +      int len = 0;
 +      int maxlen = 3*edgelen*edgelen;
 +      _ray_templ[0][0] = _ray_templ[0][2] = _ray_templ[0][2] = 0;
 +      
 +      while (len <= maxlen)
 +      {
 +              // fx + t*lx = (x+1)   ->   t = (x+1-fx)/lx
 +              tx = (x+xinc-fx)/lx;
 +              ty = (y+yinc-fy)/ly;
 +              tz = (z+zinc-fz)/lz;
 +
 +              if ((tx<=ty)&&(tx<=tz)) {
 +                      _ray_templ[i][0] = _ray_templ[i-1][0] + xinc;
 +                      x =+ xinc;
 +                      fx = x;
 +
 +                      if (ALMOST_EQUAL(ty,tx)) {
 +                              _ray_templ[i][1] = _ray_templ[i-1][1] + yinc;
 +                              y += yinc;
 +                              fy = y;
 +                      } else {
 +                              _ray_templ[i][1] = _ray_templ[i-1][1];
 +                              fy += tx*ly;
 +                      }
 +
 +                      if (ALMOST_EQUAL(tz,tx)) {
 +                              _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
 +                              z += zinc;
 +                              fz = z;
 +                      } else {
 +                              _ray_templ[i][2] = _ray_templ[i-1][2];
 +                              fz += tx*lz;
 +                      }
 +              } else if ((ty<tx)&&(ty<=tz)) {
 +                      _ray_templ[i][0] = _ray_templ[i-1][0];
 +                      fx += ty*lx;
 +
 +                      _ray_templ[i][1] = _ray_templ[i-1][1] + yinc;
 +                      y += yinc;
 +                      fy = y;
 +
 +                      if (ALMOST_EQUAL(tz,ty)) {
 +                              _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
 +                              z += zinc;
 +                              fz = z;
 +                      } else {
 +                              _ray_templ[i][2] = _ray_templ[i-1][2];
 +                              fz += ty*lz;
 +                      }
 +              } else {
 +                      // assert((tz<tx)&&(tz<ty));
 +                      if((tz<tx)&&(tz<ty))
 +                              break;
 +                      
 +                      _ray_templ[i][0] = _ray_templ[i-1][0];
 +                      fx += tz*lx;
 +                      _ray_templ[i][1] = _ray_templ[i-1][1];
 +                      fy += tz*ly;
 +                      _ray_templ[i][2] = _ray_templ[i-1][2] + zinc;
 +                      z += zinc;
 +                      fz = z;
 +              }
 +
 +              len = _ray_templ[i][0]*_ray_templ[i][0]
 +                              + _ray_templ[i][1]*_ray_templ[i][1]
 +                              + _ray_templ[i][2]*_ray_templ[i][2];
 +              i++;
 +      }
 +}
 +
 +int intersect_edges(float ret[12][3], float a, float b, float c, float d)
 +{
 +      int i;
 +      float t;
 +      int num = 0;
 +
 +      for (i=0; i<12; i++) {
 +              t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d)
 +                      / (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]);
 +              if ((t>0)&&(t<2)) {
 +                      ret[num][0] = edges[i][0][0] + edges[i][1][0]*t;
 +                      ret[num][1] = edges[i][0][1] + edges[i][1][1]*t;
 +                      ret[num][2] = edges[i][0][2] + edges[i][1][2]*t;
 +                      num++;
 +              }
 +      }
 +
 +      return num;
 +}
 +
 +void draw_slices ( float m[][4] )
 +{
 +      int i;
 +
 +      float viewdir[3];
 +      float d0;
 +      float dd;
 +      int n;
 +      float d;
 +      
 +      viewdir[0] = m[0][2];
 +      viewdir[1] = m[1][2];
 +      viewdir[2] = m[2][2];
 +      Normalize(viewdir);
 +      
 +      // find cube vertex that is closest to the viewer
 +      for ( i=0; i<8; i++ )
 +      {
 +              float x = cv[i][0] + viewdir[0];
 +              float y = cv[i][1] + viewdir[1];
 +              float z = cv[i][2] + viewdir[2];
 +              if ( ( x>=-1.0f ) && ( x<=1.0f )
 +                      && ( y>=-1.0f ) && ( y<=1.0f )
 +                      && ( z>=-1.0f ) && ( z<=1.0f ) )
 +              {
 +                      break;
 +              }
 +      }
 +      if ( i != 8 ) return;
 +
 +      glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
 +      glDisable ( GL_DEPTH_TEST );
 +      // our slices are defined by the plane equation a*x + b*y +c*z + d = 0
 +      // (a,b,c), the plane normal, are given by viewdir
 +      // d is the parameter along the view direction. the first d is given by
 +      // inserting previously found vertex into the plane equation
 +      d0 = - ( viewdir[0]*cv[i][0] + viewdir[1]*cv[i][1] + viewdir[2]*cv[i][2] );
 +      dd = 2*d0/64.0f;
 +      n = 0;
 +      
 +      for ( d = -d0; d < d0; d += dd )
 +      {
 +              // intersect_edges returns the intersection points of all cube edges with
 +              // the given plane that lie within the cube
 +              float pt[12][3];
 +              int num = intersect_edges ( pt, viewdir[0], viewdir[1], viewdir[2], d );
 +
 +              if ( num > 2 )
 +              {
 +                      // sort points to get a convex polygon
 +                      // std::sort(pt.begin()+1, pt.end(), Convexcomp(pt[0], viewdir));
 +                      int shuffled = 1;
 +
 +                      while ( shuffled )
 +                      {
 +                              int j;
 +                              shuffled = 0;
 +
 +                              for ( j = 0; j < num-1; j++ )
 +                              {
 +                                      // Vec3 va = a-p0, vb = b-p0;
 +                                      // return dot(up, cross(va, vb)) >= 0;
 +                                      float va[3], vb[3], vc[3];
 +
 +                                      VECSUB ( va, pt[j], pt[0] );
 +                                      VECSUB ( vb, pt[j+1], pt[0] );
 +                                      Crossf ( vc, va, vb );
 +
 +                                      if ( INPR ( viewdir, vc ) >= 0 )
 +                                      {
 +                                              float temp[3];
 +
 +                                              VECCOPY ( temp, pt[j] );
 +                                              VECCOPY ( pt[j], pt[j+1] );
 +                                              VECCOPY ( pt[j+1], temp );
 +
 +                                              shuffled = 1;
 +                                      }
 +                              }
 +                      }
 +/*
 +                      glEnable ( GL_TEXTURE_3D );
 +                      glEnable ( GL_FRAGMENT_PROGRAM_ARB );
 +                      glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB, _prog[0] );
 +                      glActiveTextureARB ( GL_TEXTURE0_ARB );
 +                      glBindTexture ( GL_TEXTURE_3D, _txt[0] );
 +                      glBegin ( GL_POLYGON );
 +                      for ( i=0; i<num; i++ )
 +                      {
 +                              glColor3f ( 1.0, 1.0, 1.0 );
 +                              glTexCoord3d ( ( pt[i][0]+1.0 ) /2.0, ( -pt[i][1]+1 ) /2.0, ( pt[i][2]+1.0 ) /2.0 );
 +                              glVertex3f ( pt[i][0], pt[i][1], pt[i][2] );
 +                      }
 +                      glEnd();
 +                      */
 +              }
 +              n++;
 +      }
 +}
 +
  static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm)
  {
        
@@@ -3814,7 -3534,9 +3814,9 @@@ static void draw_new_particle_system(Ba
        glDisable(GL_LIGHTING);
        glDisableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
+ #if 0 /* If this is needed, it cant be enabled in wire mode, since it messes up the view - Campbell */
        glEnable(GL_DEPTH_TEST);
+ #endif
  
        if(states)
                MEM_freeN(states);
@@@ -5399,102 -5121,6 +5401,102 @@@ void draw_object(Base *base, int flag
                if(col) cpack(col);
                glDepthMask(GL_TRUE); 
        }
 +      
 +      /* code for drawing pinned cloth verts */
 +      if(modifiers_isClothEnabled(ob))
 +      {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +              Cloth *cloth = clmd->clothObject;
 +              ClothVertex *verts;
 +              float col[3];
 +              col[0] = 0.53;
 +              col[1] = 0.04;
 +              col[2] = 0.0;
 +              glColor3fv(col);
 +              
 +              /* inverse matrix is not uptodate... */
 +              Mat4Invert ( ob->imat, ob->obmat );
 +              
 +              if(cloth)
 +              {
 +                      /* don't paint anything if cloth has RESET status */
 +                      if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET))
 +                      {       
 +                              verts = cloth->verts;
 +                              /*
 +                              // this makes the screen pink
 +                              glEnable(GL_LIGHTING);
 +                              glEnable(GL_COLOR_MATERIAL);
 +                              glShadeModel(GL_SMOOTH);
 +                              */
 +                                      
 +                              for(i = 0; i < cloth->numverts; i++)
 +                              {
 +                                      if(verts[i].flags & CLOTH_VERT_FLAG_PINNED)
 +                                      {
 +                                              float size[3], cent[3];
 +                                              GLUquadricObj *qobj = gluNewQuadric(); 
 +                                              
 +                                              gluQuadricDrawStyle(qobj, GLU_FILL); 
 +              
 +                                              size[0]= clmd->coll_parms->avg_spring_len / 3.0;
 +                                              size[1]= clmd->coll_parms->avg_spring_len / 3.0;
 +                                              size[2]= clmd->coll_parms->avg_spring_len / 3.0;
 +                                              
 +                                              VECCOPY ( cent, verts[i].x );
 +                                              Mat4MulVecfl ( ob->imat, cent );
 +                                              
 +                                              glPushMatrix();
 +                                              glTranslatef(cent[0], cent[1], cent[2]);
 +                                              glScalef(size[0], size[1], size[2]);
 +                                              
 +                                              // gluSphere(qobj, 1.0, 8, 5);
 +                                              
 +                                              glTranslatef(0, 0, 1.0);
 +                                              gluDisk(qobj, 0, 0.25, 8,  5);
 +                                              
 +                                              glTranslatef(0, 0, -1.0);
 +                                              
 +                                              glTranslatef(0, 0, 0.875);
 +                                              gluCylinder(qobj, 0.15, 0.25,  0.125, 8, 5);
 +                                              
 +                                              glTranslatef(0, 0, -0.25);
 +                                              gluCylinder(qobj, 0.15, 0.15,  0.25, 8, 5);
 +                                              
 +                                              glTranslatef(0, 0, -0.125);
 +                                              gluCylinder(qobj, 0.25, 0.15,  0.125, 8, 5);
 +                                              
 +                                              // gluDisk(qobj, 0, 0.5, 8,  5);
 +                                              
 +                                              /*
 +                                              glTranslatef(0, 0, 1.0);
 +                                              gluDisk(qobj, 0, 0.4, 8,  5);
 +                                              */
 +                                              /*
 +                                              col[0] = 0.53;
 +                                              col[1] = 0.54;
 +                                              col[2] = 0.0;
 +                                              glColor3fv(col);
 +                                              */
 +                                              glTranslatef(0, 0, -0.5);
 +                                              gluCylinder(qobj, 0.0, 0.05,  0.5, 8, 5);
 +                                              
 +                                              glTranslatef(0, 0, 0.5);
 +                                              gluDisk(qobj, 0, 0.25, 8,  5);
 +                                              
 +                                              glPopMatrix();
 +              
 +                                              gluDeleteQuadric(qobj); 
 +                                      }
 +                              }
 +                              /*
 +                              glShadeModel(GL_FLAT);
 +                              glDisable(GL_COLOR_MATERIAL);
 +                              glDisable(GL_LIGHTING);
 +                              */
 +                      }
 +              }
 +      }
  
        {
                bConstraint *con;
index a7b8400fb9db26748df81dd693ece52ba179f667,ac631cf2a5ca4ec4bcb7cd650273b260583e670f..269c1db4649e770ce863b7b6bb725fab44590259
  #include "BKE_customdata.h"
  #include "BKE_blender.h"
  #include "BKE_booleanops.h"
 +#include "BKE_cloth.h"
  #include "BKE_curve.h"
  #include "BKE_displist.h"
  #include "BKE_depsgraph.h"
@@@ -1760,11 -1759,6 +1760,11 @@@ void exit_editmode(int flag)  /* freedat
                sbObjectToSoftbody(ob);
        }
        
 +      if(modifiers_isClothEnabled(ob)) {
 +              ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
 +              clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
 +      }
 +      
        if(ob->type==OB_MESH && get_mesh(ob)->mr)
                multires_edge_level_update(ob, get_mesh(ob));
        
@@@ -2554,7 -2548,7 +2554,7 @@@ void special_editmenu(void
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        }
        else if(G.obedit->type==OB_ARMATURE) {
-               nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3");
+               nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6");
                if(nr==1)
                        subdivide_armature(1);
                if(nr==2) {
                }
                else if(nr==3)
                        armature_flip_names();
+               else if(ELEM3(nr, 4, 5, 6)) {
+                       armature_autoside_names(nr-4);
+               }
        }
        else if(G.obedit->type==OB_LATTICE) {
                static float weight= 1.0f;
index e69fabdd926db836560cb327c6f609724e14ba15,3d580c70a1c34ede511e45f6bd94d4bded900e50..1534ab9c95153fc7014ff98acd0b5ba6b624a127
@@@ -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"
@@@ -2347,6 -2346,102 +2347,102 @@@ void flushTransIpoData(TransInfo *t
  
  /* ********************* ACTION/NLA EDITOR ****************** */
  
+ /* Called by special_aftertrans_update to make sure selected keyframes replace
+  * any other keyframes which may reside on that frame (that is not selected).
+  */
+ static void posttrans_ipo_clean (Ipo *ipo)
+ {
+       IpoCurve *icu;
+       int i;
+       
+       /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
+       for (icu= ipo->curve.first; icu; icu= icu->next) {
+               float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
+               int len, index;         /* number of frames in cache, item index */
+               
+               /* allocate memory for the cache */
+               // TODO: investigate using GHash for this instead?
+               if (icu->totvert == 0) 
+                       continue;
+               selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
+               len= 0;
+               index= 0;
+               
+               /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
+                * as there is no guarantee what order the keyframes are exactly, even though 
+                * they have been sorted by time.
+                */
+                
+               /*      Loop 1: find selected keyframes   */
+               for (i = 0; i < icu->totvert; i++) {
+                       BezTriple *bezt= &icu->bezt[i];
+                       
+                       if (BEZSELECTED(bezt)) {
+                               selcache[index]= bezt->vec[1][0];
+                               index++;
+                               len++;
+                       }
+               }
+               
+               /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
+               if (len) {
+                       for (i = 0; i < icu->totvert; i++) {
+                               BezTriple *bezt= &icu->bezt[i];
+                               
+                               if (BEZSELECTED(bezt) == 0) {
+                                       /* check beztriple should be removed according to cache */
+                                       for (index= 0; index < len; index++) {
+                                               if (IS_EQ(bezt->vec[1][0], selcache[index])) {
+                                                       delete_icu_key(icu, i, 0);
+                                                       break;
+                                               }
+                                               else if (bezt->vec[1][0] > selcache[index])
+                                                       break;
+                                       }
+                               }
+                       }
+                       
+                       testhandles_ipocurve(icu);
+               }
+               
+               /* free cache */
+               MEM_freeN(selcache);
+       }
+ }
+ /* Called by special_aftertrans_update to make sure selected keyframes replace
+  * any other keyframes which may reside on that frame (that is not selected).
+  * remake_action_ipos should have already been called 
+  */
+ static void posttrans_action_clean (bAction *act)
+ {
+       ListBase act_data = {NULL, NULL};
+       bActListElem *ale;
+       int filter;
+       
+       /* filter data */
+       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
+       
+       /* loop through relevant data, removing keyframes from the ipo-blocks that were attached 
+        *      - all keyframes are converted in/out of global time 
+        */
+       for (ale= act_data.first; ale; ale= ale->next) {
+               if (NLA_ACTION_SCALED) {
+                       actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); 
+                       posttrans_ipo_clean(ale->key_data);
+                       actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
+               }
+               else 
+                       posttrans_ipo_clean(ale->key_data);
+       }
+       
+       /* free temp data */
+       BLI_freelistN(&act_data);
+ }
+ /* ----------------------------- */
  /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
  static short FrameOnMouseSide(char side, float frame, float cframe)
  {
@@@ -3003,9 -3098,9 +3099,9 @@@ short autokeyframe_cfra_can_key(Object 
        
        /* get keyframes that object has (bone anim is stored on ob too) */
        if (ob->action)
-               action_to_keylist(ob->action, &keys, NULL);
+               action_to_keylist(ob->action, &keys, NULL, NULL);
        else if (ob->ipo)
-               ipo_to_keylist(ob->ipo, &keys, NULL);
+               ipo_to_keylist(ob->ipo, &keys, NULL, NULL);
        else
                return 0;
                
@@@ -3294,7 -3389,6 +3390,6 @@@ void special_aftertrans_update(TransInf
                ob = OBACT;
                
                if (datatype == ACTCONT_ACTION) {
-                       /* Update the curve */
                        /* Depending on the lock status, draw necessary views */
                        if (ob) {
                                ob->ctime= -1234567.0f;
                                        DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
                        }
                        
+                       /* Do curve updates */
                        remake_action_ipos((bAction *)data);
                        
+                       /* Do curve cleanups? */
+                       if ((G.saction->flag & SACTION_NOTRANSKEYCULL)==0)
+                               posttrans_action_clean((bAction *)data);
+                       
                        G.saction->flag &= ~SACTION_MOVING;
                }
                else if (datatype == ACTCONT_SHAPEKEY) {
                                        sort_time_ipocurve(icu);
                                        testhandles_ipocurve(icu);
                                }
+                               
+                               if ((G.saction->flag & SACTION_NOTRANSKEYCULL)==0)
+                                       posttrans_ipo_clean(key->ipo);
                        }
                        
                        DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
        }
        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)) {