Merge from Harmonic Skeleton branch
[blender.git] / source / blender / src / buttons_editing.c
index d5b3feae81016246f575c826f81894d7f2fd1d0b..a6ba07bfb34ee0e8f78abb564b0cfe726d202b8b 100644 (file)
@@ -66,6 +66,7 @@
 #include "DNA_nla_types.h"
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_particle_types.h"
 #include "DNA_radio_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_texture_types.h"
 #include "BKE_key.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_packedFile.h"
+#include "BKE_particle.h"
 #include "BKE_scene.h"
 
 #include "BLI_blenlib.h"
 #include "BIF_editfont.h"
 #include "BIF_editkey.h"
 #include "BIF_editmesh.h"
+#include "BIF_editparticle.h"
 #include "BIF_imasel.h"
 #include "BIF_interface.h"
 #include "BIF_meshtools.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_effect.h"
 #include "BKE_font.h"
+#include "BKE_icons.h"
 #include "BKE_image.h"
 #include "BKE_ipo.h"
 #include "BKE_lattice.h"
@@ -384,6 +389,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
        EditFace *efa;
        Base *base;
        Object *ob= OBACT;
+       Material *ma;
        Nurb *nu;
        Curve *cu;
        BezTriple *bezt;
@@ -396,8 +402,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
        case B_MATWICH:
                if(G.obedit && G.obedit->actcol>0) {
                        if(G.obedit->type == OB_MESH) {
-                               efa= em->faces.first;
-                               while(efa) {
+                               for(efa= em->faces.first; efa; efa= efa->next) {
                                        if(efa->f & SELECT) {
                                                if(index== -1) index= efa->mat_nr;
                                                else if(index!=efa->mat_nr) {
@@ -405,7 +410,6 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
                                                        return;
                                                }
                                        }
-                                       efa= efa->next;
                                }
                        }
                        else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
@@ -472,6 +476,30 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
                        BIF_undo_push("Assign material index");
                }
                break;
+       case B_MATASS_BROWSE:
+               /* if slot available, make that index active, and assign */
+               /* else, make new slot, and assign */
+               ma= BLI_findlink(&G.main->mat, G.buts->menunr-1);
+               if(ma) {
+                       ob->actcol= find_material_index(ob, ma);
+                       if(ob->actcol==0) {
+                               assign_material(ob, ma, ob->totcol+1);
+                               ob->actcol= ob->totcol;
+                       }
+               }
+               else {
+                       do_common_editbuts(B_MATNEW);
+               }
+               do_common_editbuts(B_MATASS);
+               break;
+               
+       case B_MATCOL2:
+               ma= give_current_material(ob, ob->actcol);
+               BKE_icon_changed(BKE_icon_getid((ID *)ma));
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSEDIT, 0);
+               break;
+               
        case B_MATSEL:
        case B_MATDESEL:
                if(G.obedit) {
@@ -493,14 +521,14 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
                                                        while(a--) {
                                                                if(bezt->hide==0) {
                                                                        if(event==B_MATSEL) {
-                                                                               bezt->f1 |= 1;
-                                                                               bezt->f2 |= 1;
-                                                                               bezt->f3 |= 1;
+                                                                               bezt->f1 |= SELECT;
+                                                                               bezt->f2 |= SELECT;
+                                                                               bezt->f3 |= SELECT;
                                                                        }
                                                                        else {
-                                                                               bezt->f1 &= ~1;
-                                                                               bezt->f2 &= ~1;
-                                                                               bezt->f3 &= ~1;
+                                                                               bezt->f1 &= ~SELECT;
+                                                                               bezt->f2 &= ~SELECT;
+                                                                               bezt->f3 &= ~SELECT;
                                                                        }
                                                                }
                                                                bezt++;
@@ -646,6 +674,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
                allqueue(REDRAWACTION, 0);
                break;
                
+               
        default:
                if (G.vd==NULL)
                        break;
@@ -949,7 +978,7 @@ static uiBlock *modifiers_add_menu(void *ob_v)
                ModifierTypeInfo *mti = modifierType_getInfo(i);
 
                /* Only allow adding through appropriate other interfaces */
-               if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
+               if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
 
                if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
                   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@ -989,6 +1018,12 @@ static void modifiers_del(void *ob_v, void *md_v)
        if (!md)
                return;
 
+       if(md->type==eModifierType_ParticleSystem){
+               ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
+               BLI_remlink(&ob->particlesystem, psmd->psys);
+               psys_free(ob,psmd->psys);
+       }
+
        BLI_remlink(&ob->modifiers, md_v);
 
        modifier_free(md_v);
@@ -1200,7 +1235,93 @@ void autocomplete_meshob(char *str, void *arg_v)
                autocomplete_end(autocpl, str);
        }
 }
