Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
[blender.git] / source / blender / src / editobject.c
index 749dcc0ffae3ba9c12190b7167926bc5848b1884..d46c06bd4b9ecd39d24e73a5bfa9fafbb59b5536 100644 (file)
@@ -62,7 +62,6 @@
 #include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_effect_types.h"
-#include "DNA_ika_types.h"
 #include "DNA_image_types.h"
 #include "DNA_ipo_types.h"
 #include "DNA_key_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_world_types.h"
+#include "DNA_modifier_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 
-#include "BKE_constraint.h"
 #include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_utildefines.h"
 #include "BKE_anim.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
 #include "BKE_blender.h"
 #include "BKE_booleanops.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
+#include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_effect.h"
 #include "BKE_font.h"
 #include "BKE_global.h"
-#include "BKE_ika.h"
 #include "BKE_ipo.h"
 #include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_subsurf.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
+#include "BKE_modifier.h"
 
 #include "BIF_gl.h"
 #include "BIF_graphics.h"
 #include "BIF_editconstraint.h"
 #include "BIF_editdeform.h"
 #include "BIF_editfont.h"
-#include "BIF_editika.h"
 #include "BIF_editlattice.h"
 #include "BIF_editmesh.h"
 #include "BIF_editoops.h"
 #include "BIF_resources.h"
 
 #include "BSE_edit.h"
-#include "BSE_editaction.h"
 #include "BSE_editipo.h"
 #include "BSE_filesel.h"       /* For activate_databrowse() */
 #include "BSE_view.h"
 #include "nla.h"
 
 #include "blendef.h"
-
+#include "butspace.h"
 #include "BIF_transform.h"
 
 #include "BIF_poseobject.h"
@@ -183,6 +181,7 @@ void add_object_draw(int type)      /* for toolbox or menus, only non-editmode stuff
        if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
                if (G.obedit) exit_editmode(2); // freedata, and undo
                ob= add_object(type);
+               set_active_base(BASACT);
                base_init_from_view3d(BASACT, G.vd);
                
                /* only undo pushes on objects without editmode... */
@@ -203,6 +202,8 @@ void add_object_draw(int type)      /* for toolbox or menus, only non-editmode stuff
 
        deselect_all_area_oops();
        set_select_flag_oops();
+       
+       DAG_scene_sort(G.scene);
        allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
 }
 
@@ -224,7 +225,7 @@ void add_objectLamp(short type)
        allqueue(REDRAWALL, 0);
 }
 
-// really bad, doesnt do constraints, that has been coded in test_scene_constraints();
+/* note: now unlinks constraints as well */
 void free_and_unlink_base(Base *base)
 {
        if (base==BASACT)
@@ -240,7 +241,6 @@ void delete_obj(int ok)
        Base *base;
        int islamp= 0;
        
-       if(G.obpose) return;
        if(G.obedit) return;
        if(G.scene->id.lib) return;
        
@@ -249,7 +249,7 @@ void delete_obj(int ok)
                Base *nbase= base->next;
 
                if TESTBASE(base) {
-                       if(ok==0 &&  (ok=okee("Erase selected"))==0) return;
+                       if(ok==0 &&  (ok=okee("Erase selected Object(s)"))==0) return;
                        if(base->object->type==OB_LAMP) islamp= 1;
                        
                        free_and_unlink_base(base);
@@ -264,10 +264,8 @@ void delete_obj(int ok)
        
        if(islamp && G.vd->drawtype==OB_SHADED) reshadeall_displist();
 
-       test_scene_constraints(); // do because of delete obj
-       
-       allqueue(REDRAWVIEW3D, 0);
        redraw_test_buttons(OBACT);
+       allqueue(REDRAWVIEW3D, 0);
        allqueue (REDRAWACTION, 0);
        allqueue(REDRAWIPO, 0);
        allqueue(REDRAWDATASELECT, 0);
@@ -275,10 +273,12 @@ void delete_obj(int ok)
        allqueue(REDRAWACTION, 0);
        allqueue(REDRAWNLA, 0);
        
+       DAG_scene_sort(G.scene);
+       
        BIF_undo_push("Delete object(s)");
 }
 
-static int return_editmesh_indexar(int **indexar, float *cent)
+static int return_editmesh_indexar(int *tot, int **indexar, float *cent)
 {
        EditMesh *em = G.editMesh;
        EditVert *eve;
@@ -290,6 +290,7 @@ static int return_editmesh_indexar(int **indexar, float *cent)
        if(totvert==0) return 0;
        
        *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       *tot= totvert;
        nr= 0;
        cent[0]= cent[1]= cent[2]= 0.0;
        
@@ -301,27 +302,57 @@ static int return_editmesh_indexar(int **indexar, float *cent)
                nr++;
        }
        
-       VecMulf(cent, 1.0/(float)totvert);
+       VecMulf(cent, 1.0f/(float)totvert);
        
        return totvert;
 }
 
-static void select_editmesh_hook(ObHook *hook)
+static int return_editmesh_vgroup(char *name, float *cent)
+{
+       EditMesh *em = G.editMesh;
+       EditVert *eve;
+       int i, totvert=0;
+       
+       cent[0]= cent[1]= cent[2]= 0.0;
+       
+       if (G.obedit->actdef) {
+               
+               /* find the vertices */
+               for(eve= em->verts.first; eve; eve= eve->next) {
+                       for (i=0; i<eve->totweight; i++){
+                               if(eve->dw[i].def_nr == (G.obedit->actdef-1)) {
+                                       totvert++;
+                                       VecAddf(cent, cent, eve->co);
+                               }
+                       }
+               }
+               if(totvert) {
+                       bDeformGroup *defGroup = BLI_findlink(&G.obedit->defbase, G.obedit->actdef-1);
+                       strcpy(name, defGroup->name);
+                       VecMulf(cent, 1.0f/(float)totvert);
+                       return 1;
+               }
+       }
+       
+       return 0;
+}      
+
+static void select_editmesh_hook(HookModifierData *hmd)
 {
        EditMesh *em = G.editMesh;
        EditVert *eve;
        int index=0, nr=0;
        
        for(eve= em->verts.first; eve; eve= eve->next, nr++) {
-               if(nr==hook->indexar[index]) {
+               if(nr==hmd->indexar[index]) {
                        eve->f |= SELECT;
-                       if(index < hook->totindex-1) index++;
+                       if(index < hmd->totindex-1) index++;
                }
        }
        EM_select_flush();
 }
 
-static int return_editlattice_indexar(int **indexar, float *cent)
+static int return_editlattice_indexar(int *tot, int **indexar, float *cent)
 {
        BPoint *bp;
        int *index, nr, totvert=0, a;
@@ -339,6 +370,7 @@ static int return_editlattice_indexar(int **indexar, float *cent)
        if(totvert==0) return 0;
        
        *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       *tot= totvert;
        nr= 0;
        cent[0]= cent[1]= cent[2]= 0.0;
        
@@ -355,12 +387,12 @@ static int return_editlattice_indexar(int **indexar, float *cent)
                nr++;
        }
        
-       VecMulf(cent, 1.0/(float)totvert);
+       VecMulf(cent, 1.0f/(float)totvert);
        
        return totvert;
 }
 
-static void select_editlattice_hook(ObHook *hook)
+static void select_editlattice_hook(HookModifierData *hmd)
 {
        BPoint *bp;
        int index=0, nr=0, a;
@@ -369,16 +401,16 @@ static void select_editlattice_hook(ObHook *hook)
        a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
        bp= editLatt->def;
        while(a--) {
-               if(hook->indexar[index]==nr) {
+               if(hmd->indexar[index]==nr) {
                        bp->f1 |= SELECT;
-                       if(index < hook->totindex-1) index++;
+                       if(index < hmd->totindex-1) index++;
                }
                nr++;
                bp++;
        }
 }
 
-static int return_editcurve_indexar(int **indexar, float *cent)
+static int return_editcurve_indexar(int *tot, int **indexar, float *cent)
 {
        extern ListBase editNurb;
        Nurb *nu;
@@ -409,6 +441,7 @@ static int return_editcurve_indexar(int **indexar, float *cent)
        if(totvert==0) return 0;
        
        *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       *tot= totvert;
        nr= 0;
        cent[0]= cent[1]= cent[2]= 0.0;
        
@@ -449,12 +482,12 @@ static int return_editcurve_indexar(int **indexar, float *cent)
                }
        }
        
-       VecMulf(cent, 1.0/(float)totvert);
+       VecMulf(cent, 1.0f/(float)totvert);
        
        return totvert;
 }
 
