Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
[blender.git] / source / blender / src / editobject.c
index e82e0e6ebba617e2a228dd3a10fa991ed747c7a1..d46c06bd4b9ecd39d24e73a5bfa9fafbb59b5536 100644 (file)
@@ -81,6 +81,7 @@
 #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 "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_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"
 
 /* --------------------------------- */
 
-Base *dupfontbase;
-
 void add_object_draw(int type) /* for toolbox or menus, only non-editmode stuff */
 {
        Object *ob;
@@ -182,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... */
@@ -278,7 +278,7 @@ void delete_obj(int ok)
        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,28 +701,24 @@ 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);
        }
 
@@ -814,7 +885,7 @@ void clear_parent(void)
        }
 
        DAG_scene_sort(G.scene);
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        
@@ -878,7 +949,7 @@ void clear_object(char mode)
                                // no test if we got armature; could be in future...
                                clear_armature(ob, mode);
                        }
-                       else {
+                       else if((G.f & G_WEIGHTPAINT)==0) {
                                
                                if(mode=='r') {
                                        memset(ob->rot, 0, 3*sizeof(float));
@@ -917,7 +988,7 @@ void clear_object(char mode)
        }
        
        allqueue(REDRAWVIEW3D, 0);
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        BIF_undo_push(str);
 }
 
@@ -1126,7 +1197,19 @@ 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;
 
@@ -1143,7 +1226,7 @@ void make_parent(void)
                        mode= PAROBJECT;
                        if((cu->flag & CU_PATH)==0) {
                                cu->flag |= CU_PATH|CU_FOLLOW;
-                               makeDispListCurveTypes(par);  // force creation of path data
+                               makeDispListCurveTypes(par, 0);  // force creation of path data
                        }
                        else cu->flag |= CU_FOLLOW;
                }
@@ -1273,7 +1356,7 @@ void make_parent(void)
                                }
                                else {
                                        
-                                       base->object->recalc |= OB_RECALC_OB;
+                                       base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
                                        
                                        /* the ifs below are horrible code (ton) */
                                        
@@ -1288,7 +1371,7 @@ 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 {
@@ -1325,7 +1408,6 @@ void make_parent(void)
                                        
                                        if(par->type==OB_ARMATURE && mode == PARSKEL){
                                                verify_defgroups(base->object);
-                                               base->object->recalc |= OB_RECALC_DATA;
                                        }
                                }
                        }
@@ -1336,7 +1418,7 @@ void make_parent(void)
        allqueue(REDRAWOOPS, 0);
        
        DAG_scene_sort(G.scene);
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        
        BIF_undo_push("make Parent");
 }
@@ -1350,7 +1432,6 @@ void enter_editmode(void)
        Mesh *me;
        int ok= 0;
        bArmature *arm;
-       Curve *cu;
        
        if(G.scene->id.lib) return;
        base= BASACT;
