Bugfix #25636
[blender.git] / source / blender / editors / mesh / editmesh_add.c
index c2e98e97e091c48f68703275bea992cc1ef8f03a..d9db1e99bfa68d2f5167be467b6e4f72b2b8f1e8 100644 (file)
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_editVert.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
-#include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_mesh.h"
-#include "BKE_object.h"
-#include "BKE_utildefines.h"
 #include "BKE_report.h"
 
 #include "WM_api.h"
@@ -113,57 +111,98 @@ static short icoface[20][3] = {
 static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
 {
        ViewContext vc;
-       EditVert *eve, *v1;
+       EditVert *eve;
        float min[3], max[3];
        int done= 0;
-       
+       short use_proj;
+
        em_setup_viewcontext(C, &vc);
+
+       use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) &&     (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
+       
+       invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
        
        INIT_MINMAX(min, max);
        
-       for(v1= vc.em->verts.first;v1; v1=v1->next) {
-               if(v1->f & SELECT) {
-                       DO_MINMAX(v1->co, min, max);
+       for(eve= vc.em->verts.first; eve; eve= eve->next) {
+               if(eve->f & SELECT) {
+                       DO_MINMAX(eve->co, min, max);
                        done= 1;
                }
        }
 
        /* call extrude? */
        if(done) {
+               short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
                EditEdge *eed;
                float vec[3], cent[3], mat[3][3];
                float nor[3]= {0.0, 0.0, 0.0};
                
-               /* check for edges that are half selected, use for rotation */
+               /* 2D normal calc */
+               float mval_f[2];
+
+               mval_f[0]= (float)event->mval[0];
+               mval_f[1]= (float)event->mval[1];
+
                done= 0;
+
+               /* calculate the normal for selected edges */
                for(eed= vc.em->edges.first; eed; eed= eed->next) {
-                       if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) {
-                               if(eed->v1->f & SELECT) sub_v3_v3v3(vec, eed->v1->co, eed->v2->co);
-                               else sub_v3_v3v3(vec, eed->v2->co, eed->v1->co);
-                               add_v3_v3v3(nor, nor, vec);
+                       if(eed->f & SELECT) {
+                               float co1[3], co2[3];
+                               mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
+                               mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
+                               project_float_noclip(vc.ar, co1, co1);
+                               project_float_noclip(vc.ar, co2, co2);
+                               
+                               /* 2D rotate by 90d while adding.
+                                *  (x, y) = (y, -x)
+                                *
+                                * accumulate the screenspace normal in 2D,
+                                * with screenspace edge length weighting the result. */
+                               if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
+                                       nor[0] +=  (co1[1] - co2[1]);
+                                       nor[1] += -(co1[0] - co2[0]);
+                               }
+                               else {
+                                       nor[0] +=  (co2[1] - co1[1]);
+                                       nor[1] += -(co2[0] - co1[0]);
+                               }
                                done= 1;
                        }
                }
-               if(done) normalize_v3(nor);
+
+               if(done) {
+                       float view_vec[3], cross[3];
+
+                       /* convert the 2D nomal into 3D */
+                       mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
+                       mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
+                       
+                       /* correct the normal to be aligned on the view plane */
+                       copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
+                       mul_mat3_m4_v3(vc.obedit->imat, view_vec);
+                       cross_v3_v3v3(cross, nor, view_vec);
+                       cross_v3_v3v3(nor, view_vec, cross);
+                       normalize_v3(nor);
+               }
                
                /* center */
-               add_v3_v3v3(cent, min, max);
-               mul_v3_fl(cent, 0.5f);
-               VECCOPY(min, cent);
+               mid_v3_v3v3(cent, min, max);
+               copy_v3_v3(min, cent);
                
                mul_m4_v3(vc.obedit->obmat, min);       // view space
                view3d_get_view_aligned_coordinate(&vc, min, event->mval);
-               invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
                mul_m4_v3(vc.obedit->imat, min); // back in object space
                
-               sub_v3_v3v3(min, min, cent);
+               sub_v3_v3(min, cent);
                
                /* calculate rotation */
                unit_m3(mat);
                if(done) {
                        float dot;
                        
-                       VECCOPY(vec, min);
+                       copy_v3_v3(vec, min);
                        normalize_v3(vec);
                        dot= INPR(vec, nor);
 
@@ -173,27 +212,38 @@ static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
                                cross_v3_v3v3(cross, nor, vec);
                                normalize_v3(cross);
                                dot= 0.5f*saacos(dot);
+                               
+                               /* halve the rotation if its applied twice */
+                               if(rot_src) dot *= 0.5f;
+                               
                                si= (float)sin(dot);
                                q1[0]= (float)cos(dot);
                                q1[1]= cross[0]*si;
                                q1[2]= cross[1]*si;
-                               q1[3]= cross[2]*si;
-                               
+                               q1[3]= cross[2]*si;                             
                                quat_to_mat3( mat,q1);
                        }
                }
                
+               if(rot_src) {
+                       rotateflag(vc.em, SELECT, cent, mat);
+                       /* also project the source, for retopo workflow */
+                       if(use_proj)
+                               EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
+               }
+               
                extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
                rotateflag(vc.em, SELECT, cent, mat);
                translateflag(vc.em, SELECT, min);
                
                recalc_editnormals(vc.em);
        }
-       else {
+       else if(vc.em->selectmode & SCE_SELECT_VERTEX) {
+
                float mat[3][3],imat[3][3];
                float *curs= give_cursor(vc.scene, vc.v3d);
                
-               VECCOPY(min, curs);
+               copy_v3_v3(min, curs);
                view3d_get_view_aligned_coordinate(&vc, min, event->mval);
                
                eve= addvertlist(vc.em, 0, NULL);
@@ -201,16 +251,18 @@ static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
                copy_m3_m4(mat, vc.obedit->obmat);
                invert_m3_m3(imat, mat);
                
-               VECCOPY(eve->co, min);
+               copy_v3_v3(eve->co, min);
                mul_m3_v3(imat, eve->co);
                sub_v3_v3v3(eve->co, eve->co, vc.obedit->obmat[3]);
                
                eve->f= SELECT;
        }
-       
-       //retopo_do_all();
+
+       if(use_proj)
+               EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
+
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); 
-       DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA);
+       DAG_id_tag_update(vc.obedit->data, 0);
        
        return OPERATOR_FINISHED;
 }