+static void modifiers_convertParticles(void *obv, void *mdv)
+{
+       Object *obn;
+       ModifierData *md = mdv;
+       ParticleSystem *psys;
+       ParticleCacheKey *key, **cache;
+       Mesh *me;
+       MVert *mvert;
+       MFace *mface;
+       int a, k, kmax;
+       int totvert=0, totface=0, cvert=0;
+       int totpart=0, totchild=0;
+
+       if(md->type != eModifierType_ParticleSystem) return;
 
+       if(G.f & G_PARTICLEEDIT) return;
+
+       psys=((ParticleSystemModifierData *)md)->psys;
+
+       if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
+
+       totpart= psys->totcached;
+       totchild= psys->totchildcache;
+
+       if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
+               totpart= 0;
+
+       /* count */
+       cache= psys->pathcache;
+       for(a=0; a<totpart; a++) {
+               key= cache[a];
+               totvert+= (int)(key->col[3])+1;
+               totface+= (int)(key->col[3]);
+       }
+
+       cache= psys->childcache;
+       for(a=0; a<totchild; a++) {
+               key= cache[a];
+               totvert+= (int)(key->col[3])+1;
+               totface+= (int)(key->col[3]);
+       }
+
+       if(totvert==0) return;
+
+       /* add new mesh */
+       obn= add_object(OB_MESH);
+       me= obn->data;
+       
+       me->totvert= totvert;
+       me->totface= totface;
+       
+       me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+       me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+       
+       mvert= me->mvert;
+       mface= me->mface;
+
+       /* copy coordinates */
+       cache= psys->pathcache;
+       for(a=0; a<totpart; a++){
+               key= cache[a];
+               kmax= (int)(key->col[3]);
+               for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
+                       VECCOPY(mvert->co,key->co);
+                       if(k){
+                               mface->v1= cvert-1;
+                               mface->v2= cvert;
+                               mface++;
+                       }
+               }
+       }
+
+       cache=psys->childcache;
+       for(a=0; a<totchild; a++) {
+               key=cache[a];
+               kmax=(int)(key->col[3]);
+               for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
+                       VECCOPY(mvert->co,key->co);
+                       if(k){
+                               mface->v1=cvert-1;
+                               mface->v2=cvert;
+                               mface++;
+                       }
+               }
+       }
+       make_edges(me, 0);
+}
 static void modifiers_applyModifier(void *obv, void *mdv)
 {
        Object *ob = obv;
@@ -1469,13 +1590,20 @@ static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
        MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
        Object *ob = (Object*)ob_v;
 
-       if(mmd->bindweights) {
-               MEM_freeN(mmd->bindweights);
-               MEM_freeN(mmd->bindcos);
+       if(mmd->bindcos) {
+               if(mmd->bindweights) MEM_freeN(mmd->bindweights);
+               if(mmd->bindcos) MEM_freeN(mmd->bindcos);
+               if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
+               if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
+               if(mmd->dynverts) MEM_freeN(mmd->dynverts);
                mmd->bindweights= NULL;
                mmd->bindcos= NULL;
+               mmd->dyngrid= NULL;
+               mmd->dyninfluences= NULL;
+               mmd->dynverts= NULL;
                mmd->totvert= 0;
                mmd->totcagevert= 0;
+               mmd->totinfluence= 0;
        }
        else {
                DerivedMesh *dm;
@@ -1492,12 +1620,35 @@ static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
                else if(ob->type == OB_LATTICE) {
                        lattice_calc_modifiers(ob);
                }
+               else if(ob->type==OB_MBALL) {
+                       makeDispListMBall(ob);
+               }
+               else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+                       makeDispListCurveTypes(ob, 0);
+               }
 
                mmd->needbind= 0;
                mmd->modifier.mode= mode;
        }
 }
 
+void modifiers_explodeFacepa(void *arg1, void *arg2)
+{
+       ExplodeModifierData *emd=arg1;
+
+       emd->flag |= eExplodeFlag_CalcFaces;
+}
+
+static void modifiers_psysEnable(void *ob_v, void *md_v)
+{
+       ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md_v;
+
+       if(psmd->modifier.mode & eModifierMode_Realtime)
+               psmd->psys->flag |= PSYS_ENABLED;
+       else
+               psmd->psys->flag &= ~PSYS_ENABLED;
+}
+
 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
 {
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1536,7 +1687,9 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        /* Softbody not allowed in this situation, enforce! */
                if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
                        uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
-                       uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
+                       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 (md->type==eModifierType_ParticleSystem)
+                               uiButSetFunc(but, modifiers_psysEnable, ob, md);
                        if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
                                uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
                        }
@@ -1596,7 +1749,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                } else if (md->type==eModifierType_Build) {
                        height = 86;
                } else if (md->type==eModifierType_Mirror) {
-                       height = 67;
+                       height = 86;
                } else if (md->type==eModifierType_EdgeSplit) {
                        EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
                        height = 48;
@@ -1624,7 +1777,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        if(wmd->flag & MOD_WAVE_NORM)
                                height += 19;
                } else if (md->type==eModifierType_Armature) {
-                       height = 86;
+                       height = 105;
                } else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
                        height = 86;
@@ -1633,15 +1786,22 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        if(hmd->indexar==NULL)
                                height += 20;
                } else if (md->type==eModifierType_Softbody) {
-                       height = 26;
+                       height = 31;
                } else if (md->type==eModifierType_Boolean) {
                        height = 48;
                } else if (md->type==eModifierType_Array) {
                        height = 211;
                } else if (md->type==eModifierType_MeshDeform) {
-                       height = 73;
-               } 
-               
+                       MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
+                       height = (mmd->bindcos)? 73: 93;
+               } else if (md->type==eModifierType_ParticleSystem) {
+                       height = 31;
+               } else if (md->type==eModifierType_ParticleInstance) {
+                       height = 94;
+               } 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, ""); 
 
@@ -1649,9 +1809,16 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 
                if (!isVirtual) {
                        uiBlockBeginAlign(block);
-                       but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
-                       uiButSetFunc(but, modifiers_applyModifier, ob, md);
-                       if (md->type!=eModifierType_Softbody) {
+                       if (md->type==eModifierType_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_convertParticles, ob, md);
+                       }
+                       else{
+                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
+                               uiButSetFunc(but, modifiers_applyModifier, ob, md);
+                       }
+                       
+                       if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
                                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);
                        }