@@ -1394,20 +1475,6 @@ void enter_editmode(void)
                allqueue (REDRAWVIEW3D,0);
        }
        else if(ob->type==OB_FONT) {
-               cu= ob->data;
-               if ((cu->flag & CU_FAST)==0) { 
-                       base->flag |= SELECT;
-                       ob->flag |= SELECT;
-                       G.qual |= LR_ALTKEY;    /* patch to make sure we get a linked duplicate */
-                       adduplicate(1);
-                       G.qual &= ~LR_ALTKEY;
-                       dupfontbase = BASACT;
-                       BASACT->flag &= ~SELECT;
-                       BASACT->object->flag &= ~SELECT;
-                       set_active_base(base);
-                       base->flag |= SELECT;
-                       base->object->flag |= SELECT;
-               }
                G.obedit= ob;
                ok= 1;
                make_editText();
@@ -1445,7 +1512,6 @@ void enter_editmode(void)
 
 void exit_editmode(int freedata)       /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
 {
-       Base *oldbase;
        Object *ob;
 
        if(G.obedit==NULL) return;
@@ -1496,33 +1562,14 @@ void exit_editmode(int freedata)        /* freedata==0 at render, 1= freedata, 2= do un
        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, NULL);
+       if(modifiers_isSoftbodyEnabled(ob)) {
+               if (ob->soft && ob->soft->keys) {
+                       notice("Erased Baked SoftBody");
                }
-               else sbObjectToSoftbody(ob, NULL);
-       }
-       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
 
-       // evil HACK!
-       if ((ob->type == OB_FONT) && (freedata)) {
-               Curve *cu= ob->data;
-               if ((cu->flag & CU_FAST)==0) {
-                       oldbase = BASACT;
-                       BASACT->flag &= ~SELECT;
-                       BASACT->object->flag &= ~SELECT;
-                       set_active_base(dupfontbase);
-                       BASACT->flag |= SELECT;
-                       BASACT->object->flag |= SELECT;
-                       delete_obj(1);
-                       oldbase->flag |= SELECT;
-                       oldbase->object->flag |= SELECT;
-                       set_active_base(oldbase);
-               }
+               sbObjectToSoftbody(ob);
        }
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
 
        if(freedata) {
                setcursor_space(SPACE_VIEW3D, CURSOR_STD);
@@ -1774,14 +1821,13 @@ void docentre(int centremode)
 
                                        allqueue(REDRAWBUTSEDIT, 0);
                                }
-                               base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+                               DAG_object_flush_update(G.scene, base->object, OB_RECALC_OB|OB_RECALC_DATA);
                        }
                }
                base= base->next;
        }
 
        allqueue(REDRAWVIEW3D, 0);
-       DAG_scene_flush_update(G.scene);
        BIF_undo_push("Do Centre");     
 }
 
@@ -1867,7 +1913,7 @@ void split_font()
                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);
+               makeDispListCurveTypes(OBACT, 0);
                
                OBACT->flag &= ~SELECT;
                BASACT->flag &= ~SELECT;
@@ -1880,8 +1926,6 @@ void split_font()
 void special_editmenu(void)
 {
        Object *ob= OBACT;
-       extern short editbutflag;
-       extern float doublimit;
        float fac;
        int nr,ret;
        short randfac,numcuts;
@@ -1930,6 +1974,7 @@ 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");
@@ -1949,6 +1994,18 @@ 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 {
@@ -1961,7 +2018,8 @@ void special_editmenu(void)
                        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.
                                        // All of the boolean functions require 2 mesh objects 
@@ -1976,16 +2034,30 @@ void special_editmenu(void)
 
                                        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");
                                                }
@@ -2007,32 +2079,32 @@ void special_editmenu(void)
                }
        }
        else if(G.obedit->type==OB_MESH) {
-        
-               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");
+
+               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:
-            numcuts = 1;
+                       numcuts = 1;
                        waitcursor(1);
-            esubdivideflag(1, 0.0, editbutflag,numcuts,0);
+                       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;
+               numcuts = 2;
+                       if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
                        waitcursor(1);
-            esubdivideflag(1, 0.0, editbutflag,numcuts,0);
+                       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;
+                       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;
-                       esubdivideflag(1, fac, editbutflag,numcuts,0);
+                       esubdivideflag(1, fac, G.scene->toolsettings->editbutflag,numcuts,0);
                        BIF_undo_push("Subdivide Fractal");
                        break;
 
@@ -2040,7 +2112,7 @@ void special_editmenu(void)
                        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:
@@ -2063,17 +2135,23 @@ void special_editmenu(void)
                        bevel_menu();
                        break;
                case 12:
-            numcuts = 2;
-            if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+                       numcuts = 2;
+                       if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
                        waitcursor(1);
-                       esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,numcuts,0);
+                       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, editbutflag | B_SMOOTH);
+                       subdivideflag(1, 0.0, G.scene->toolsettings->editbutflag | B_SMOOTH);
                        BIF_undo_push("Subdivide Smooth");
-                       break;          
+                       break;
+               case 14:
+                       mesh_set_smooth_faces(1);
+                       break;
+               case 15: 
+                       mesh_set_smooth_faces(0);
+                       break;
                }
                
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -2096,6 +2174,13 @@ void special_editmenu(void)
                
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        }
+       else if(G.obedit->type==OB_ARMATURE) {
+               nr= pupmenu("Specials%t|Subdivide %x1|Flip Left-Right Names%x2");
+               if(nr==1)
+                       subdivide_armature();
+               else if(nr==2)
+                       armature_flip_names();
+       }
 
        countall();
        allqueue(REDRAWVIEW3D, 0);
@@ -2171,6 +2256,7 @@ void convertmenu(void)
 
                                ob1= copy_object(ob);
                                ob1->recalc |= OB_RECALC;
+                               object_free_modifiers(ob1);
 
                                basen= MEM_mallocN(sizeof(Base), "duplibase");
                                *basen= *base;
@@ -2191,13 +2277,11 @@ void convertmenu(void)
                                        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);
-                               dm->release(dm);
 
+                               dm= mesh_create_derived_no_deform(ob, NULL);
+                               dlm= dm->convertToDispListMesh(dm, 0);
                                displistmesh_to_mesh(dlm, ob1->data);
-                               displistmesh_free(dlm);
+                               dm->release(dm);
                        }
                        else if(ob->type==OB_FONT) {
                                if(nr==1) {
@@ -2243,7 +2327,7 @@ void convertmenu(void)
                                        cu= ob->data;
                                        
                                        dl= cu->disp.first;
-                                       if(dl==0) makeDispListCurveTypes(ob);           // force creation
+                                       if(dl==0) makeDispListCurveTypes(ob, 0);                // force creation
 
                                        nurbs_to_mesh(ob); /* also does users */
 
@@ -2297,14 +2381,14 @@ void convertmenu(void)
                        free_and_unlink_base(basedel);  
                basedel = NULL;                         
        }
-       
+
        countall();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSEDIT, 0);
        BIF_undo_push("Convert Object");
 
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_sort(G.scene);
 }
 
        /* Change subdivision properties of mesh object ob, if
@@ -2312,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);
+       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;
@@ -2394,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;
        
@@ -2428,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
@@ -2449,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");
@@ -2458,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;
        
@@ -2469,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;
@@ -2494,6 +2673,10 @@ void copy_attr(short event)
                copymenu_logicbricks(ob);
                return;
        }
+       else if(event==24) {
+               copymenu_modifiers(ob);
+               return;
+       }
 
        base= FIRSTBASE;
        while(base) {
@@ -2604,6 +2787,24 @@ void copy_attr(short event)
                                                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 */
                                        PartEff *pa1, *pa2;
                                        char *p1, *p2;