-static void select_editcurve_hook(ObHook *hook)
+static void select_editcurve_hook(HookModifierData *hmd)
 {
        extern ListBase editNurb;
        Nurb *nu;
@@ -467,19 +500,19 @@ static void select_editcurve_hook(ObHook *hook)
                        bezt= nu->bezt;
                        a= nu->pntsu;
                        while(a--) {
-                               if(nr == hook->indexar[index]) {
+                               if(nr == hmd->indexar[index]) {
                                        bezt->f1 |= SELECT;
-                                       if(index<hook->totindex-1) index++;
+                                       if(index<hmd->totindex-1) index++;
                                }
                                nr++;
-                               if(nr == hook->indexar[index]) {
+                               if(nr == hmd->indexar[index]) {
                                        bezt->f2 |= SELECT;
-                                       if(index<hook->totindex-1) index++;
+                                       if(index<hmd->totindex-1) index++;
                                }
                                nr++;
-                               if(nr == hook->indexar[index]) {
+                               if(nr == hmd->indexar[index]) {
                                        bezt->f3 |= SELECT;
-                                       if(index<hook->totindex-1) index++;
+                                       if(index<hmd->totindex-1) index++;
                                }
                                nr++;
 
@@ -490,9 +523,9 @@ static void select_editcurve_hook(ObHook *hook)
                        bp= nu->bp;
                        a= nu->pntsu*nu->pntsv;
                        while(a--) {
-                               if(nr == hook->indexar[index]) {
+                               if(nr == hmd->indexar[index]) {
                                        bp->f1 |= SELECT;
-                                       if(index<hook->totindex-1) index++;
+                                       if(index<hmd->totindex-1) index++;
                                }
                                nr++;
                                bp++;
@@ -501,17 +534,46 @@ static void select_editcurve_hook(ObHook *hook)
        }
 }
 
+void hook_select(HookModifierData *hmd) 
+{
+       if(G.obedit->type==OB_MESH) select_editmesh_hook(hmd);
+       else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hmd);
+       else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hmd);
+       else if(G.obedit->type==OB_SURF) select_editcurve_hook(hmd);
+}
+
+int hook_getIndexArray(int *tot, int **indexar, char *name, float *cent_r)
+{
+       *indexar= NULL;
+       *tot= 0;
+       name[0]= 0;
+
+       switch(G.obedit->type) {
+       case OB_MESH:
+               /* check selected vertices first */
+               if( return_editmesh_indexar(tot, indexar, cent_r)) return 1;
+               else return return_editmesh_vgroup(name, cent_r);
+       case OB_CURVE:
+       case OB_SURF:
+               return return_editcurve_indexar(tot, indexar, cent_r);
+       case OB_LATTICE:
+               return return_editlattice_indexar(tot, indexar, cent_r);
+       default:
+               return 0;
+       }
+}
+
 void add_hook(void)
 {
+       ModifierData *md = NULL;
+       HookModifierData *hmd = NULL;
        Object *ob=NULL;
-       ObHook *hook=NULL;
-       float cent[3];
-       int tot=0, *indexar, mode;
+       int mode;
 
        if(G.obedit==NULL) return;
        
-       if(G.obedit->hooks.first)
-               mode= pupmenu("Hooks %t|Add Hook, To New Empty %x1|Add Hook, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
+       if(modifiers_findByType(G.obedit, eModifierType_Hook))
+               mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
        else
                mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
 
@@ -540,7 +602,10 @@ void add_hook(void)
                char *cp;
                
                // make pupmenu with hooks
-               for(hook= G.obedit->hooks.first; hook; hook= hook->next) maxlen+=32;
+               for(md=G.obedit->modifiers.first; md; md= md->next) {
+                       if (md->type==eModifierType_Hook) 
+                               maxlen+=32;
+               }
                
                if(maxlen==0) {
                        error("Object has no hooks yet");
@@ -553,9 +618,11 @@ void add_hook(void)
                else if(mode==5) strcpy(cp, "Select %t|");
                else if(mode==6) strcpy(cp, "Clear Offset %t|");
                
-               for(hook= G.obedit->hooks.first; hook; hook= hook->next) {
-                       strcat(cp, hook->name);
-                       strcat(cp, " |");
+               for(md=G.obedit->modifiers.first; md; md= md->next) {
+                       if (md->type==eModifierType_Hook) {
+                               strcat(cp, md->name);
+                               strcat(cp, " |");
+                       }
                }
        
                nr= pupmenu(cp);
@@ -564,37 +631,39 @@ void add_hook(void)
                if(nr<1) return;
                
                a= 1;
-               for(hook= G.obedit->hooks.first; hook; hook= hook->next, a++) {
-                       if(a==nr) break;
+               for(md=G.obedit->modifiers.first; md; md=md->next) {
+                       if (md->type==eModifierType_Hook) {
+                               if(a==nr) break;
+                               a++;
+                       }
                }
-               ob= hook->parent;
+
+               hmd = (HookModifierData*) md;
+               ob= hmd->object;
        }
 
        /* do it, new hooks or reassign */
        if(mode==1 || mode==2 || mode==4) {
-       
-               switch(G.obedit->type) {
-               case OB_MESH:
-                       tot= return_editmesh_indexar(&indexar, cent);
-                       break;
-               case OB_CURVE:
-               case OB_SURF:
-                       tot= return_editcurve_indexar(&indexar, cent);
-                       break;
-               case OB_LATTICE:
-                       tot= return_editlattice_indexar(&indexar, cent);
-                       break;
-               }
+               float cent[3];
+               int tot, ok, *indexar;
+               char name[32];
                
-               if(tot==0) {
-                       error("Requires selected vertices");
+               ok = hook_getIndexArray(&tot, &indexar, name, cent);
+
+               if(ok==0) {
+                       error("Requires selected vertices or active Vertex Group");
                }
                else {
                        
                        if(mode==1) {
-                               Base *base= BASACT;
+                               Base *base= BASACT, *newbase;
 
                                ob= add_object(OB_EMPTY);
+                               /* set layers OK */
+                               newbase= BASACT;
+                               newbase->lay= base->lay;
+                               ob->lay= newbase->lay;
+                               
                                /* transform cent to global coords for loc */
                                VecMat4MulVecfl(ob->loc, G.obedit->obmat, cent);
                                
@@ -605,17 +674,23 @@ void add_hook(void)
                                                                        
                        /* new hook */
                        if(mode==1 || mode==2) {
-                               hook= MEM_callocN(sizeof(ObHook), "new hook");
-                               BLI_addtail(&G.obedit->hooks, hook);
-                               strncpy(hook->name, ob->id.name+2, 30);
-                               hook->force= 1.0;
+                               ModifierData *md = G.obedit->modifiers.first;
+
+                               while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
+                                       md = md->next;
+                               }
+
+                               hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
+                               BLI_insertlinkbefore(&G.obedit->modifiers, md, hmd);
+                               sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
                        }
-                       else MEM_freeN(hook->indexar); // reassign, hook was set
+                       else if (hmd->indexar) MEM_freeN(hmd->indexar); // reassign, hook was set
 
-                       hook->parent= ob;
-                       hook->indexar= indexar;
-                       VECCOPY(hook->cent, cent);
-                       hook->totindex= tot;
+                       hmd->object= ob;
+                       hmd->indexar= indexar;
+                       VECCOPY(hmd->cent, cent);
+                       hmd->totindex= tot;
+                       BLI_strncpy(hmd->name, name, 32);
                        
                        if(mode==1 || mode==2) {
                                /* matrix calculus */
@@ -626,33 +701,31 @@ void add_hook(void)
                
                                Mat4Invert(ob->imat, ob->obmat);
                                /* apparently this call goes from right to left... */
-                               Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
+                               Mat4MulSerie(hmd->parentinv, ob->imat, G.obedit->obmat, NULL, 
                                                        NULL, NULL, NULL, NULL, NULL);
                        }
                }
        }
        else if(mode==3) { // remove
-               BLI_remlink(&G.obedit->hooks, hook);
-               MEM_freeN(hook->indexar);
-               MEM_freeN(hook);
+               BLI_remlink(&G.obedit->modifiers, md);
+               modifier_free(md);
        }
        else if(mode==5) { // select
-               if(G.obedit->type==OB_MESH) select_editmesh_hook(hook);
-               else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hook);
-               else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hook);
-               else if(G.obedit->type==OB_SURF) select_editcurve_hook(hook);
+               hook_select(hmd);
        }
        else if(mode==6) { // clear offset
                where_is_object(ob);    // ob is hook->parent
 
                Mat4Invert(ob->imat, ob->obmat);
                /* this call goes from right to left... */
-               Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
+               Mat4MulSerie(hmd->parentinv, ob->imat, G.obedit->obmat, NULL, 
                                        NULL, NULL, NULL, NULL, NULL);
        }
 
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWBUTSOBJECT, 0);
+       DAG_scene_sort(G.scene);
+       
        BIF_undo_push("Add hook");
 }
 
@@ -684,7 +757,8 @@ void make_track(void)
 
                                        data = con->data;
                                        data->tar = BASACT->object;
-
+                                       base->object->recalc |= OB_RECALC;
+                                       
                                        /* Lamp and Camera track differently by default */
                                        if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
                                                data->reserved1 = TRACK_nZ;
@@ -697,9 +771,6 @@ void make_track(void)
                        base= base->next;
                }
 
-               test_scene_constraints();
-               allqueue(REDRAWVIEW3D, 0);
-               sort_baselist(G.scene);
        }
        else if (mode == 2){
                bConstraint *con;
@@ -714,7 +785,8 @@ void make_track(void)
 
                                        data = con->data;
                                        data->tar = BASACT->object;
-
+                                       base->object->recalc |= OB_RECALC;
+                                       
                                        /* Lamp and Camera track differently by default */
                                        if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
                                                data->trackflag = TRACK_nZ;
@@ -727,27 +799,24 @@ void make_track(void)
                        base= base->next;
                }
 
-               test_scene_constraints();
-               allqueue(REDRAWVIEW3D, 0);
-               sort_baselist(G.scene);
        }
        else if (mode == 3){
                base= FIRSTBASE;
                while(base) {
                        if TESTBASELIB(base) {
                                if(base!=BASACT) {
-
                                        base->object->track= BASACT->object;
+                                       base->object->recalc |= OB_RECALC;
                                }
                        }
                        base= base->next;
                }
-
-               test_scene_constraints();
-               allqueue(REDRAWVIEW3D, 0);
-               allqueue(REDRAWOOPS, 0);
-               sort_baselist(G.scene);
        }
+
+       allqueue(REDRAWOOPS, 0);
+       allqueue(REDRAWVIEW3D, 0);
+       DAG_scene_sort(G.scene);
+       
        BIF_undo_push("Make Track");
 }
 
@@ -796,32 +865,27 @@ void clear_parent(void)
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
-                       par= 0;
+                       par= NULL;
                        if(mode==1 || mode==2) {
-                               if(base->object->type==OB_IKA) {
-                                       Ika *ika= base->object->data;
-                                       ika->parent= 0;
-                               }
                                par= base->object->parent;
-                               base->object->parent= 0;
-                       
+                               base->object->parent= NULL;
+                               base->object->recalc |= OB_RECALC;
+                               
                                if(mode==2) {
-                                       base->object->track= 0;
+                                       base->object->track= NULL;
                                        apply_obmat(base->object);
                                }
                        }
                        else if(mode==3) {
                                Mat4One(base->object->parentinv);
-                       }
-                       
-                       if(par) {
-                               makeDispList(base->object);     // just always..., checks are not available well (ton)
+                               base->object->recalc |= OB_RECALC;
                        }
                }
                base= base->next;
        }
 
-       test_scene_constraints();
+       DAG_scene_sort(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        
@@ -843,15 +907,17 @@ void clear_track(void)
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
-                       base->object->track= 0;
-
+                       base->object->track= NULL;
+                       base->object->recalc |= OB_RECALC;
+                       
                        if(mode==2) {
                                apply_obmat(base->object);
                        }                       
                }
                base= base->next;
        }
-       test_scene_constraints();
+
+       DAG_scene_sort(G.scene);
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        
@@ -874,67 +940,55 @@ void clear_object(char mode)
        else if(mode=='o') str= "Clear origin";
        else return;
        
-       if (G.obpose){
-
-               switch (G.obpose->type){
-               case OB_ARMATURE:
-                       clear_armature (G.obpose, mode);
-#if 1
-                       clear_pose_constraint_status(G.obpose);
-                       make_displists_by_armature (G.obpose);
-#endif
-                       break;
-               }
-
-               allqueue(REDRAWVIEW3D, 0);
-               BIF_undo_push(str);
-               return;
-       }
-
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
                        ob= base->object;
                        