@@ -1719,6 +1886,11 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                                     &mmd->flag, 0, 0, 0, 0,
                                     "Mirror the V texture coordinate around "
                                     "the 0.5 point");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                      "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+                                      &mmd->mirror_ob,
+                                      "Object to use as mirror");
+
                } else if (md->type==eModifierType_EdgeSplit) {
                        EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
                        uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
@@ -1755,7 +1927,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                                  "Material value that gives no displacement");
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
                                  lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
-                                 -1000, 1000, 10, 10,
+                                 -1000, 1000, 10, 0.1,
                                  "Strength of displacement");
                        sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
                                "Z%%x%d|Y%%x%d|X%%x%d",
@@ -1943,12 +2115,17 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        ArmatureModifierData *amd = (ArmatureModifierData*) md;
                        uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
                        
-                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
                        uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv",        lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence");
+                       
                        uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups",       lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
                        uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes",       lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
                        uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion",    lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
                        uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position");
+                       
+                       uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier",        lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup");
+
                } else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
@@ -2129,16 +2306,50 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        uiDefButBitS(block, TOG, MOD_MDEF_INVERT_VGROUP, B_MODIFIER_RECALC, "Inv", lx+buttonWidth-40, (cy-=19), 40,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
 
                        uiBlockBeginAlign(block);
-                       if(mmd->bindweights) {
-                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
+                       if(mmd->bindcos) {
+                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
                                uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
                        }
                        else {
-                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-24), buttonWidth/2,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
+                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
                                uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
-                               uiDefButS(block, NUM, B_NOP, "Precision:", lx+(buttonWidth+1)/2,(cy-=24), buttonWidth/2,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
+                               uiDefButS(block, NUM, B_NOP, "Precision:", lx,(cy-19), buttonWidth/2 + 20,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
+                               uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
                        }
                        uiBlockEndAlign(block);
+               } else if (md->type==eModifierType_ParticleSystem) {
+                       uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_ParticleInstance) {
+                       ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
+                       uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Parents, B_MODIFIER_RECALC, "Normal",    lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from normal particles");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Children, B_MODIFIER_RECALC, "Children", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from child particles");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Path, B_MODIFIER_RECALC, "Path", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances along particle paths");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Unborn, B_MODIFIER_RECALC, "Unborn",     lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are unborn");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Alive, B_MODIFIER_RECALC, "Alive",       lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are alive");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are dead");
+               } else if (md->type==eModifierType_Explode) {
+                       ExplodeModifierData *emd = (ExplodeModifierData*) md;
+                       uiBut *but;
+                       char *menustr= get_vertexgroup_menustr(ob);
+                       int defCount=BLI_countlist(&ob->defbase);
+                       if(defCount==0) emd->vgroup=0;
+
+                       but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth/2,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+                       MEM_freeN(menustr);
+
+                       but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+
+                       but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+
+                       uiDefButBitS(block, TOG, eExplodeFlag_EdgeSplit, B_MODIFIER_RECALC, "Split Edges",      lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->flag, 0, 0, 0, 0, "Split face edges for nicer shrapnel");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Unborn, B_MODIFIER_RECALC, "Unborn",      lx, (cy-=19), buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are unborn");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Alive, B_MODIFIER_RECALC, "Alive",        lx+buttonWidth/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are alive");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Dead, B_MODIFIER_RECALC, "Dead",  lx+buttonWidth*2/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are dead");
                }
 
                uiBlockEndAlign(block);
@@ -2160,6 +2371,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
        }
 
+       uiClearButLock();
+
        y -= 3+6;
 
        *xco = x;
@@ -2197,7 +2410,7 @@ static void editing_panel_modifiers(Object *ob)
        if(yco < 0) uiNewPanelHeight(block, 204-yco);
 }
 