@@ -228,6 +280,8 @@ void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape");
 }
 
 
@@ -306,13 +360,13 @@ int make_fgon(EditMesh *em, wmOperator *op, int make)
                if(eve->f1==1) break;
        }
        if(eve) {
-               BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices");
+               BKE_report(op->reports, RPT_WARNING, "Cannot make a polygon with interior vertices");
                return 0;
        }
        
        // check for faces
        if(nor==NULL) {
-               BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon");
+               BKE_report(op->reports, RPT_WARNING, "No faces were selected to make FGon");
                return 0;
        }
 
@@ -335,7 +389,7 @@ static int make_fgon_exec(bContext *C, wmOperator *op)
        EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
 
        if( make_fgon(em, op, 1) ) {
-               DAG_id_flush_update(obedit->data, OB_RECALC_DATA);      
+               DAG_id_tag_update(obedit->data, 0);
                WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
                BKE_mesh_end_editmesh(obedit->data, em);
@@ -367,7 +421,7 @@ static int clear_fgon_exec(bContext *C, wmOperator *op)
        EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
        
        if( make_fgon(em, op, 0) ) {
-               DAG_id_flush_update(obedit->data, OB_RECALC_DATA);      
+               DAG_id_tag_update(obedit->data, 0);
                WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
                
                BKE_mesh_end_editmesh(obedit->data, em);
@@ -656,7 +710,7 @@ void addfaces_from_edgenet(EditMesh *em)
 
        EM_select_flush(em);
        
-// XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+// XXX DAG_id_tag_update(obedit->data, 0);
 }
 
 static void addedgeface_mesh(EditMesh *em, wmOperator *op)
@@ -685,7 +739,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
                eed= addedgelist(em, neweve[0], neweve[1], NULL);
                EM_select_edge(eed, 1);
 
-               // XXX          DAG_id_flush_update(obedit->data, OB_RECALC_DATA);      
+               // XXX          DAG_id_tag_update(obedit->data, 0);
                return;
        }
        else if(amount > 4) {
@@ -693,7 +747,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
                return;
        }
        else if(amount<2) {
-               BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face");
+               BKE_report(op->reports, RPT_WARNING, "More vertices are needed to make an edge/face");
                return;
        }
 
@@ -705,7 +759,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
                        efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
                        EM_select_face(efa, 1);
                }
-               else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+               else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
        }
        else if(amount==4) {
                /* this test survives when theres 2 triangles */
@@ -757,14 +811,14 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
                                                else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
                                                        efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
                                                }