-                       if(mode=='r') {
-                               memset(ob->rot, 0, 3*sizeof(float));
-                               memset(ob->drot, 0, 3*sizeof(float));
-                               QuatOne(ob->quat);
-                               QuatOne(ob->dquat);
-                       }
-                       else if(mode=='g') {
-                               memset(ob->loc, 0, 3*sizeof(float));
-                               memset(ob->dloc, 0, 3*sizeof(float));
+                       if(ob->flag & OB_POSEMODE) {
+                               // no test if we got armature; could be in future...
+                               clear_armature(ob, mode);
                        }
-                       else if(mode=='s') {
-                               memset(ob->dsize, 0, 3*sizeof(float));
-                               ob->size[0]= 1.0;
-                               ob->size[1]= 1.0;
-                               ob->size[2]= 1.0;
-                       }
-                       else if(mode=='o') {
-                               if(ob->parent) {
-                                       v1= ob->loc;
-                                       v3= ob->parentinv[3];
-                                       
-                                       Mat3CpyMat4(mat, ob->parentinv);
-                                       VECCOPY(v3, v1);
-                                       v3[0]= -v3[0];
-                                       v3[1]= -v3[1];
-                                       v3[2]= -v3[2];
-                                       Mat3MulVecfl(mat, v3);
+                       else if((G.f & G_WEIGHTPAINT)==0) {
+                               
+                               if(mode=='r') {
+                                       memset(ob->rot, 0, 3*sizeof(float));
+                                       memset(ob->drot, 0, 3*sizeof(float));
+                                       QuatOne(ob->quat);
+                                       QuatOne(ob->dquat);
                                }
-                       }
-                       
-                       if(ob->parent && ob->partype==PARSKEL)
-                               freedisplist(&ob->disp);
-                       else if(ob->hooks.first)
-                               freedisplist(&ob->disp);
+                               else if(mode=='g') {
+                                       memset(ob->loc, 0, 3*sizeof(float));
+                                       memset(ob->dloc, 0, 3*sizeof(float));
+                               }
+                               else if(mode=='s') {
+                                       memset(ob->dsize, 0, 3*sizeof(float));
+                                       ob->size[0]= 1.0;
+                                       ob->size[1]= 1.0;
+                                       ob->size[2]= 1.0;
+                               }
+                               else if(mode=='o') {
+                                       if(ob->parent) {
+                                               v1= ob->loc;
+                                               v3= ob->parentinv[3];
+                                               
+                                               Mat3CpyMat4(mat, ob->parentinv);
+                                               VECCOPY(v3, v1);
+                                               v3[0]= -v3[0];
+                                               v3[1]= -v3[1];
+                                               v3[2]= -v3[2];
+                                               Mat3MulVecfl(mat, v3);
+                                       }
+                               }
+                               
+                               ob->recalc |= OB_RECALC_OB;
+                       }                       
                }
                base= base->next;
        }
        
        allqueue(REDRAWVIEW3D, 0);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        BIF_undo_push(str);
 }
 