-static char *make_key_menu(Key *key)
+static char *make_key_menu(Key *key, int startindex)
 {
        KeyBlock *kb;
        int index= 1;
@@ -2207,7 +2420,7 @@ static char *make_key_menu(Key *key)
        str= MEM_mallocN(index*40, "key string");
        str[0]= 0;
        
-       index= 1;
+       index= startindex;
        for (kb = key->block.first; kb; kb=kb->next, index++) {
                sprintf (item,  "|%s%%x%d", kb->name, index);
                strcat(str, item);
@@ -2251,14 +2464,17 @@ static void editing_panel_shapes(Object *ob)
        uiBlockBeginAlign(block);
        if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
        uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
+       if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
+       uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
        uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
-       uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
-       strp= make_key_menu(key);
-       uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
+       uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
+       strp= make_key_menu(key, 1);
+       uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
        MEM_freeN(strp);
-       uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
+       
+       uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
        uiClearButLock();
-       uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
+       uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
        uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
        uiBlockEndAlign(block);
 
@@ -2269,9 +2485,14 @@ static void editing_panel_shapes(Object *ob)
                uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
                uiBlockEndAlign(block);
        }
-       if(key->type && ob->shapenr!=1)
+       if(key->type && ob->shapenr!=1) {
                uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",     10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
 
+               strp= make_key_menu(key, 0);
+               uiDefButS(block, MENU, B_MODIFIER_RECALC, strp,         160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key");
+               MEM_freeN(strp);
+       }
+       
        if(key->type==0)
                uiDefButS(block, NUM, B_DIFF, "Slurph:",                        10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first");
        
@@ -2918,6 +3139,40 @@ void do_curvebuts(unsigned short event)
                allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
 
                break;
+       
+       /* Buttons for aligning handles */
+       case B_SETPT_AUTO:
+               if(ob->type==OB_CURVE) {
+                       sethandlesNurb(1);
+                       BIF_undo_push("Auto Curve Handles");
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+               break;
+       case B_SETPT_VECTOR:
+               if(ob->type==OB_CURVE) {
+                       sethandlesNurb(2);
+                       BIF_undo_push("Vector Curve Handles");
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+               break;
+       case B_SETPT_ALIGN:
+               if(ob->type==OB_CURVE) {
+                       sethandlesNurb(5);
+                       BIF_undo_push("Align Curve Handles");
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+               break;
+       case B_SETPT_FREE:
+               if(ob->type==OB_CURVE) {
+                       sethandlesNurb(6);
+                       BIF_undo_push("Free Align Curve Handles");
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       allqueue(REDRAWVIEW3D, 0);
+               }
+               break;
        }
 }
 
@@ -3722,15 +3977,23 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm)
                arm->pathsf = SFRA;
                arm->pathef = EFRA;
        }
+       if ((arm->pathbc == 0) || (arm->pathac == 0)) {
+               arm->pathbc = 15;
+               arm->pathac = 15;
+       }
        
        /* Ghost Drawing Options */
        uiDefBut(block, LABEL, 0, "Ghost Options", 10,180,150,20, 0, 0, 0, 0, 0, "");
 
        uiBlockBeginAlign(block);
-       uiDefButS(block, MENU, REDRAWVIEW3D, "Ghosts %t|Around Current Frame %x0|In Range %x1", 
-                                                                                               10, 160, 150, 20, &arm->ghosttype, 0, 0, 0, 0, "Choose range of Ghosts to draw for current Action");    
-       
-       uiDefButS(block, NUM, REDRAWVIEW3D, "GStep: ", 10,140,150,20, &arm->ghostsize, 1.0f, 20.0f, 0, 0, "How many frames between Ghost instances");
+               uiDefButS(block, MENU, REDRAWVIEW3D, "Ghosts %t|Around Current Frame %x0|In Range %x1|On Keyframes %x2", 
+                                                                                                       10, 160, 150, 20, &arm->ghosttype, 0, 0, 0, 0, "Choose range of Ghosts to draw for current Action");    
+               
+               if (arm->ghosttype != ARM_GHOST_KEYS)
+                       uiDefButS(block, NUM, REDRAWVIEW3D, "GStep: ", 10,140,120,20, &arm->ghostsize, 1.0f, 20.0f, 0, 0, "How many frames between Ghost instances");
+               else
+                       uiDefBut(block, LABEL, REDRAWVIEW3D, "GStep: N/A", 10,140,120,20, NULL, 0.0f, 0.0f, 0, 0, "How many frames between Ghost instances");
+               uiDefButBitI(block, TOG, ARM_GHOST_ONLYSEL, REDRAWVIEW3D, "Sel", 130, 140, 30, 20, &arm->flag, 0, 0, 0, 0, "Only show Ghosts for selected bones");
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
@@ -3738,7 +4001,7 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm)
                /* range is around current frame */
                uiDefButS(block, NUM, REDRAWVIEW3D, "Ghost: ", 10,110,150,20, &arm->ghostep, 0.0f, 30.0f, 0, 0, "Draw Ghosts around current frame, for current Action");
        }