@@ -2632,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;
+                                               ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
 
-                                               targetme->flag= (targetme->flag&~ME_SUBSURF) | (sourceme->flag&ME_SUBSURF);
-                                               targetme->subsurftype = sourceme->subsurftype;
-                                               targetme->subdiv= sourceme->subdiv;
-                                               targetme->subdivr= sourceme->subdivr;
-                                               base->object->recalc |= OB_RECALC_DATA;
+                                               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) {
@@ -2652,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));
+                                       }
                                }
                        }
                }
@@ -2668,7 +2876,7 @@ void copy_attr(short event)
        }
        
        allqueue(REDRAWVIEW3D, 0);
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
 
        if(event==20) {
                allqueue(REDRAWBUTSOBJECT, 0);
@@ -2821,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 */
@@ -2889,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");
 }
 
@@ -3309,6 +3521,14 @@ void std_rmouse_transform(void (*xf_func)(int, int))
                getmouseco_areawin(mval);
                if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) {
                        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();
                        }
@@ -3322,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;
+                               }
                        }
                }
        }
@@ -3340,6 +3562,10 @@ void rightmouse_transform(void)
 /* ************************************** */
 
 
+static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
+{
+       ID_NEW(*obpoin);
+}
 void single_object_users(int flag)     
 {
        Base *base;
@@ -3381,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;
@@ -3472,7 +3691,9 @@ void single_obdata_users(int flag)
                                        ob->data= copy_lattice(ob->data);
                                        break;
                                case OB_ARMATURE:
-                                       ob->data=copy_armature(ob->data);
+                                       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);
@@ -3492,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;
                                }
@@ -3908,7 +4128,10 @@ void make_local(void)
        BIF_undo_push("Make local");
 }
 
-
+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 */
 {
@@ -3916,6 +4139,7 @@ void adduplicate(int noTrans)
        Object *ob, *obn;
        Material ***matarar, *ma, *mao;
        ID *id;
+       Ipo *ipo;
        bConstraintChannel *chan;
        int a, didit, dupflag;
        
@@ -3953,7 +4177,7 @@ void adduplicate(int noTrans)
                                        id= (ID *)obn->ipo;
                                        if(id) {
                                                ID_NEW_US( obn->ipo)
-                                                       else obn->ipo= copy_ipo(obn->ipo);
+                                               else obn->ipo= copy_ipo(obn->ipo);
                                                id->us--;
                                        }
                                        /* Handle constraint ipos */
@@ -3961,7 +4185,7 @@ void adduplicate(int noTrans)
                                                id= (ID *)chan->ipo;
                                                if(id) {
                                                        ID_NEW_US( chan->ipo)
-                                                               else chan->ipo= copy_ipo(chan->ipo);
+                                                       else chan->ipo= copy_ipo(chan->ipo);
                                                        id->us--;
                                                }
                                        }
@@ -3970,9 +4194,8 @@ void adduplicate(int noTrans)
                                        id= (ID *)obn->action;
                                        if (id){
                                                ID_NEW_US(obn->action)
-                                                       else{
+                                               else{
                                                        obn->action= copy_action(obn->action);
-                                                       obn->activecon=NULL;
                                                }
                                                id->us--;
                                        }
@@ -4058,6 +4281,7 @@ void adduplicate(int noTrans)
                                                ID_NEW_US2(obn->data )
                                                else {
                                                        obn->data= copy_armature(obn->data);
+                                                       armature_rebuild_pose(obn, obn->data);
                                                        didit= 1;
                                                }
                                                id->us--;
@@ -4102,7 +4326,6 @@ void adduplicate(int noTrans)
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
-                       
                        relink_constraints(&base->object->constraints);
                        if (base->object->pose){
                                bPoseChannel *chan;
@@ -4110,20 +4333,28 @@ void adduplicate(int noTrans)
                                        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;
@@ -4156,7 +4387,7 @@ void adduplicate(int noTrans)
        }
 
        DAG_scene_sort(G.scene);
-       DAG_scene_flush_update(G.scene);
+       DAG_scene_flush_update(G.scene, screen_view3d_layers());
        set_sca_new_poins();
 
        clear_id_newpoins();
@@ -4261,6 +4492,7 @@ void selectlinks(int nr)
                }
                base= base->next;
        }
+       
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWDATASELECT, 0);
        allqueue(REDRAWOOPS, 0);
@@ -4313,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;