@@ -1046,7 +1100,9 @@ void make_vertex_parent(void)
        while(base) {
                if TESTBASELIB(base) {
                        if(base!=BASACT) {
+                               
                                ob= base->object;
+                               ob->recalc |= OB_RECALC;
                                par= BASACT->object->parent;
                                
                                while(par) {
@@ -1085,6 +1141,7 @@ void make_vertex_parent(void)
        }
        allqueue(REDRAWVIEW3D, 0);
        
+       DAG_scene_sort(G.scene);
        // BIF_undo_push(str); not, conflicts with editmode undo...
 }
 
@@ -1095,25 +1152,39 @@ int test_parent_loop(Object *par, Object *ob)
        if(par==0) return 0;
        if(ob == par) return 1;
        
-       if(par->type==OB_IKA) {
-               Ika *ika= par->data;
-               
-               if( ob == ika->parent ) return 1;
-               if( test_parent_loop(ika->parent, ob) ) return 1;
-       }
-
        return test_parent_loop(par->parent, ob);
 
 }
 
+static char *make_bone_menu (Object *ob)
+{
+       char *menustr=NULL;
+       bPoseChannel *pchan;
+       int             size;
+       int             index=0;
+       
+       //      Count the bones
+       for(size=0, pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, size++);
+       
+       size = size*48 + 256;
+       menustr = MEM_callocN(size, "bonemenu");
+       
+       sprintf (menustr, "Select Bone%%t");
+       
+       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, index++) {
+               sprintf (menustr, "%s|%s%%x%d", menustr, pchan->bone->name, index);
+       }
+       
+       return menustr;
+}
+
+
 void make_parent(void)
 {
        Base *base;
        Object *par;
-       short qual, mode=0, limbnr=0, effchild=0;
-       char *bonestr=NULL;
        Bone    *bone=NULL;
-       int     bonenr;
+       short qual, mode=0;
 
        if(G.scene->id.lib) return;
        if(G.obedit) {
@@ -1126,21 +1197,43 @@ void make_parent(void)
        qual= G.qual;
        par= BASACT->object;
 
-       if(par->type == OB_CURVE){
+       if(par->type == OB_LATTICE){
+               mode= pupmenu("Make Parent %t|Normal Parent %x1|Lattice Deform %x2");
+               if(mode<=0){
+                       return;
+               }
+               else if(mode==1) {
+                       mode= PAROBJECT;
+               }
+               else if(mode==2) {
+                       mode= PARSKEL;
+               }
+       }
+       else if(par->type == OB_CURVE){
                bConstraint *con;
                bFollowPathConstraint *data;
 
-               mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3");
+               mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3|Path Constraint %x4");
                if(mode<=0){
                        return;
                }
                else if(mode==1) {
                        mode= PAROBJECT;
                }
+               else if(mode==2) {
+                       Curve *cu= par->data;
+                       
+                       mode= PAROBJECT;
+                       if((cu->flag & CU_PATH)==0) {
+                               cu->flag |= CU_PATH|CU_FOLLOW;
+                               makeDispListCurveTypes(par, 0);  // force creation of path data
+                       }
+                       else cu->flag |= CU_FOLLOW;
+               }
                else if(mode==3) {
                        mode= PARSKEL;
                }
-               else if(mode==2) {
+               else if(mode==4) {
 
                        base= FIRSTBASE;
                        while(base) {
@@ -1167,67 +1260,65 @@ void make_parent(void)
                                base= base->next;
                        }
 
-                       test_scene_constraints();
                        allqueue(REDRAWVIEW3D, 0);
-                       sort_baselist(G.scene);
+                       DAG_scene_sort(G.scene);
                        BIF_undo_push("make Parent");
                        return;
                }
        }
        else if(par->type == OB_ARMATURE){
-
-                       base= FIRSTBASE;
-                       while(base) {
-                               if TESTBASELIB(base) {
-                                       if(base!=BASACT) {
-                                               if(base->object->type==OB_MESH) {
-                                                       mode= pupmenu("Make Parent To%t|Bone %x1|Armature %x2|Object %x3");
-                                                       break;
-                                               }
-                                               else {
-                                                       mode= pupmenu("Make Parent To %t|Bone %x1|Object %x3");
-                                                       break;
-                                               }
+               int     bonenr;
+               char *bonestr=NULL;
+               
+               base= FIRSTBASE;
+               while(base) {
+                       if TESTBASELIB(base) {
+                               if(base!=BASACT) {
+                                       if(base->object->type==OB_MESH) {
+                                               mode= pupmenu("Make Parent To%t|Bone %x1|Armature %x2|Object %x3");
+                                               break;
+                                       }
+                                       else {
+                                               mode= pupmenu("Make Parent To %t|Bone %x1|Object %x3");
+                                               break;
                                        }
                                }
-                               base= base->next;
                        }
-               
-                       switch (mode){
-                       case 1:
-                               mode=PARBONE;
-                               /* Make bone popup menu */
-
-                               bonestr = make_bone_menu(get_armature(par));
-               //              if(mbutton(&bone, bonestr, 1, 24, "Bone: ")==0) {
+                       base= base->next;
+               }
+       
+               switch (mode){
+               case 1:
+                       mode=PARBONE;
+                       /* Make bone popup menu */
 
-                               bonenr= pupmenu_col(bonestr, 20);
-                               if (bonestr)
-                                       MEM_freeN (bonestr);
-                               
-                               if (bonenr==-1){
-                                       allqueue(REDRAWVIEW3D, 0);
-                                       return;
-                               }
+                       bonestr = make_bone_menu(par);
 
-                               apply_pose_armature(get_armature(par), par->pose, 0);
-                               bone=get_indexed_bone(get_armature(par), bonenr); 
-                               if (!bone){
-               //                      error ("Invalid bone!");
-                                       allqueue(REDRAWVIEW3D, 0);
-                                       return;
-                               }
+                       bonenr= pupmenu_col(bonestr, 20);
+                       if (bonestr)
+                               MEM_freeN (bonestr);
+                       
+                       if (bonenr==-1){
+                               allqueue(REDRAWVIEW3D, 0);
+                               return;
+                       }
 
-                               break;
-                       case 2:
-                               mode=PARSKEL;
-                               break;
-                       case 3:
-                               mode=PAROBJECT;
-                               break;
-                       default:
+                       bone= get_indexed_bone(par, bonenr<<16);                // function uses selection codes
+                       if (!bone){
+                               allqueue(REDRAWVIEW3D, 0);
                                return;
                        }
+
+                       break;
+               case 2:
+                       mode=PARSKEL;
+                       break;
+               case 3:
+                       mode=PAROBJECT;
+                       break;
+               default:
+                       return;
+               }
        }
        else {
                if(qual & LR_SHIFTKEY) {
@@ -1239,31 +1330,13 @@ void make_parent(void)
                        }
                        else if(okee("Make parent")==0) return;
 
-                       /* test effchild */
-                       base= FIRSTBASE;
-                       while(base) {
-                               if TESTBASELIB(base) {
-                                       if(base->object->type==OB_IKA && base->object != par) {
-                                               if(effchild==0) {
-                                                       if(okee("Effector as Child")) effchild= 1;
-                                                       else effchild= 2;
-                                               }
-                                       }
-                               }
-                               if(effchild) break;
-                               base= base->next;
-                       }
-                       
                        /* now we'll clearparentandkeeptransform all objects */
                        base= FIRSTBASE;
                        while(base) {
                                if TESTBASELIB(base) {
                                        if(base!=BASACT && base->object->parent) {
-                                               if(base->object->type==OB_IKA && effchild==1);
-                                               else {
-                                                       base->object->parent= 0;
-                                                       apply_obmat(base->object);
-                                               }
+                                               base->object->parent= NULL;
+                                               apply_obmat(base->object);
                                        }
                                }
                                base= base->next;
@@ -1271,6 +1344,7 @@ void make_parent(void)
                }
        }
        
+       par->recalc |= OB_RECALC_OB;
        
        base= FIRSTBASE;
        while(base) {
@@ -1282,13 +1356,11 @@ void make_parent(void)
                                }
                                else {
                                        
+                                       base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+                                       
                                        /* the ifs below are horrible code (ton) */
                                        
-                                       if(par->type==OB_IKA){
-                                               base->object->partype= mode;
-                                               base->object->par1= limbnr;
-                                       }
-                                       else if (par->type==OB_ARMATURE){
+                                       if (par->type==OB_ARMATURE) {
                                                base->object->partype= mode;
                                                if (bone)
                                                        strcpy (base->object->parsubstr, bone->name);
@@ -1299,13 +1371,14 @@ void make_parent(void)
                                                if(qual & LR_ALTKEY) {
                                                        base->object->partype= PARVERT1;
                                                }
-                                               else if(par->type==OB_CURVE) {
+                                               else if(ELEM(par->type, OB_CURVE, OB_LATTICE)) {
                                                        base->object->partype= mode;
                                                }
                                                else {
                                                        base->object->partype= PAROBJECT;
                                                }
                                        }
+                                       
                                        base->object->parent= par;
                                        
                                        /* calculate inverse parent matrix? */
@@ -1333,11 +1406,8 @@ void make_parent(void)
                                                Mat4Invert(base->object->parentinv, workob.obmat);
                                        }
                                        
-                                       if(par->type==OB_LATTICE) makeDispList(base->object);
-                                       if(par->type==OB_CURVE && mode==PARSKEL) makeDispList(base->object);
                                        if(par->type==OB_ARMATURE && mode == PARSKEL){
                                                verify_defgroups(base->object);
-                                               makeDispList(base->object);
                                        }
                                }
                        }
@@ -1347,9 +1417,9 @@ void make_parent(void)
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        
-       test_scene_constraints();
-       sort_baselist(G.scene);
-
+       DAG_scene_sort(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
+       
        BIF_undo_push("make Parent");
 }
 
@@ -1358,7 +1428,6 @@ void enter_editmode(void)
 {
        Base *base;
        Object *ob;
-       Ika *ika;
        ID *id;
        Mesh *me;
        int ok= 0;
@@ -1369,6 +1438,8 @@ void enter_editmode(void)
        if(base==0) return;
        if((G.vd==NULL || (base->lay & G.vd->lay))==0) return;
        
+       strcpy(G.editModeTitleExtra, "");
+
        ob= base->object;
        if(ob->data==0) return;
        
@@ -1403,20 +1474,6 @@ void enter_editmode(void)
                make_editArmature();
                allqueue (REDRAWVIEW3D,0);
        }
-       else if(ob->type==OB_IKA) {     /* grab type */
-               base= FIRSTBASE;
-               while(base) {
-                       if TESTBASE(base) {
-                               if(base->object->type==OB_IKA) {
-                                       ika= base->object->data;
-                                       if(ika->flag & IK_GRABEFF) ika->flag &= ~IK_GRABEFF;
-                                       else ika->flag |= IK_GRABEFF;
-                               }
-                       }
-                       base= base->next;
-               }
-               allqueue(REDRAWVIEW3D, 0);
-       }
        else if(ob->type==OB_FONT) {
                G.obedit= ob;
                ok= 1;
@@ -1445,27 +1502,17 @@ void enter_editmode(void)
                setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
        
                allqueue(REDRAWVIEW3D, 1);
+               DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+               
        }
-       else G.obedit= 0;
+       else G.obedit= NULL;
 
-       if (G.obpose)
-               exit_posemode (1);
        scrarea_queue_headredraw(curarea);
 }
 
-void make_displists_by_parent(Object *ob) {
-       Base *base;
-       
-       for (base= FIRSTBASE; base; base= base->next)
-               if (ob==base->object->parent)
-                       makeDispList(base->object);
-}
-
 void exit_editmode(int freedata)       /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
 {
-       Base *base;
        Object *ob;
-       Curve *cu;
 
        if(G.obedit==NULL) return;
 
@@ -1478,7 +1525,7 @@ void exit_editmode(int freedata)  /* freedata==0 at render, 1= freedata, 2= do un
                        error("Too many vertices");
                        return;
                }
-               load_editMesh();        /* makes new displist */
+               load_editMesh();
 
                if(freedata) free_editMesh(G.editMesh);
 
@@ -1486,8 +1533,6 @@ void exit_editmode(int freedata)  /* freedata==0 at render, 1= freedata, 2= do un
                        set_seamtface();
                        allqueue(REDRAWIMAGE, 0);
                }
-
-               build_particle_system(G.obedit);
        }
        else if (G.obedit->type==OB_ARMATURE){  
                load_editArmature();
@@ -1513,45 +1558,18 @@ void exit_editmode(int freedata)        /* freedata==0 at render, 1= freedata, 2= do un
 
        ob= G.obedit;
        
-       /* displist make is different in editmode */
+       /* for example; displist make is different in editmode */
        if(freedata) G.obedit= NULL;
 
        /* total remake of softbody data */
-       if(ob->softflag & OB_SB_ENABLE) {
-               SoftBody *sb= ob->soft;
-               
-               if(sb->keys) {
-                       if( okee("Erase Baked SoftBody") )
-                               sbObjectToSoftbody(ob);
+       if(modifiers_isSoftbodyEnabled(ob)) {
+               if (ob->soft && ob->soft->keys) {
+                       notice("Erased Baked SoftBody");
                }
-               else sbObjectToSoftbody(ob);
-       }
-       makeDispList(ob);
-
-       /* has this influence at other objects? */
-       if(ob->type==OB_CURVE) {
 
-               /* test if ob is use as bevelcurve r textoncurve */
-               base= FIRSTBASE;
-               while(base) {
-                       if ELEM(base->object->type, OB_CURVE, OB_FONT) {
-                               cu= base->object->data;
-                               
-                               if(cu->textoncurve==ob) {
-                                       text_to_curve(base->object, 0);
-                                       makeDispList(base->object);
-                               }
-                               if(cu->bevobj==ob || cu->taperobj==ob) {
-                                       makeDispList(base->object);
-                               }
-                       }
-                       base= base->next;
-               }
-               
-       }
-       else if(ob->type==OB_LATTICE) {
-               make_displists_by_parent(ob);
+               sbObjectToSoftbody(ob);
        }
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
 
        if(freedata) {
                setcursor_space(SPACE_VIEW3D, CURSOR_STD);
@@ -1624,6 +1642,8 @@ void docentre(int centremode)
                        for(eve= em->verts.first; eve; eve= eve->next) {
                                VecSubf(eve->co, eve->co, cent);                        
                        }
+                       
+                       recalc_editnormals();
                }
        }
        
@@ -1718,13 +1738,6 @@ void docentre(int centremode)
                                                        ob= ob->id.next;
                                                }
                                        }
-                               
-                                       /* displist of all users, also this one */
-                                       makeDispList(base->object);
-                                       
-                                       /* DO: check all users... */
-                                       tex_space_mesh(me);
-               
                                }
                                else if ELEM(base->object->type, OB_CURVE, OB_SURF) {
                                                                        
@@ -1789,10 +1802,8 @@ void docentre(int centremode)
                                        }
                        
                                        if(G.obedit) {
-                                               makeDispList(G.obedit);
                                                break;
                                        }
-                                       else makeDispList(base->object);
        
                                }
                                else if(base->object->type==OB_FONT) {
@@ -1807,12 +1818,10 @@ void docentre(int centremode)
                                        /* not really ok, do this better once! */
                                        cu->xof /= cu->fsize;
                                        cu->yof /= cu->fsize;
-                                       
-                                       text_to_curve(base->object, 0);
-                                       makeDispList(base->object);
-                                       
+
                                        allqueue(REDRAWBUTSEDIT, 0);
                                }
+                               DAG_object_flush_update(G.scene, base->object, OB_RECALC_OB|OB_RECALC_DATA);
                        }
                }
                base= base->next;
@@ -1888,18 +1897,48 @@ void movetolayer(void)
        BIF_undo_push("Move to layer");
 }
 
+void split_font()
+{
+       Object *ob = OBACT;
+       Base *oldbase = BASACT;
+       Curve *cu= ob->data;
+       char *p= cu->str;
+       int slen= strlen(p);
+       int i;
+
+       for (i = 0; i<=slen; p++, i++) {
+               adduplicate(1);
+               cu= OBACT->data;
+               cu->sepchar = i+1;
+               text_to_curve(OBACT, 0);        // pass 1: only one letter, adapt position
+               text_to_curve(OBACT, 0);        // pass 2: remake
+               freedisplist(&OBACT->disp);
+               makeDispListCurveTypes(OBACT, 0);
+               
+               OBACT->flag &= ~SELECT;
+               BASACT->flag &= ~SELECT;
+               oldbase->flag |= SELECT;
+               oldbase->object->flag |= SELECT;
+               set_active_base(oldbase);               
+       }
+}
 
 void special_editmenu(void)
 {
-       extern short editbutflag;
-       extern float doublimit;
+       Object *ob= OBACT;
        float fac;
        int nr,ret;
-       short randfac;
+       short randfac,numcuts;
        
-       if(G.obedit==0) {
-               if(G.f & G_FACESELECT) {
-                       Mesh *me= get_mesh(OBACT);
+       if(ob==NULL) return;
+       
+       if(G.obedit==NULL) {
+               
+               if(ob->flag & OB_POSEMODE) {
+                       pose_special_editmenu();
+               }
+               else if(G.f & G_FACESELECT) {
+                       Mesh *me= get_mesh(ob);
                        TFace *tface;
                        int a;
                        
@@ -1935,12 +1974,13 @@ void special_editmenu(void)
                                        }
                                }
                        }
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue(REDRAWVIEW3D, 0);
                        allqueue(REDRAWBUTSEDIT, 0);
                        BIF_undo_push("Change texture face");
                }
                else if(G.f & G_VERTEXPAINT) {
-                       Mesh *me= get_mesh(OBACT);
+                       Mesh *me= get_mesh(ob);
                        
                        if(me==0 || (me->mcol==NULL && me->tface==NULL) ) return;
                        
@@ -1954,18 +1994,31 @@ void special_editmenu(void)
                                
                                if(me->tface) mcol_to_tface(me, 1);
                                BIF_undo_push("Shared VertexCol");
+
+                               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       }
+               }
+               else if(G.f & G_WEIGHTPAINT) {
+                       if(ob->parent && (ob->parent->flag & OB_POSEMODE)) {
+                               nr= pupmenu("Specials%t|Apply Bone Envelopes to VertexGroups %x1");
+                               if(nr==1) {
+                                       Mesh *me= ob->data;
+                                       if(me->dvert) copy_wpaint_undo(me->dvert, me->totvert);
+                                       pose_adds_vgroups(ob);
+                               }
                        }
                }
                else {
                        Base *base, *base_select= NULL;
-
+                       
                        // Get the active object mesh.
-                       Mesh *me= get_mesh(OBACT);
+                       Mesh *me= get_mesh(ob);
 
-                       // If the active object is a mesh...
-                       if (me) {
+                       // Booleans, if the active object is a mesh...
+                       if (me && ob->id.lib==NULL) {
+                               
                                // Bring up a little menu with the boolean operation choices on.
-                               nr= pupmenu("Boolean %t|Intersect%x1|Union%x2|Difference%x3");
+                               nr= pupmenu("Boolean Tools%t|Intersect%x1|Union%x2|Difference%x3|Add Intersect Modifier%x4|Add Union Modifier%x5|Add Difference Modifier%x6");
 
                                if (nr > 0) {
                                        // user has made a choice of a menu element.
@@ -1973,27 +2026,38 @@ void special_editmenu(void)
                                        // we search through the object list to find the other 
                                        // selected item and make sure it is distinct and a mesh.
 
-                                       base= FIRSTBASE;
-                                       while(base) {
-                                               if(base->flag & SELECT) {
-                                                       if(base->object != OBACT) base_select= base;
+                                       for(base= FIRSTBASE; base; base= base->next) {
+                                               if TESTBASELIB(base) {
+                                                       if(base->object != ob) base_select= base;
                                                }
-
-                                               base= base->next;
                                        }
 
                                        if (base_select) {
                                                if (get_mesh(base_select->object)) {
-                                                       waitcursor(1);
-                                                       ret = NewBooleanMesh(BASACT,base_select,nr);
-                                                       if (ret==0) {
-                                                               error("An internal error occurred -- sorry!");
-                                                       } else if(ret==-1) {
-                                                               error("Selected meshes must have faces to perform boolean operations");
-                                                       }
-                                                       else BIF_undo_push("Boolean");
-
-                                                       waitcursor(0);
+                                                       if(nr <= 3){
+                                                               waitcursor(1);
+                                                               ret = NewBooleanMesh(BASACT,base_select,nr);
+                                                               if (ret==0) {
+                                                                       error("An internal error occurred -- sorry!");
+                                                               } else if(ret==-1) {
+                                                                       error("Selected meshes must have faces to perform boolean operations");
+                                                               }
+                                                               else BIF_undo_push("Boolean");
+                                                               waitcursor(0);
+                                                       } else {
+                                                               BooleanModifierData *bmd = NULL;
+                                                               bmd = (BooleanModifierData *)modifier_new(eModifierType_Boolean);
+                                                               BLI_addtail(&ob->modifiers, bmd);
+                                                               bmd->object = base_select->object;
+                                                               bmd->modifier.mode |= eModifierMode_Realtime;
+                                                               switch(nr){
+                                                                       case 4: bmd->operation = eBooleanModifierOp_Intersect; break;
+                                                                       case 5: bmd->operation = eBooleanModifierOp_Union; break;
+                                                                       case 6: bmd->operation = eBooleanModifierOp_Difference; break;
+                                                               }
+                                                               do_common_editbuts(B_CHANGEDEP);
+                                                               BIF_undo_push("Add Boolean modifier");                                                          
+                                                       }                                                               
                                                } else {
                                                        error("Please select 2 meshes");
                                                }
@@ -2004,34 +2068,51 @@ void special_editmenu(void)
 
                                allqueue(REDRAWVIEW3D, 0);
                        }
+                       else if (ob->type == OB_FONT) {
+                               nr= pupmenu("Split %t|Characters%x1");
+                               if (nr > 0) {
+                                       switch(nr) {
+                                               case 1: split_font();
+                                       }
+                               }
+                       }                       
                }
        }
        else if(G.obedit->type==OB_MESH) {
 
-               nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
-               if(nr>0) waitcursor(1);
+               nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Multi Smooth - WIP%x12|Subdivide Smooth Old%x13|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11|Set Smooth %x14|Set Solid %x15");
                
                switch(nr) {
                case 1:
-                       subdivideflag(1, 0.0, editbutflag);
-                       BIF_undo_push("Subdivide");
+                       numcuts = 1;
+                       waitcursor(1);
+                       esubdivideflag(1, 0.0, G.scene->toolsettings->editbutflag,numcuts,0);
+                       
+                       BIF_undo_push("ESubdivide Single");            
                        break;
                case 2:
+               numcuts = 2;
+                       if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+                       waitcursor(1);
+                       esubdivideflag(1, 0.0, G.scene->toolsettings->editbutflag,numcuts,0);
+                       BIF_undo_push("ESubdivide");
+                       break;
+               case 3:
+                       numcuts = 2;
+                       if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+                       waitcursor(1);
                        randfac= 10;
                        if(button(&randfac, 1, 100, "Rand fac:")==0) return;
                        fac= -( (float)randfac )/100;
-                       subdivideflag(1, fac, editbutflag);
+                       esubdivideflag(1, fac, G.scene->toolsettings->editbutflag,numcuts,0);
                        BIF_undo_push("Subdivide Fractal");
                        break;
-               case 3:
-                       subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
-                       BIF_undo_push("Subdivide Smooth");
-                       break;
+
                case 4:
                        mergemenu();
                        break;
                case 5:
-                       notice("Removed %d Vertices", removedoublesflag(1, doublimit));
+                       notice("Removed %d Vertices", removedoublesflag(1, G.scene->toolsettings->doublimit));
                        BIF_undo_push("Remove Doubles");
                        break;
                case 6:
@@ -2053,9 +2134,27 @@ void special_editmenu(void)
                case 11:
                        bevel_menu();
                        break;
-               }               
+               case 12:
+                       numcuts = 2;
+                       if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+                       waitcursor(1);
+                       esubdivideflag(1, 0.0, G.scene->toolsettings->editbutflag | B_SMOOTH,numcuts,0);
+                       BIF_undo_push("Subdivide Smooth");
+                       break;          
+               case 13:
+                       waitcursor(1);
+                       subdivideflag(1, 0.0, G.scene->toolsettings->editbutflag | B_SMOOTH);
+                       BIF_undo_push("Subdivide Smooth");
+                       break;
+               case 14:
+                       mesh_set_smooth_faces(1);
+                       break;
+               case 15: 
+                       mesh_set_smooth_faces(0);
+                       break;
+               }
                
-               makeDispList(G.obedit);
+               DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
                
                if(nr>0) waitcursor(0);
                
@@ -2072,6 +2171,15 @@ void special_editmenu(void)
                        switchdirectionNurb2();
                        break;
                }
+               
+               DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+       }
+       else if(G.obedit->type==OB_ARMATURE) {
+               nr= pupmenu("Specials%t|Subdivide %x1|Flip Left-Right Names%x2");
+               if(nr==1)
+                       subdivide_armature();
+               else if(nr==2)
+                       armature_flip_names();
        }
 
        countall();
@@ -2113,8 +2221,8 @@ void convertmenu(void)
                nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
                if(nr>0) ok= 1;
        }
-       else if(ob->type==OB_MESH && mesh_uses_displist((Mesh*) ob->data)) {
-               nr= pupmenu("Convert SubSurf to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
+       else if(ob->type==OB_MESH) {
+               nr= pupmenu("Convert Modifiers to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
                if(nr>0) ok= 1;
        }
        if(ok==0) return;
@@ -2139,51 +2247,41 @@ void convertmenu(void)
                        if(ob->flag & OB_DONE);
                        else if(ob->type==OB_MESH) {
                                Mesh *oldme= ob->data;
-                               
-                               if (mesh_uses_displist(oldme)) {
-                                       DispListMesh *dlm;
-                                       DerivedMesh *dm;
+                               DispListMesh *dlm;
+                               DerivedMesh *dm;
 
-                                       basedel = base;
+                               basedel = base;
 
-                                       ob->flag |= OB_DONE;
+                               ob->flag |= OB_DONE;
 
-                                       ob1= copy_object(ob);
+                               ob1= copy_object(ob);
+                               ob1->recalc |= OB_RECALC;
+                               object_free_modifiers(ob1);
 
-                                       basen= MEM_mallocN(sizeof(Base), "duplibase");
-                                       *basen= *base;
-                                       BLI_addhead(&G.scene->base, basen);     /* addhead: otherwise eternal loop */
-                                       basen->object= ob1;
-                                       basen->flag &= ~SELECT;
-                                               
-                                       me= ob1->data;
-                                       me->id.us--;
-                                               
-                                       ob1->data= add_mesh();
-                                       G.totmesh++;
-                                       ob1->type= OB_MESH;
-
-                                       me= ob1->data;
-                                       me->totcol= oldme->totcol;
-                                       if(ob1->totcol) {
-                                               me->mat= MEM_dupallocN(oldme->mat);
-                                               for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
-                                       }
+                               basen= MEM_mallocN(sizeof(Base), "duplibase");
+                               *basen= *base;
+                               BLI_addhead(&G.scene->base, basen);     /* addhead: otherwise eternal loop */
+                               basen->object= ob1;
+                               basen->flag &= ~SELECT;
                                        
-                                       dm= subsurf_make_derived_from_mesh(oldme, oldme->subdiv);
-                                       dlm= dm->convertToDispListMesh(dm);
-                                       dm->release(dm);
-
-                                       displistmesh_to_mesh(dlm, ob1->data);
-                                       displistmesh_free(dlm);
-
-                                       /* texspace and normals */
-                                       BASACT= basen;
-                                       enter_editmode();
-                                       exit_editmode(1); // freedata, but no undo
-                                       BASACT= basact;
+                               me= ob1->data;
+                               me->id.us--;
                                        
+                               ob1->data= add_mesh();
+                               G.totmesh++;
+                               ob1->type= OB_MESH;
+
+                               me= ob1->data;
+                               me->totcol= oldme->totcol;
+                               if(ob1->totcol) {
+                                       me->mat= MEM_dupallocN(oldme->mat);
+                                       for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
                                }
+
+                               dm= mesh_create_derived_no_deform(ob, NULL);
+                               dlm= dm->convertToDispListMesh(dm, 0);
+                               displistmesh_to_mesh(dlm, ob1->data);
+                               dm->release(dm);
                        }
                        else if(ob->type==OB_FONT) {
                                if(nr==1) {
@@ -2197,11 +2295,26 @@ void convertmenu(void)
                                                cu->vfont->id.us--;
                                                cu->vfont= 0;
                                        }
+                                       if(cu->vfontb) {
+                                               cu->vfontb->id.us--;
+                                               cu->vfontb= 0;
+                                       }
+                                       if(cu->vfonti) {
+                                               cu->vfonti->id.us--;
+                                               cu->vfonti= 0;
+                                       }
+                                       if(cu->vfontbi) {
+                                               cu->vfontbi->id.us--;
+                                               cu->vfontbi= 0;
+                                       }                                       
                                        /* other users */
                                        if(cu->id.us>1) {
                                                ob1= G.main->object.first;
                                                while(ob1) {
-                                                       if(ob1->data==cu) ob1->type= OB_CURVE;
+                                                       if(ob1->data==cu) {
+                                                               ob1->type= OB_CURVE;
+                                                               ob1->recalc |= OB_RECALC;
+                                                       }
                                                        ob1= ob1->id.next;
                                                }
                                        }
@@ -2214,7 +2327,7 @@ void convertmenu(void)
                                        cu= ob->data;
                                        
                                        dl= cu->disp.first;
-                                       if(dl==0) makeDispList(ob);
+                                       if(dl==0) makeDispListCurveTypes(ob, 0);                // force creation
 
                                        nurbs_to_mesh(ob); /* also does users */
 
@@ -2223,7 +2336,7 @@ void convertmenu(void)
                                        enter_editmode();
                                        exit_editmode(1); // freedata, but no undo
                                        BASACT= basact;
-                               }
+                               }
                        }
                        else if(ob->type==OB_MBALL) {
                        
@@ -2236,6 +2349,7 @@ void convertmenu(void)
                                                ob->flag |= OB_DONE;
 
                                                ob1= copy_object(ob);
+                                               ob1->recalc |= OB_RECALC;
 
                                                basen= MEM_mallocN(sizeof(Base), "duplibase");
                                                *basen= *base;
@@ -2258,7 +2372,6 @@ void convertmenu(void)
                                                }
                                                
                                                mball_to_mesh(&ob->disp, ob1->data);
-                                               tex_space_mesh(me);
                                        }
                                }
                        }
@@ -2268,14 +2381,14 @@ void convertmenu(void)
                        free_and_unlink_base(basedel);  
                basedel = NULL;                         
        }
-       
-       test_scene_constraints();       // always call after delete object
-       
+
        countall();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSEDIT, 0);
        BIF_undo_push("Convert Object");