-       else if (arm->ghosttype == ARM_GHOST_RANGE) {
+       else if (ELEM(arm->ghosttype, ARM_GHOST_RANGE, ARM_GHOST_KEYS)) {
                /* range is defined by start+end frame below */
                uiDefButI(block, NUM,REDRAWVIEW3D,"GSta:",10,110,150,20, &arm->ghostsf,1.0,MAXFRAMEF, 0, 0, "The start frame for Ghost display range");
                uiDefButI(block, NUM,REDRAWVIEW3D,"GEnd:",10,90,150,20, &arm->ghostef,arm->ghostsf,MAXFRAMEF, 0, 0, "The end frame for Ghost display range");   
@@ -3746,23 +4009,38 @@ static void editing_panel_armature_visuals(Object *ob, bArmature *arm)
        uiBlockEndAlign(block);
        
        /* Bone Path Drawing Options */
-       uiDefBut(block, LABEL, 0, "Bone Paths", 165,180,150,20, 0, 0, 0, 0, 0, "");
+       uiDefBut(block, LABEL, 0, "Bone Paths Drawing:", 165,180,170,20, 0, 0, 0, 0, 0, "");
        
        uiBlockBeginAlign(block);
-       uiDefButBitS(block, TOG, ARM_PATH_FNUMS, REDRAWVIEW3D, "Frame Nums", 170, 160, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers on path");
-       uiDefButS(block, NUM, REDRAWVIEW3D, "PStep:",250,160,80,20, &arm->pathsize,1,100, 10, 50, "Frames between highlighted points on bone path");
-       uiDefButBitS(block, TOG, ARM_PATH_KFRAS, REDRAWVIEW3D, "Show Keys", 170, 140, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Show key frames on path");
+               uiDefButS(block, NUM, REDRAWVIEW3D, "PStep:",170,160,80,20, &arm->pathsize,1,100, 10, 50, "Frames between highlighted points on bone path");
+               uiDefButBitS(block, TOG, ARM_PATH_FNUMS, REDRAWVIEW3D, "Frame Nums", 250, 160, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers on path");
+               
+               uiDefButBitS(block, TOG, ARM_PATH_KFRAS, REDRAWVIEW3D, "Show Keys", 170, 140, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show key frames on path");
+               uiDefButBitS(block, TOG, ARM_PATH_KFNOS, REDRAWVIEW3D, "Keyframe Nums", 250, 140, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers of key frames on path");
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
-       uiDefButI(block, NUM,REDRAWVIEW3D,"PSta:",170,100,80,20, &arm->pathsf, 1.0, MAXFRAMEF, 0, 0, "The start frame for Bone Path display range");
-       uiDefButI(block, NUM,REDRAWVIEW3D,"PEnd:",250,100,80,20, &arm->pathef, arm->pathsf, MAXFRAMEF, 0, 0, "The end frame for Bone Path display range");      
-       uiDefButBitS(block, TOG, ARM_PATH_HEADS, REDRAWVIEW3D, "Bone-Head Path", 170, 80, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate the Path travelled by the Bone's Head instead of Tail");
+               uiDefButBitS(block, TOG, ARM_PATH_ACFRA, REDRAWVIEW3D, "Around Current Frame", 170, 110, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Only show Bone Path around the current frame");
+               
+               /* only show extra ranges when needed */
+               if (arm->pathflag & ARM_PATH_ACFRA) {
+                       uiDefButI(block, NUM, REDRAWVIEW3D,"PPre:",170,90,80,20, &arm->pathbc, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames before current frame for Bone Path display range");
+                       uiDefButI(block, NUM, REDRAWVIEW3D,"PPost:",250,90,80,20, &arm->pathac, 1.0, MAXFRAMEF/2, 0, 0, "The number of frames after current frame for Bone Path display range");        
+               }
+       uiBlockEndAlign(block);
+       
+       /* Bone Path Calculation Options */
+       uiDefBut(block, LABEL, 0, "Bone Paths Calc.", 10,50,170,20, 0, 0, 0, 0, 0, "");
+       
+       uiBlockBeginAlign(block);
+               uiDefBut(block, BUT, B_ARM_CALCPATHS, "Calculate Paths", 10,30,155,20, 0, 0, 0, 0, 0, "(Re)calculates the paths of the selected bones");
+               uiDefBut(block, BUT, B_ARM_CLEARPATHS, "Clear Paths", 10,10,155,20, 0, 0, 0, 0, 0, "Clears bone paths of the selected bones");
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
-       uiDefBut(block, BUT, B_ARM_CALCPATHS, "Calculate Paths", 170,40,160,20, 0, 0, 0, 0, 0, "(Re)calculates the paths of the selected bones");
-       uiDefBut(block, BUT, B_ARM_CLEARPATHS, "Clear All Paths", 170,20,160,20, 0, 0, 0, 0, 0, "Clears all bone paths");
+               uiDefButBitS(block, TOG, ARM_PATH_HEADS, REDRAWVIEW3D, "Bone-Head Path", 170, 30, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate the Path travelled by the Bone's Head instead of Tail");
+               uiDefButI(block, NUM,REDRAWVIEW3D,"PSta:",170,10,80,20, &arm->pathsf, 1.0, MAXFRAMEF, 0, 0, "The start frame for Bone Path display range");
+               uiDefButI(block, NUM,REDRAWVIEW3D,"PEnd:",250,10,80,20, &arm->pathef, arm->pathsf, MAXFRAMEF, 0, 0, "The end frame for Bone Path display range");
        uiBlockEndAlign(block);
 }
 
@@ -3838,10 +4116,11 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
                        uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
 
                        /* bone types */
-                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,85,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
-                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   75, by-38, 85, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 160,by-38,85,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
-                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   245,by-38,85,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          70,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   250,by-38,80,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
                        
                        /* layers */
                        uiBlockBeginAlign(block);
@@ -3933,11 +4212,12 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
                        uiDefButF(block, NUM,B_ARM_RECALCDATA, "Out:",          220, by-19, 110, 19, &curBone->ease2, 0.0, 2.0, 10.0, 0.0, "Second length of Bezier handle");
                        
                        /* bone types */
-                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", -10,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
-                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   70, by-38, 80, 19, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 150,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",                 -10,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",                  70,by-38,20,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
+                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 19, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult",    170,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
                        ob_arm_bone_pchan_lock(ob, arm, curBone, pchan);
-                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "OB:",      230,by-38,100,19, &pchan->custom, "Object that defines custom draw type for this Bone");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "OB:",              250,by-38,80,19, &pchan->custom, "Object that defines custom draw type for this Bone");
                        ob_arm_bone_pchan_lock(ob, arm, curBone, NULL);
                        
                        /* layers */
@@ -4285,7 +4565,7 @@ void do_meshbuts(unsigned short event)
                G.f -= G_DISABLE_OK;
                break;
        case B_REMDOUB:
-               count= removedoublesflag(1, 1, G.scene->toolsettings->doublimit);
+               count= removedoublesflag(1, 0, G.scene->toolsettings->doublimit);
                notice("Removed: %d", count);
                if (count) { /* only undo and redraw if an action is taken */
                        countall ();
@@ -4533,7 +4813,7 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
 #endif
        
        uiBlockEndAlign(block);
-
+       
        uiBlockBeginAlign(block);
        uiDefButBitI(block, TOG, G_ALLEDGES, 0, "All Edges",                    1125, 22,150,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization");
        uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation");
@@ -4544,7 +4824,7 @@ char *get_vertexgroup_menustr(Object *ob)
 {
        bDeformGroup *dg;
        int defCount, min, index;
-       char (*qsort_ptr)[sizeof(dg->name)+5] = NULL; // +5 for "%x99|"
+       char (*qsort_ptr)[sizeof(dg->name)+6] = NULL; // +6 for "%x999|" max 999 groups selectable
        char *s, *menustr;
        int printed;
        
@@ -4562,7 +4842,7 @@ char *get_vertexgroup_menustr(Object *ob)
                                                                 "qsort_ptr");
                for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) {
                        printed = snprintf (qsort_ptr[index - 1], sizeof (dg->name), dg->name);
-                       snprintf (qsort_ptr[index - 1]+printed, 5+1, "%%x%d|", index); // +1 to move the \0
+                       snprintf (qsort_ptr[index - 1]+printed, 6+1, "%%x%d|", index); // +1 to move the \0   see above 999 max here too
                }
                
                qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]),
@@ -4740,23 +5020,30 @@ static void editing_panel_links(Object *ob)
        if(ob->totcol) min= 1.0; else min= 0.0;
        ma= give_current_material(ob, ob->actcol);
 
-       if(ma) uiDefBut(block, LABEL, 0, ma->id.name+2, 318,153, 103, 20, 0, 0, 0, 0, 0, "");
+       if(G.obedit) {
+               char *str= NULL;
+               IDnames_to_pupstring(&str, NULL, "ADD NEW %x 32767", &G.main->mat, NULL, NULL);
+               uiDefButS(block, MENU, B_MATASS_BROWSE, str, 292,150,20,20, &G.buts->menunr, 0, 0, 0, 0, "Browses existing choices and assign");
+               MEM_freeN(str);
+       }
+       
+       if(ma) uiDefBut(block, LABEL, 0, ma->id.name+2, 318,150, 103, 20, 0, 0, 0, 0, 0, "");
 
        uiBlockBeginAlign(block);
-       if(ma) uiDefButF(block, COL, B_REDR, "",                        292,123,31,30, &(ma->r), 0, 0, 0, 0, "");
-       uiDefButC(block, NUM, B_ACTCOL, str,            324,123,100,30, &ob->actcol, min, (float)(ob->totcol), 0, 0, "Displays total number of material indices and the current index");
-       uiDefBut(block, BUT,B_MATWICH,  "?",            424,123,30,30, 0, 0, 0, 0, 0, "In EditMode, sets the active material index from selected faces");
+       if(ma) uiDefButF(block, COL, B_MATCOL2, "",     292,113,31,30, &(ma->r), 0, 0, 0, 0, "");
+       uiDefButC(block, NUM, B_ACTCOL, str,            324,113,100,30, &ob->actcol, min, (float)(ob->totcol), 0, 0, "Displays total number of material indices and the current index");
+       uiDefBut(block, BUT,B_MATWICH,  "?",            424,113,30,30, 0, 0, 0, 0, 0, "In EditMode, sets the active material index from selected faces");
 
        uiBlockBeginAlign(block);
-       uiDefBut(block, BUT,B_MATNEW,   "New",          292,98,80,20, 0, 0, 0, 0, 0, "Adds a new Material index");
-       uiDefBut(block, BUT,B_MATDEL,   "Delete",       374,98,80,20, 0, 0, 0, 0, 0, "Deletes this Material index");
-       uiDefBut(block, BUT,B_MATSEL,   "Select",       292,76,80,20, 0, 0, 0, 0, 0, "In EditMode, selects faces that have the active index");
-       uiDefBut(block, BUT,B_MATDESEL, "Deselect",     374,76,80,20, 0, 0, 0, 0, 0, "Deselects everything with current indexnumber");
-       uiDefBut(block, BUT,B_MATASS,   "Assign",       292,47,162,26, 0, 0, 0, 0, 0, "In EditMode, assigns the active index to selected faces");
+       uiDefBut(block, BUT,B_MATNEW,   "New",          292,90,80,20, 0, 0, 0, 0, 0, "Adds a new Material index");
+       uiDefBut(block, BUT,B_MATDEL,   "Delete",       372,90,80,20, 0, 0, 0, 0, 0, "Deletes this Material index");
+       uiDefBut(block, BUT,B_MATSEL,   "Select",       292,70,80,20, 0, 0, 0, 0, 0, "In EditMode, selects faces that have the active index");
+       uiDefBut(block, BUT,B_MATDESEL, "Deselect",     372,70,80,20, 0, 0, 0, 0, 0, "Deselects everything with current indexnumber");
+       uiDefBut(block, BUT,B_MATASS,   "Assign",       292,50,160,20, 0, 0, 0, 0, 0, "In EditMode, assigns the active index to selected faces");
 
        uiBlockBeginAlign(block);
-       uiDefBut(block, BUT,B_SETSMOOTH,"Set Smooth",   291,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'smooth' rendering of selected faces");
-       uiDefBut(block, BUT,B_SETSOLID, "Set Solid",    373,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'solid' rendering of selected faces");
+       uiDefBut(block, BUT,B_SETSMOOTH,"Set Smooth",   292,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'smooth' rendering of selected faces");
+       uiDefBut(block, BUT,B_SETSOLID, "Set Solid",    372,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'solid' rendering of selected faces");
 
        uiBlockEndAlign(block);
 
@@ -4961,6 +5248,7 @@ void do_fpaintbuts(unsigned short event)
        ToolSettings *settings= G.scene->toolsettings;
        int nr= 1;
        MTex *mtex;
+       ParticleSystem *psys;
 
        ob= OBACT;
        if(ob==NULL) return;
@@ -5235,6 +5523,20 @@ void do_fpaintbuts(unsigned short event)
                allqueue(REDRAWIMAGE, 0);
                allqueue(REDRAWBUTSEDIT, 0);
                break;
+       case B_BAKE_REDRAWEDIT:
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSEDIT, 0);
+               break;
+       case B_BAKE_RECACHE:
+               psys=PE_get_current(ob);
+               PE_hide_keys_time(psys,CFRA);
+               psys_cache_paths(ob,psys,CFRA,0);
+               if(PE_settings()->flag & PE_SHOW_CHILD)
+                       psys_cache_child_paths(ob,psys,CFRA,0);
+               
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSEDIT, 0);
+               break;
        }
 }
 
@@ -5272,7 +5574,7 @@ void weight_paint_buttons(uiBlock *block)
        uiDefButS(block, ROW, B_DIFF, "Add",            250,152,60,17, &Gwp.mode, 1.0, 1.0, 0, 0, "Add the vertex colors");
        uiDefButS(block, ROW, B_DIFF, "Sub",            250,134,60,17, &Gwp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex color");
        uiDefButS(block, ROW, B_DIFF, "Mul",            250,116,60,17, &Gwp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex color");
-       uiDefButS(block, ROW, B_DIFF, "Filter",         250, 98,60,17, &Gwp.mode, 1.0, 4.0, 0, 0, "Mix the colors with an alpha factor");
+       uiDefButS(block, ROW, B_DIFF, "Blur",           250, 98,60,17, &Gwp.mode, 1.0, 4.0, 0, 0, "Blur the weight with surrounding values");
        uiDefButS(block, ROW, B_DIFF, "Lighter",        250, 80,60,17, &Gwp.mode, 1.0, 5.0, 0, 0, "Paint over darker areas only");
        uiDefButS(block, ROW, B_DIFF, "Darker",         250, 62,60,17, &Gwp.mode, 1.0, 6.0, 0, 0, "Paint over lighter areas only");
        uiBlockEndAlign(block);
@@ -5337,7 +5639,7 @@ static void editing_panel_mesh_paint(void)
                uiDefButS(block, ROW, B_DIFF, "Add",                    1212,152,63,17, &Gvp.mode, 1.0, 1.0, 0, 0, "Add the vertex color");
                uiDefButS(block, ROW, B_DIFF, "Sub",                    1212, 134,63,17, &Gvp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex color");
                uiDefButS(block, ROW, B_DIFF, "Mul",                    1212, 116,63,17, &Gvp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex color");
-               uiDefButS(block, ROW, B_DIFF, "Filter",                 1212, 98,63,17, &Gvp.mode, 1.0, 4.0, 0, 0, "Mix the colors with an alpha factor");
+               uiDefButS(block, ROW, B_DIFF, "Blur",                   1212, 98,63,17, &Gvp.mode, 1.0, 4.0, 0, 0, "Blur the color with surrounding values");
                uiDefButS(block, ROW, B_DIFF, "Lighter",                1212, 80,63,17, &Gvp.mode, 1.0, 5.0, 0, 0, "Paint over darker areas only");
                uiDefButS(block, ROW, B_DIFF, "Darker",                 1212, 62,63,17, &Gvp.mode, 1.0, 6.0, 0, 0, "Paint over lighter areas only");
                uiBlockEndAlign(block);
@@ -5580,6 +5882,127 @@ void editing_panel_mesh_multires()
        uiBlockEndAlign(block);
 }
 
+void particle_edit_buttons(uiBlock *block)
+{
+       Object *ob=OBACT;
+       ParticleSystem *psys = PE_get_current(ob);
+       ParticleEditSettings *pset = PE_settings();
+       ParticleEdit *edit;
+       uiBut *but;
+       short butx=10,buty=150,butw=150,buth=20, lastbuty;
+       static short partact;
+
+       char *menustr;
+       
+       if(psys==NULL) return;
+       
+       menustr = psys_menu_string(ob, 0);
+       partact = PE_get_current_num(ob)+1;
+       
+       but=uiDefButS(block, MENU, B_BAKE_REDRAWEDIT, menustr, 160,180,butw,buth, &partact, 14.0, 0.0, 0, 0, "Browse systems");
+       uiButSetFunc(but, PE_change_act, ob, &partact);
+
+       MEM_freeN(menustr);
+
+       if(psys->edit) {
+               edit= psys->edit;
+
+               /* brushes */
+               //uiDefBut(block, LABEL, 0, "Brush",    butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
+               uiBlockBeginAlign(block);       
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"None",butx,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_NONE,0,0,"Disable brush");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Comb",butx+75,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_COMB,0,0,"Comb hairs");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Smooth",butx+150,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_SMOOTH,0,0,"Smooth hairs");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Weight",butx+225,buty,75,19,&pset->brushtype,14,PE_BRUSH_WEIGHT,0,0,"Weight hairs");
+               buty-= buth;
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Add", butx,buty,75,19,&pset->brushtype,14,PE_BRUSH_ADD,0,0,"Add hairs");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Length", butx+75,buty,75,19,&pset->brushtype,14, PE_BRUSH_LENGTH,0,0,"Make hairs longer or shorter");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Puff", butx+150,buty,75,19,&pset->brushtype,14, PE_BRUSH_PUFF,0,0,"Make hairs stand up");
+               uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Cut", butx+225,buty,75,19,&pset->brushtype,14, PE_BRUSH_CUT,0,0,"Cut hairs");
+               uiBlockEndAlign(block);
+
+               buty-= 10;
+               lastbuty= buty;
+
+               /* brush options */
+               if(pset->brushtype>=0) {
+                       ParticleBrushData *brush= &pset->brush[pset->brushtype];
+
+                       butw= 180;
+
+                       uiBlockBeginAlign(block);
+                       uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Size:", butx,(buty-=buth),butw,buth, &brush->size, 1.0, 100.0, 1, 1, "Brush size");
+                       uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Strength:", butx,(buty-=buth),butw,buth, &brush->strength, 1.0, 100.0, 1, 1, "Brush strength");
+
+                       if(ELEM(pset->brushtype, PE_BRUSH_LENGTH, PE_BRUSH_PUFF)) {
+                               char *str1, *str2, *tip1, *tip2;
+
+                               if(pset->brushtype == PE_BRUSH_LENGTH) {
+                                       str1= "Grow"; tip1= "Make hairs longer [Shift]";
+                                       str2= "Shrink"; tip2= "Make hairs shorter [Shift]";
+                               }
+                               else /*if(pset->brushtype == PE_BRUSH_PUFF)*/ {
+                                       str1= "Add"; tip1= "Make hair more puffy [Shift]";
+                                       str2= "Sub"; tip2= "Make hair less puffy [Shift]";
+                               }
+
+                               uiDefButS(block,ROW,B_NOP,str1, butx,(buty-=buth),butw/2,buth,&brush->invert,0.0,0.0,0, 0,tip1);
+                               uiDefButS(block,ROW,B_NOP,str2, butx+butw/2,buty,butw/2,buth,&brush->invert,0.0,1.0,0, 0,tip2);
+                       }
+                       uiBlockEndAlign(block);
+
+                       butx += butw+10;
+                       buty= lastbuty;
+                       butw= 110;
+
+                       if(pset->brushtype==PE_BRUSH_ADD) {
+                               uiBlockBeginAlign(block);
+                               uiDefButBitS(block, TOG, PE_INTERPOLATE_ADDED, B_BAKE_REDRAWEDIT, "Interpolate",        butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Interpolate new particles from the existing ones");
+                               uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Step:",    butx,(buty-=buth),butw,buth, &brush->step, 1.0, 50.0, 1, 1, "Brush step");
+                               uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Keys:",    butx,(buty-=buth),butw,buth, &pset->totaddkey, 2.0, 20.0, 1, 1, "How many keys to make new particles with");
+                               uiBlockEndAlign(block);
+                       }
+               }
+
+               /* keep options */
+               butw= 150;
+               butx= 10;
+               buty= lastbuty - (buth*3 + 10);
+               lastbuty= buty;
+
+               uiDefBut(block, LABEL, 0, "Keep",       butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
+               uiBlockBeginAlign(block);
+               uiDefButBitS(block, TOG, PE_KEEP_LENGTHS, B_BAKE_REDRAWEDIT, "Lengths", butx,(buty-=buth),butw/2,buth, &pset->flag, 0, 0, 0, 0, "Keep path lengths constant");
+               uiDefButBitS(block, TOG, PE_LOCK_FIRST, B_BAKE_REDRAWEDIT, "Root",       butx+butw/2,buty,butw/2,buth, &pset->flag, 0, 0, 0, 0, "Keep first keys unmodified");
+               uiBlockEndAlign(block);
+
+               buty -= 5;
+
+               uiBlockBeginAlign(block);
+               uiDefButBitS(block, TOG, PE_DEFLECT_EMITTER, B_BAKE_REDRAWEDIT, "Deflect Emitter",      butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Keep paths from intersecting the emitter");
+               uiDefButF(block, NUM, B_BAKE_REDRAWEDIT, "Dist:",               butx,(buty-=buth),butw,buth, &pset->emitterdist, 0.0, 10.0, 1, 1, "Distance from emitter");
+               uiBlockEndAlign(block);
+
+               buty= lastbuty;
+               butx += butw+10;
+               butw -= 10;
+
+               uiDefBut(block, LABEL, 0, "Draw",       butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
+               uiBlockBeginAlign(block);
+               uiDefButS(block, NUMSLI, B_BAKE_RECACHE, "Steps:",      butx,(buty-=buth),butw,buth, &psys->part->draw_step, 0.0, 10.0, 1, 1, "Drawing accuracy of paths");
+               uiBlockEndAlign(block);
+
+               buty -= 5;
+
+               uiBlockBeginAlign(block);
+               uiDefButBitS(block, TOG, PE_SHOW_TIME, B_BAKE_REDRAWEDIT, "Show Time",  butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Show time values of the baked keys");
+               uiDefButBitS(block, TOG, PE_SHOW_CHILD, B_BAKE_RECACHE, "Show Children",        butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Show child particles in particle mode");
+               uiBlockEndAlign(block);
+       }
+       else{
+               uiDefBut(block, LABEL, 0, "System isn't editable",      butx,(buty-=buth),250,buth, NULL, 0.0, 0, 0, 0, "");
+       }
+}
 /* this is a mode context sensitive system */
 
 void editing_panels()