-                                               else BKE_report(op->reports, RPT_ERROR, "cannot find nice quad from concave set of vertices");
+                                               else BKE_report(op->reports, RPT_WARNING, "cannot find nice quad from concave set of vertices");
 
                                        }
                                }
                        }
-                       else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+                       else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
                }
-               else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
+               else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
        }
        
        if(efa) {
@@ -783,7 +837,7 @@ static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
        
        addedgeface_mesh(em, op);
        
-       DAG_id_flush_update(obedit->data, OB_RECALC_DATA);      
+       DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
        
        BKE_mesh_end_editmesh(obedit->data, em);
@@ -1000,15 +1054,13 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
                /* one segment first: the X axis */             
                phi = (2*dia)/(float)(tot-1);
                phid = (2*dia)/(float)(seg-1);
-               for(a=0;a<tot;a++) {
+               for(a=tot-1;a>=0;a--) {
                        vec[0] = (phi*a) - dia;
                        vec[1]= - dia;
                        vec[2]= 0.0f;
                        eve= addvertlist(em, vec, NULL);
                        eve->f= 1+2+4;
-                       if (a) {
-                               addedgelist(em, eve->prev, eve, NULL);
-                       }
+                       if(a < tot -1) addedgelist(em, eve->prev, eve, NULL);
                }
                /* extrude and translate */
                vec[0]= vec[2]= 0.0;
@@ -1018,7 +1070,17 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
                        extrudeflag_vert(obedit, em, 2, nor, 0);        // nor unused
                        translateflag(em, 2, vec);
                }
+                       
+               /* and now do imat */
+               eve= em->verts.first;
+               while(eve) {
+                       if(eve->f & SELECT) {
+                               mul_m4_v3(mat,eve->co);
+                       }
+                       eve= eve->next;
+               }
                break;
+                       
        case PRIM_UVSPHERE: /*  UVsphere */
                
                /* clear all flags */
@@ -1096,7 +1158,7 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
                        }
 
                        dia*=200;
-                       for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1,0);
+                       for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0);
                        /* and now do imat */
                        eve= em->verts.first;
                        while(eve) {
@@ -1151,7 +1213,10 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
                else if(ext==0) 
                        depth= 0.0f;
        
-               /* vertices */
+               /* first vertex at 0° for circular objects */
+               if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) )
+                       phi = 0.0f;
+                       
                vtop= vdown= v1= v2= 0;
                for(b=0; b<=ext; b++) {
                        for(a=0; a<tot; a++) {
@@ -1262,6 +1327,23 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
 
 /* ********* add primitive operators ************* */
 
+static const char *get_mesh_defname(int type)
+{
+       switch (type) {
+               case PRIM_PLANE: return "Plane";
+               case PRIM_CUBE: return "Cube";
+               case PRIM_CIRCLE: return "Circle";
+               case PRIM_CYLINDER: return "Cylinder";
+               case PRIM_CONE: return "Cone";
+               case PRIM_GRID: return "Grid";
+               case PRIM_UVSPHERE: return "Sphere";
+               case PRIM_ICOSPHERE: return "Icosphere";
+               case PRIM_MONKEY: return "Monkey";
+               default:
+                       return "Mesh";
+       }
+}
+
 static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmode, unsigned int layer, 
                int type, int tot, int seg,
                int subdiv, float dia, float depth, int ext, int fill)
@@ -1269,22 +1351,28 @@ static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmod
        Object *obedit= CTX_data_edit_object(C);
        int newob = 0;
        float mat[4][4];
+       float scale;
 
        if(obedit==NULL || obedit->type!=OB_MESH) {
                obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer);
                
+               rename_id((ID *)obedit, get_mesh_defname(type));
+               rename_id((ID *)obedit->data, get_mesh_defname(type));
+               
                /* create editmode */
                ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
                newob = 1;
        }
-       else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
+       else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+
+       scale= ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
 
-       dia *= ED_object_new_primitive_matrix(C, loc, rot, mat);
-       depth *= ED_object_new_primitive_matrix(C, loc, rot, mat);
+       dia *= scale;
+       depth *= scale * 0.5f;
 
        make_prim(obedit, type, mat, tot, seg, subdiv, dia, depth, ext, fill);
 
-       DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+       DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
 