+
+       DAG_scene_sort(G.scene);
 }
 
        /* Change subdivision properties of mesh object ob, if
@@ -2283,23 +2396,41 @@ void convertmenu(void)
         */
 void flip_subdivison(Object *ob, int level)
 {
-       Mesh *me = ob->data;
+       ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
+
+       if (md) {
+               SubsurfModifierData *smd = (SubsurfModifierData*) md;
 
-       if (level == -1) {
-               me->flag ^= ME_SUBSURF;
+               if (level == -1) {
+                       if (smd->modifier.mode&(eModifierMode_Render|eModifierMode_Realtime)) {
+                               smd->modifier.mode &= ~(eModifierMode_Render|eModifierMode_Realtime);
+                       } else {
+                               smd->modifier.mode |= (eModifierMode_Render|eModifierMode_Realtime);
+                       }
+               } else {
+                       smd->levels = level;
+               }
        } else {
-               me->subdiv = level;
+               SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
+
+               BLI_addtail(&ob->modifiers, smd);
+
+               if (level!=-1) {
+                       smd->levels = level;
+               }
        }
 
+       countall();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSEDIT, 0);
-       makeDispList(ob);
+       allqueue(REDRAWBUTSOBJECT, 0);
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
        
        BIF_undo_push("Switch subsurf on/off");
 }
  
-void copymenu_properties(Object *ob)
+static void copymenu_properties(Object *ob)
 {      
        bProperty *prop, *propn, *propc;
        Base *base;
@@ -2365,7 +2496,7 @@ void copymenu_properties(Object *ob)
        BIF_undo_push("Copy properties");
 }
 
-void copymenu_logicbricks(Object *ob)
+static void copymenu_logicbricks(Object *ob)
 {
        Base *base;
        
@@ -2399,11 +2530,79 @@ void copymenu_logicbricks(Object *ob)
        BIF_undo_push("Copy logic");
 }
 
+static void copymenu_modifiers(Object *ob)
+{
+       char str[512];
+       int i, event;
+       Base *base;
+
+       strcpy(str, "Copy Modifiers %t");
+
+       sprintf(str+strlen(str), "|All%%x%d|%%l", NUM_MODIFIER_TYPES);
+
+       for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
+               ModifierTypeInfo *mti = modifierType_getInfo(i);
+
+               if (ELEM(i, eModifierType_Hook, eModifierType_Softbody)) continue;
+
+               if (    (mti->flags&eModifierTypeFlag_AcceptsCVs) || 
+                               (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
+                       sprintf(str+strlen(str), "|%s%%x%d", mti->name, i);
+               }
+       }
+
+       event = pupmenu(str);
+       if(event<=0) return;
+
+       for (base= FIRSTBASE; base; base= base->next) {
+               if(base->object != ob) {
+                       if(TESTBASELIB(base)) {
+                               ModifierData *md;
+
+                               base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+
+                               if (base->object->type==OB_MESH) {
+                                       if (event==NUM_MODIFIER_TYPES) {
+                                               object_free_modifiers(base->object);
+
+                                               for (md=ob->modifiers.first; md; md=md->next) {
+                                                       if (md->type!=eModifierType_Hook) {
+                                                               ModifierData *nmd = modifier_new(md->type);
+                                                               modifier_copyData(md, nmd);
+                                                               BLI_addtail(&base->object->modifiers, nmd);
+                                                       }
+                                               }
+                                       } else {
+                                               ModifierData *md = modifiers_findByType(ob, event);
+
+                                               if (md) {
+                                                       ModifierData *tmd = modifiers_findByType(base->object, event);
+
+                                                       if (!tmd) {
+                                                               tmd = modifier_new(event);
+                                                               BLI_addtail(&base->object->modifiers, tmd);
+                                                       }
+
+                                                       modifier_copyData(md, tmd);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+                               
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSOBJECT, 0);
+       DAG_scene_sort(G.scene);
+       
+       BIF_undo_push("Copy modifiers");
+}
+
 void copy_attr_menu()
 {
        Object *ob;
        short event;
-       char str[256];
+       char str[512];
 
        /* If you change this menu, don't forget to update the menu in header_view3d.c
         * view3d_edit_object_copyattrmenu() and in toolbox.c
@@ -2420,6 +2619,10 @@ void copy_attr_menu()
        
        if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
        if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19");
+       
+       if((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
+                       strcat(str, "|Curve Resolution%x25");
+       }
 
        if(ob->type==OB_MESH){
                strcat(str, "|Subdiv%x21");
@@ -2429,6 +2632,10 @@ void copy_attr_menu()
 
        if(ob->soft) strcat(str, "|Soft Body Settings%x23");
        
+       if(ob->type==OB_MESH){
+               strcat(str, "|Modifiers ...%x24");
+       }
+
        event= pupmenu(str);
        if(event<= 0) return;
        
@@ -2440,6 +2647,7 @@ void copy_attr(short event)
        Object *ob, *obt;
        Base *base;
        Curve *cu, *cu1;
+       Nurb *nu;
        void *poin1, *poin2=0;
        
        if(G.scene->id.lib) return;
@@ -2465,11 +2673,16 @@ void copy_attr(short event)
                copymenu_logicbricks(ob);
                return;
        }
+       else if(event==24) {
+               copymenu_modifiers(ob);
+               return;
+       }
 
        base= FIRSTBASE;
        while(base) {
                if(base != BASACT) {
                        if(TESTBASELIB(base)) {
+                               base->object->recalc |= OB_RECALC_OB;
                                
                                if(event==1) {  /* loc */
                                        VECCOPY(base->object->loc, ob->loc);
@@ -2488,7 +2701,7 @@ void copy_attr(short event)
                                else if(event==4) {  /* drawtype */
                                        base->object->dt= ob->dt;
                                        base->object->dtx= ob->dtx;
-                                       }
+                               }
                                else if(event==5) {  /* time offs */
                                        base->object->sf= ob->sf;
                                }
@@ -2518,7 +2731,7 @@ void copy_attr(short event)
                                        if(poin1) {
                                                memcpy(poin1, poin2, 4+12+12+12);
                                        
-                                               if(obt->type==OB_MESH) tex_space_mesh(obt->data);
+                                               if(obt->type==OB_MESH) ;
                                                else if(obt->type==OB_MBALL) tex_space_mball(obt);
                                                else tex_space_curve(obt->data);
                                        }
@@ -2540,11 +2753,22 @@ void copy_attr(short event)
                                                if(cu1->vfont) cu1->vfont->id.us--;
                                                cu1->vfont= cu->vfont;
                                                id_us_plus((ID *)cu1->vfont);
-                                               text_to_curve(base->object, 0);
+                                               if(cu1->vfontb) cu1->vfontb->id.us--;
+                                               cu1->vfontb= cu->vfontb;
+                                               id_us_plus((ID *)cu1->vfontb);
+                                               if(cu1->vfonti) cu1->vfonti->id.us--;
+                                               cu1->vfonti= cu->vfonti;
+                                               id_us_plus((ID *)cu1->vfonti);
+                                               if(cu1->vfontbi) cu1->vfontbi->id.us--;
+                                               cu1->vfontbi= cu->vfontbi;
+                                               id_us_plus((ID *)cu1->vfontbi);                                         
+
+                                               text_to_curve(base->object, 0);         // needed?
+
                                                
                                                strcpy(cu1->family, cu->family);
                                                
-                                               makeDispList(base->object);
+                                               base->object->recalc |= OB_RECALC_DATA;
                                        }
                                }
                                else if(event==19) {    /* bevel settings */
@@ -2560,7 +2784,25 @@ void copy_attr(short event)
                                                cu1->ext1= cu->ext1;
                                                cu1->ext2= cu->ext2;
                                                
-                                               makeDispList(base->object);
+                                               base->object->recalc |= OB_RECALC_DATA;
+                                       }
+                               }
+                               else if(event==25) {    /* curve resolution */
+
+                                       if ELEM(base->object->type, OB_CURVE, OB_FONT) {
+                                               cu= ob->data;
+                                               cu1= base->object->data;
+                                               
+                                               cu1->resolu= cu->resolu;
+                                               
+                                               nu= cu1->nurb.first;
+                                               
+                                               while(nu) {
+                                                       nu->resolu= cu1->resolu;
+                                                       nu= nu->next;
+                                               }
+                                               
+                                               base->object->recalc |= OB_RECALC_DATA;
                                        }
                                }
                                else if(event==20) {    /* particle settings */
@@ -2591,14 +2833,19 @@ void copy_attr(short event)
                                }
                                else if(event==21){
                                        if (base->object->type==OB_MESH) {
-                                               Mesh *targetme= base->object->data;
-                                               Mesh *sourceme= ob->data;
-
-                                               targetme->flag= (targetme->flag&~ME_SUBSURF) | (sourceme->flag&ME_SUBSURF);
-                                               targetme->subsurftype = sourceme->subsurftype;
-                                               targetme->subdiv= sourceme->subdiv;
-                                               targetme->subdivr= sourceme->subdivr;
-                                               makeDispList(base->object);
+                                               ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
+
+                                               if (md) {
+                                                       ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
+
+                                                       if (!tmd) {
+                                                               tmd = modifier_new(eModifierType_Subsurf);
+                                                               BLI_addtail(&base->object->modifiers, tmd);
+                                                       }
+
+                                                       modifier_copyData(md, tmd);
+                                                       base->object->recalc |= OB_RECALC_DATA;
+                                               }
                                        }
                                }
                                else if(event==22) {
@@ -2611,15 +2858,17 @@ void copy_attr(short event)
                                        if (U.dupflag& USER_DUP_IPO)
                                                copy_constraint_channels(&base->object->constraintChannels, &ob->constraintChannels);
                                        else
-                                               clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels, NULL);
-
-                                       base->object->activecon = NULL;
+                                               clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels);
                                }
                                else if(event==23) {
                                        base->object->softflag= ob->softflag;
                                        if(base->object->soft) sbFree(base->object->soft);
                                        
                                        base->object->soft= copy_softbody(ob->soft);
+
+                                       if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
+                                               BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
+                                       }
                                }
                        }
                }
@@ -2627,6 +2876,8 @@ void copy_attr(short event)
        }
        
        allqueue(REDRAWVIEW3D, 0);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