@@ -1301,7 +1389,8 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
        make_prim_ext(C, loc, rot, enter_editmode, layer,
@@ -1333,11 +1422,12 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
        make_prim_ext(C, loc, rot, enter_editmode, layer,
-                       PRIM_CUBE, 4, 0, 0, sqrt(2.0f), 1.0f, 1, 1);
+                       PRIM_CUBE, 4, 0, 0, sqrt(2.0f), 2.0f, 1, 1);
        return OPERATOR_FINISHED;
 }
 
@@ -1365,7 +1455,8 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_CIRCLE, RNA_int_get(op->ptr, "vertices"), 0, 0,
@@ -1398,13 +1489,14 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
        ED_object_add_generic_props(ot, TRUE);
 }
 
-static int add_primitive_tube_exec(bContext *C, wmOperator *op)
+static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
 {
        int enter_editmode;
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0,
@@ -1415,16 +1507,16 @@ static int add_primitive_tube_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void MESH_OT_primitive_tube_add(wmOperatorType *ot)
+void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Add Tube";
-       ot->description= "Construct a tube mesh";
-       ot->idname= "MESH_OT_primitive_tube_add";
+       ot->name= "Add Cylinder";
+       ot->description= "Construct a cylinder mesh";
+       ot->idname= "MESH_OT_primitive_cylinder_add";
        
        /* api callbacks */
        ot->invoke= ED_object_add_generic_invoke;
-       ot->exec= add_primitive_tube_exec;
+       ot->exec= add_primitive_cylinder_exec;
        ot->poll= ED_operator_scene_editable;
        
        /* flags */
@@ -1433,7 +1525,7 @@ void MESH_OT_primitive_tube_add(wmOperatorType *ot)
        /* props */
        RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
        RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
-       RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+       RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
        RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", "");
 
        ED_object_add_generic_props(ot, TRUE);
@@ -1445,7 +1537,8 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_CONE, RNA_int_get(op->ptr, "vertices"), 0, 0,
@@ -1473,8 +1566,8 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
        /* props */
        RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
        RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
-       RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
-       RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", "");
+       RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+       RNA_def_boolean(ot->srna, "cap_end", 1, "Cap End", "");
 
        ED_object_add_generic_props(ot, TRUE);
 }
@@ -1485,7 +1578,8 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_GRID, RNA_int_get(op->ptr, "x_subdivisions"),
@@ -1524,7 +1618,8 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_MONKEY, 0, 0, 2, 0.0f, 0.0f, 0, 0);
@@ -1556,10 +1651,11 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
-                       PRIM_UVSPHERE, RNA_int_get(op->ptr, "rings"),
+                       PRIM_UVSPHERE, RNA_int_get(op->ptr, "ring_count"),
                        RNA_int_get(op->ptr, "segments"), 0,
                        RNA_float_get(op->ptr,"size"), 0.0f, 0, 0);
 
@@ -1583,7 +1679,7 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
        
        /* props */
        RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
-       RNA_def_int(ot->srna, "rings", 16, INT_MIN, INT_MAX, "Rings", "", 3, 500);
+       RNA_def_int(ot->srna, "ring_count", 16, INT_MIN, INT_MAX, "Rings", "", 3, 500);
        RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00);
 
        ED_object_add_generic_props(ot, TRUE);
@@ -1595,7 +1691,8 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
        unsigned int layer;
        float loc[3], rot[3];
        
-       ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode, &layer);
+       if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+               return OPERATOR_CANCELLED;
 
        make_prim_ext(C, loc, rot, enter_editmode, layer,
                        PRIM_ICOSPHERE, 0, 0, RNA_int_get(op->ptr, "subdivisions"),
@@ -1620,7 +1717,7 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
+       RNA_def_int(ot->srna, "subdivisions", 2, 0, INT_MAX, "Subdivisions", "", 0, 8);
        RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
 
        ED_object_add_generic_props(ot, TRUE);
@@ -1628,7 +1725,7 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
 
 /****************** add duplicate operator ***************/
 
-static int mesh_duplicate_exec(bContext *C, wmOperator *op)
+static int mesh_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Object *ob= CTX_data_edit_object(C);
        EditMesh *em= BKE_mesh_get_editmesh(ob->data);
@@ -1637,13 +1734,13 @@ static int mesh_duplicate_exec(bContext *C, wmOperator *op)
 
        BKE_mesh_end_editmesh(ob->data, em);
 
-       DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+       DAG_id_tag_update(ob->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
        
        return OPERATOR_FINISHED;
 }
 
-static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 {
        WM_cursor_wait(1);
        mesh_duplicate_exec(C, op);