+
        if(event==20) {
                allqueue(REDRAWBUTSOBJECT, 0);
        }
@@ -2778,6 +3029,8 @@ void make_links(short event)
                                                        
                                                        /* if amount of material indices changed: */
                                                        test_object_materials(obt->data);
+
+                                                       obt->recalc |= OB_RECALC_DATA;
                                                }
                                        }
                                else if(event==4) {  /* ob ipo */
@@ -2846,7 +3099,9 @@ void make_links(short event)
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSHEAD, 0);
-       
+
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
+
        BIF_undo_push("Create links");
 }
 
@@ -3265,9 +3520,19 @@ void std_rmouse_transform(void (*xf_func)(int, int))
        while(get_mbut() & mousebut) {
                getmouseco_areawin(mval);
                if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) {
-                       if(curarea->spacetype==SPACE_VIEW3D)
-                               Transform(TFM_TRANSLATION, CTX_NONE);
-                       else
+                       if(curarea->spacetype==SPACE_VIEW3D) {
+#ifdef TWEAK_MODE
+                               initTransform(TFM_TRANSLATION, CTX_TWEAK);
+#else
+                               initTransform(TFM_TRANSLATION, CTX_NONE);
+#endif
+                               Transform();
+                       }
+                       else if(curarea->spacetype==SPACE_IMAGE) {
+                               initTransform(TFM_TRANSLATION, CTX_NONE);
+                               Transform();
+                       }
+                       else if(xf_func)
                                xf_func('g', 0);
 
                        while(get_mbut() & mousebut) BIF_wait_for_statechange();
@@ -3277,8 +3542,10 @@ void std_rmouse_transform(void (*xf_func)(int, int))
                        PIL_sleep_ms(10);
                        timer++;
                        if(timer>=10*U.tb_rightmouse) {
-                               toolbox_n();
-                               return;
+                               if(curarea->spacetype==SPACE_VIEW3D) {
+                                       toolbox_n();
+                                       return;
+                               }
                        }
                }
        }
@@ -3288,13 +3555,17 @@ void std_rmouse_transform(void (*xf_func)(int, int))
 
 void rightmouse_transform(void)
 {
-       std_rmouse_transform(Transform);
+       std_rmouse_transform(NULL);
 }
 
 
 /* ************************************** */
 
 
+static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
+{
+       ID_NEW(*obpoin);
+}
 void single_object_users(int flag)     
 {
        Base *base;
@@ -3309,7 +3580,7 @@ void single_object_users(int flag)
                
                if( (base->flag & flag)==flag) {
 
-                       if(ob->id.lib==0 && ob->id.us>1) {
+                       if(ob->id.lib==NULL && ob->id.us>1) {
                        
                                obn= copy_object(ob);
                                ob->id.us--;
@@ -3326,7 +3597,7 @@ void single_object_users(int flag)
        base= FIRSTBASE;
        while(base) {
                ob= base->object;
-               if(ob->id.lib==0) {
+               if(ob->id.lib==NULL) {
                        if( (base->flag & flag)==flag) {
                                
                                relink_constraints(&base->object->constraints);
@@ -3336,17 +3607,10 @@ void single_object_users(int flag)
                                                relink_constraints(&chan->constraints);
                                        }
                                }
-                               if(base->object->hooks.first) {
-                                       ObHook *hook= base->object->hooks.first;
-                                       while(hook) {
-                                               ID_NEW(hook->parent);
-                                               hook= hook->next;
-                                       }
-                               }
+                               modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL);
                                
                                ID_NEW(ob->parent);
                                ID_NEW(ob->track);
-                               
                        }
                }
                base= base->next;
@@ -3382,9 +3646,7 @@ void single_obdata_users(int flag)
        Object *ob;
        Lamp *la;
        Curve *cu;
-       Ika *ika;
        Camera *cam;
-       Deform *def;
        Base *base;
        Mesh *me;
        ID *id;
@@ -3393,7 +3655,7 @@ void single_obdata_users(int flag)
        base= FIRSTBASE;
        while(base) {
                ob= base->object;
-               if(ob->id.lib==0 && (base->flag & flag)==flag ) {
+               if(ob->id.lib==NULL && (base->flag & flag)==flag ) {
                        id= ob->data;
                        
                        if(id && id->us>1 && id->lib==0) {
@@ -3424,28 +3686,14 @@ void single_obdata_users(int flag)
                                        ob->data= cu= copy_curve(ob->data);
                                        ID_NEW(cu->bevobj);
                                        ID_NEW(cu->taperobj);
-                                       makeDispList(ob);
                                        break;
                                case OB_LATTICE:
                                        ob->data= copy_lattice(ob->data);
                                        break;
                                case OB_ARMATURE:
-                                       ob->data=copy_armature(ob->data);
-                                       break;
-                               case OB_IKA:
-                                       /* this never occurs? IK is always single user */
-                                       ob->data= ika= copy_ika(ob->data);
-                                       ID_NEW(ika->parent);
-                                       
-                                       if(ika->totdef) {
-                                               a= ika->totdef;
-                                               def= ika->def;
-                                               while(a--) {
-                                                       ID_NEW(def->ob);
-                                                       def++;
-                                               }
-                                       }
-                                       
+                                       ob->recalc |= OB_RECALC_DATA;
+                                       ob->data= copy_armature(ob->data);
+                                       armature_rebuild_pose(ob, ob->data);
                                        break;
                                default:
                                        printf("ERROR single_obdata_users: %s\n", id->name);
@@ -3465,8 +3713,7 @@ void single_obdata_users(int flag)
                                        id_us_plus(id->newid);
                                }
                                else {
-                                       ob->action=copy_action(ob->action);
-                                       ob->activecon=NULL;
+                                       ob->action= copy_action(ob->action);
                                        id->us--;
                                        id->newid=(ID *)ob->action;
                                }
@@ -3525,7 +3772,7 @@ void single_mat_users(int flag)
        base= FIRSTBASE;
        while(base) {
                ob= base->object;
-               if(ob->id.lib==0 && (flag==0 || (base->flag & SELECT)) ) {
+               if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
        
                        for(a=1; a<=ob->totcol; a++) {
                                ma= give_current_material(ob, a);
@@ -3762,7 +4009,7 @@ void make_local(void)
        while(base) {
                ob= base->object;
                if( (base->flag & SELECT)) {
-                       if(ob->id.lib==0) {
+                       if(ob->id.lib==NULL) {
                                ID_NEW(ob->parent);
                                ID_NEW(ob->track);
                        }
@@ -3881,14 +4128,18 @@ void make_local(void)
        BIF_undo_push("Make local");
 }
 
-
-void adduplicate(float *dtrans)
+static void adduplicate__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
+{
+       ID_NEW(*obpoin);
+}
+void adduplicate(int noTrans)
 /* dtrans is 3 x 3xfloat dloc, drot en dsize */
 {
        Base *base, *basen;
        Object *ob, *obn;
        Material ***matarar, *ma, *mao;
        ID *id;
+       Ipo *ipo;
        bConstraintChannel *chan;
        int a, didit, dupflag;
        
@@ -3904,162 +4155,164 @@ void adduplicate(float *dtrans)
                if TESTBASELIB(base) {
                
                        ob= base->object;
-                       obn= copy_object(ob);
-                       
-                       basen= MEM_mallocN(sizeof(Base), "duplibase");
-                       *basen= *base;
-                       BLI_addhead(&G.scene->base, basen);     /* addhead: prevent eternal loop */
-                       basen->object= obn;
-                       base->flag &= ~SELECT;
-                       basen->flag &= ~OB_FROMGROUP;
-                       
-                       if(BASACT==base) BASACT= basen;
+                       if(ob->flag & OB_POSEMODE) {
+                               ; // nothing?
+                       }
+                       else {
+                               obn= copy_object(ob);
+                               obn->recalc |= OB_RECALC;
+                               
+                               basen= MEM_mallocN(sizeof(Base), "duplibase");
+                               *basen= *base;
+                               BLI_addhead(&G.scene->base, basen);     /* addhead: prevent eternal loop */
+                               basen->object= obn;
+                               base->flag &= ~SELECT;
+                               basen->flag &= ~OB_FROMGROUP;
+                               
+                               if(BASACT==base) BASACT= basen;
 
-                       /* duplicates using userflags */
-                       
-                       if(dupflag & USER_DUP_IPO) {
-                               id= (ID *)obn->ipo;
-                               if(id) {
-                                       ID_NEW_US( obn->ipo)
-                                               else obn->ipo= copy_ipo(obn->ipo);
-                                       id->us--;
-                               }
-                               /* Handle constraint ipos */
-                               for (chan=obn->constraintChannels.first; chan; chan=chan->next){
-                                       id= (ID *)chan->ipo;
+                               /* duplicates using userflags */
+                               
+                               if(dupflag & USER_DUP_IPO) {
+                                       id= (ID *)obn->ipo;
                                        if(id) {
-                                               ID_NEW_US( chan->ipo)
-                                                       else chan->ipo= copy_ipo(chan->ipo);
+                                               ID_NEW_US( obn->ipo)
+                                               else obn->ipo= copy_ipo(obn->ipo);
                                                id->us--;
                                        }
-                               }
-                       }
-                       if(dupflag & USER_DUP_ACT){
-                               id= (ID *)obn->action;
-                               if (id){
-                                       ID_NEW_US(obn->action)
-                                               else{
-                                               obn->action= copy_action(obn->action);
-                                               obn->activecon=NULL;
+                                       /* Handle constraint ipos */
+                                       for (chan=obn->constraintChannels.first; chan; chan=chan->next){
+                                               id= (ID *)chan->ipo;
+                                               if(id) {
+                                                       ID_NEW_US( chan->ipo)
+                                                       else chan->ipo= copy_ipo(chan->ipo);
+                                                       id->us--;
+                                               }
                                        }
-                                       id->us--;
                                }
-                       }
-                       if(dupflag & USER_DUP_MAT) {
-                               for(a=0; a<obn->totcol; a++) {
-                                       id= (ID *)obn->mat[a];
-                                       if(id) {
-                                               ID_NEW_US(obn->mat[a])
-                                               else obn->mat[a]= copy_material(obn->mat[a]);
+                               if(dupflag & USER_DUP_ACT){
+                                       id= (ID *)obn->action;
+                                       if (id){
+                                               ID_NEW_US(obn->action)
+                                               else{
+                                                       obn->action= copy_action(obn->action);
+                                               }
                                                id->us--;
                                        }
                                }
-                       }
-                       
-                       id= obn->data;
-                       didit= 0;
-                       
-                       switch(obn->type) {
-                       case OB_MESH:
-                               if(dupflag & USER_DUP_MESH) {
-                                       ID_NEW_US2( obn->data )
-                                       else {
-                                               obn->data= copy_mesh(obn->data);
-                                               didit= 1;
+                               if(dupflag & USER_DUP_MAT) {
+                                       for(a=0; a<obn->totcol; a++) {
+                                               id= (ID *)obn->mat[a];
+                                               if(id) {
+                                                       ID_NEW_US(obn->mat[a])
+                                                       else obn->mat[a]= copy_material(obn->mat[a]);
+                                                       id->us--;
+                                               }
                                        }
-                                       id->us--;
                                }
-                               break;
-                       case OB_CURVE:
-                               if(dupflag & USER_DUP_CURVE) {
-                                       ID_NEW_US2(obn->data )
-                                       else {
-                                               obn->data= copy_curve(obn->data);
-                                               makeDispList(ob);
-                                               didit= 1;
+                               
+                               id= obn->data;
+                               didit= 0;
+                               
+                               switch(obn->type) {
+                               case OB_MESH:
+                                       if(dupflag & USER_DUP_MESH) {
+                                               ID_NEW_US2( obn->data )
+                                               else {
+                                                       obn->data= copy_mesh(obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
                                        }
-                                       id->us--;
-                               }
-                               break;
-                       case OB_SURF:
-                               if(dupflag & USER_DUP_SURF) {
-                                       ID_NEW_US2( obn->data )
-                                       else {
-                                               obn->data= copy_curve(obn->data);
-                                               makeDispList(ob);
-                                               didit= 1;
+                                       break;
+                               case OB_CURVE:
+                                       if(dupflag & USER_DUP_CURVE) {
+                                               ID_NEW_US2(obn->data )
+                                               else {
+                                                       obn->data= copy_curve(obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
                                        }
-                                       id->us--;
-                               }
-                               break;
-                       case OB_FONT:
-                               if(dupflag & USER_DUP_FONT) {
-                                       ID_NEW_US2( obn->data )
-                                       else {
-                                               obn->data= copy_curve(obn->data);
-                                               makeDispList(ob);
-                                               didit= 1;
+                                       break;
+                               case OB_SURF:
+                                       if(dupflag & USER_DUP_SURF) {
+                                               ID_NEW_US2( obn->data )
+                                               else {
+                                                       obn->data= copy_curve(obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
                                        }
-                                       id->us--;
-                               }
-                               break;
-                       case OB_MBALL:
-                               if(dupflag & USER_DUP_MBALL) {
-                                       ID_NEW_US2(obn->data )
-                                       else {
-                                               obn->data= copy_mball(obn->data);
-                                               didit= 1;
+                                       break;
+                               case OB_FONT:
+                                       if(dupflag & USER_DUP_FONT) {
+                                               ID_NEW_US2( obn->data )
+                                               else {
+                                                       obn->data= copy_curve(obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
                                        }
-                                       id->us--;
-                               }
-                               break;
-                       case OB_LAMP:
-                               if(dupflag & USER_DUP_LAMP) {
+                                       break;
+                               case OB_MBALL:
+                                       if(dupflag & USER_DUP_MBALL) {
+                                               ID_NEW_US2(obn->data )
+                                               else {
+                                                       obn->data= copy_mball(obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
+                                       }
+                                       break;
+                               case OB_LAMP:
+                                       if(dupflag & USER_DUP_LAMP) {
+                                               ID_NEW_US2(obn->data )
+                                               else obn->data= copy_lamp(obn->data);
+                                               id->us--;
+                                       }
+                                       break;
+
+                               case OB_ARMATURE:
+                                       obn->recalc |= OB_RECALC_DATA;
+                                       if(obn->pose) obn->pose->flag |= POSE_RECALC;
+                                       
+                                       if(dupflag & USER_DUP_ARM) {
+                                               ID_NEW_US2(obn->data )
+                                               else {
+                                                       obn->data= copy_armature(obn->data);
+                                                       armature_rebuild_pose(obn, obn->data);
+                                                       didit= 1;
+                                               }
+                                               id->us--;
+                                       }
+                                       
+                                       break;
+                                       
+                               /* always dupli's */
+                               case OB_LATTICE:
                                        ID_NEW_US2(obn->data )
-                                       else obn->data= copy_lamp(obn->data);
+                                       else obn->data= copy_lattice(obn->data);
                                        id->us--;
-                               }
-                               break;
-
-                       case OB_ARMATURE:
-                               if(dupflag & USER_DUP_ARM) {
+                                       break;
+                               case OB_CAMERA:
                                        ID_NEW_US2(obn->data )
-                                       else {
-                                               obn->data= copy_armature(obn->data);
-                                               didit= 1;
-                                       }
+                                       else obn->data= copy_camera(obn->data);
                                        id->us--;
+                                       break;
                                }
-                               break;
-                       /* always dupli's */
-               
-                       case OB_LATTICE:
-                               ID_NEW_US2(obn->data )
-                               else obn->data= copy_lattice(obn->data);
-                               id->us--;
-                               break;
-                       case OB_CAMERA:
-                               ID_NEW_US2(obn->data )
-                               else obn->data= copy_camera(obn->data);
-                               id->us--;
-                               break;
-                       case OB_IKA:
-                               ID_NEW_US2(obn->data )
-                               else obn->data= copy_ika(obn->data);
-                               id->us--;
-                               break;
-                       }
-                       
-                       if(dupflag & USER_DUP_MAT) {
-                               matarar= give_matarar(obn);
-                               if(didit && matarar) {
-                                       for(a=0; a<obn->totcol; a++) {
-                                               id= (ID *)(*matarar)[a];
-                                               if(id) {
-                                                       ID_NEW_US( (*matarar)[a] )
-                                                       else (*matarar)[a]= copy_material((*matarar)[a]);
-                                                       
-                                                       id->us--;
+                               
+                               if(dupflag & USER_DUP_MAT) {
+                                       matarar= give_matarar(obn);
+                                       if(didit && matarar) {
+                                               for(a=0; a<obn->totcol; a++) {
+                                                       id= (ID *)(*matarar)[a];
+                                                       if(id) {
+                                                               ID_NEW_US( (*matarar)[a] )
+                                                               else (*matarar)[a]= copy_material((*matarar)[a]);
+                                                               
+                                                               id->us--;
+                                                       }
                                                }
                                        }
                                }
@@ -4073,7 +4326,6 @@ void adduplicate(float *dtrans)
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
-                       
                        relink_constraints(&base->object->constraints);
                        if (base->object->pose){
                                bPoseChannel *chan;
@@ -4081,20 +4333,28 @@ void adduplicate(float *dtrans)
                                        relink_constraints(&chan->constraints);
                                }
                        }
-                       if(base->object->hooks.first) {
-                               ObHook *hook= base->object->hooks.first;
-                               while(hook) {
-                                       ID_NEW(hook->parent);
-                                       hook= hook->next;
-                               }
-                       }
+                       modifiers_foreachObjectLink(base->object, adduplicate__forwardModifierLinks, NULL);
                        ID_NEW(base->object->parent);
                        ID_NEW(base->object->track);
                        
                }
                base= base->next;
        }
-
+       
+       /* ipos */
+       ipo= G.main->ipo.first;
+       while(ipo) {
+               if(ipo->id.lib==NULL && ipo->id.newid) {
+                       IpoCurve *icu;
+                       for(icu= ipo->curve.first; icu; icu= icu->next) {
+                               if(icu->driver) {
+                                       ID_NEW(icu->driver->ob);
+                               }
+                       }
+               }
+               ipo= ipo->id.next;
+       }
+       
        /* materials */
        if( dupflag & USER_DUP_MAT) {
                mao= G.main->mat.first;
@@ -4126,15 +4386,17 @@ void adduplicate(float *dtrans)
                }
        }
 
-       sort_baselist(G.scene);
+       DAG_scene_sort(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        set_sca_new_poins();
 
        clear_id_newpoins();
        
        countall();
-       if(dtrans==0) {
+       if(!noTrans) {
                BIF_TransformSetUndo("Add Duplicate");
-               Transform(TFM_TRANSLATION, CTX_NONE);
+               initTransform(TFM_TRANSLATION, CTX_NONE);
+               Transform();
        }
        set_active_base(BASACT);
        
@@ -4230,6 +4492,7 @@ void selectlinks(int nr)
                }
                base= base->next;
        }
+       
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWDATASELECT, 0);
        allqueue(REDRAWOOPS, 0);
@@ -4243,8 +4506,6 @@ void image_aspect(void)
        Object *ob;
        Material *ma;
        Tex *tex;
-       Mesh *me;
-       Curve *cu;
        float x, y, space;
        int a, b, done;
        
@@ -4264,14 +4525,16 @@ void image_aspect(void)
                                                if(ma->mtex[b] && ma->mtex[b]->tex) {
                                                        tex= ma->mtex[b]->tex;
                                                        if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {
+
                                                                /* texturespace */
                                                                space= 1.0;
                                                                if(ob->type==OB_MESH) {
-                                                                       me= ob->data;
-                                                                       space= me->size[0]/me->size[1];
+                                                                       float size[3];
+                                                                       mesh_get_texspace(ob->data, NULL, NULL, size);
+                                                                       space= size[0]/size[1];
                                                                }
                                                                else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
-                                                                       cu= ob->data;
+                                                                       Curve *cu= ob->data;
                                                                        space= cu->size[0]/cu->size[1];
                                                                }
                                                        
@@ -4282,6 +4545,7 @@ void image_aspect(void)
                                                                else ob->size[1]= ob->size[0]*y/x;
                                                                
                                                                done= 1;
+                                                               DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);                                                             
                                                        }
                                                }
                                                if(done) break;
@@ -4480,45 +4744,23 @@ void texspace_edit(void)
        }
        
 
-       if(nr==1) Transform(TFM_TRANSLATION, CTX_TEXTURE);
-       else if(nr==2) Transform(TFM_RESIZE, CTX_TEXTURE);
-       else if(nr==3) Transform(TFM_ROTATION, CTX_TEXTURE);
-}
-
-void first_base(void)
-{
-       /* inserts selected Bases in beginning of list, sometimes useful for operation order */
-       Base *base, *next;
-       
-       if(okee("Make first base")==0) return;
-       
-       base= FIRSTBASE;
-       while(base) {
-               next= base->next;
-               
-               if(base->flag & SELECT) {
-                       BLI_remlink(&G.scene->base, base);
-                       BLI_addtail(&G.scene->base, base);
-               }
-               
-               base= next;
+       if(nr==1) {
+               initTransform(TFM_TRANSLATION, CTX_TEXTURE);
+               Transform();
+       }
+       else if(nr==2) {
+               initTransform(TFM_RESIZE, CTX_TEXTURE);
+               Transform();
+       }
+       else if(nr==3) {
+               initTransform(TFM_ROTATION, CTX_TEXTURE);
+               Transform();
        }
-       
-}
-
-void make_displists_by_obdata(void *obdata) {
-       Base *base;
-       
-       for (base= FIRSTBASE; base; base= base->next)
-               if (obdata==base->object->data)
-                       makeDispList(base->object);
 }
 
 /* ******************************************************************** */
 /* Mirror function in Edit Mode */
 
-
-
 void mirrormenu(void)
 {
        short mode = 0;