merge with 2.5 (not trunk, last merge message said that on accident) at r22252
[blender.git] / source / blender / editors / mesh / editmesh_add.c
index 60d821b98018e97610292aeea3aa99c093e2d158..ff0814661ebd84cb6a5cfff6434a16e01a6eca2b 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "MEM_guardedalloc.h"
 
-
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "BLI_editVert.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 "BKE_tessmesh.h"
 
-#include "BIF_retopo.h"
+#include "WM_api.h"
+#include "WM_types.h"
 
 #include "ED_mesh.h"
-#include "ED_multires.h"
+#include "ED_retopo.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_util.h"
 #include "ED_view3d.h"
 
+#include "bmesh.h"
+
 #include "mesh_intern.h"
 
 /* bpymenu removed XXX */
 
 /* XXX */
-static void BIF_undo_push() {}
-static void waitcursor() {}
-static void error() {}
-static int pupmenu() {return 0;}
 #define add_numbut(a, b, c, d, e, f, g) {}
-static int do_clever_numbuts() {return 0;}
-static void check_editmode() {}
-static void exit_editmode() {}
 /* XXX */
 
 static float icovert[12][3] = {
-       {0,0,-200}, 
-       {144.72, -105.144,-89.443},
-       {-55.277, -170.128,-89.443}, 
-       {-178.885,0,-89.443},
-       {-55.277,170.128,-89.443}, 
-       {144.72,105.144,-89.443},
-       {55.277,-170.128,89.443},
-       {-144.72,-105.144,89.443},
-       {-144.72,105.144,89.443},
-       {55.277,170.128,89.443},
-       {178.885,0,89.443},
-       {0,0,200}
+       {0.0f,0.0f,-200.0f}, 
+       {144.72f, -105.144f,-89.443f},
+       {-55.277f, -170.128,-89.443f}, 
+       {-178.885f,0.0f,-89.443f},
+       {-55.277f,170.128f,-89.443f}, 
+       {144.72f,105.144f,-89.443f},
+       {55.277f,-170.128f,89.443f},
+       {-144.72f,-105.144f,89.443f},
+       {-144.72f,105.144f,89.443f},
+       {55.277f,170.128f,89.443f},
+       {178.885f,0.0f,89.443f},
+       {0.0f,0.0f,200.0f}
 };
 static short icoface[20][3] = {
        {1,0,2},
@@ -113,133 +119,11 @@ static short icoface[20][3] = {
        {10,9,11}
 };
 
-static void get_view_aligned_coordinate(float *fp, short mval[2])
-{
-//     float dvec[3];
-//     short mx, my;
-       
-//     mx= mval[0];
-//     my= mval[1];
-       
-// XXX project_short_noclip(ar, v3d, fp, mval);
-       
-// XXX initgrabz(fp[0], fp[1], fp[2]);
-       
-//     if(mval[0]!=IS_CLIPPED) {
-//             window_to_3d(dvec, mval[0]-mx, mval[1]-my);
-//             VecSubf(fp, fp, dvec);
-//     }
-}
-
-void add_click_mesh(Scene *scene, EditMesh *em)
-{
-       View3D *v3d= NULL; // XXX
-       EditVert *eve, *v1;
-       float min[3], max[3];
-       int done= 0;
-       
-       TEST_EDITMESH
-       if(multires_test()) return;
-       
-       INIT_MINMAX(min, max);
-       
-       for(v1= em->verts.first;v1; v1=v1->next) {
-               if(v1->f & SELECT) {
-                       DO_MINMAX(v1->co, min, max);
-                       done= 1;
-               }
-       }
-
-       /* call extrude? */
-       if(done) {
-               EditEdge *eed;
-               float vec[3], cent[3], mat[3][3];
-               float nor[3]= {0.0, 0.0, 0.0};
-               short mval[2];
-               
-               /* check for edges that are half selected, use for rotation */
-               done= 0;
-               for(eed= em->edges.first; eed; eed= eed->next) {
-                       if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) {
-                               if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co);
-                               else VecSubf(vec, eed->v2->co, eed->v1->co);
-                               VecAddf(nor, nor, vec);
-                               done= 1;
-                       }
-               }
-               if(done) Normalize(nor);
-               
-               /* center */
-               VecAddf(cent, min, max);
-               VecMulf(cent, 0.5f);
-               VECCOPY(min, cent);
-               
-               Mat4MulVecfl(G.obedit->obmat, min);     // view space
-               get_view_aligned_coordinate(min, mval);
-               Mat4Invert(G.obedit->imat, G.obedit->obmat); 
-               Mat4MulVecfl(G.obedit->imat, min); // back in object space
-               
-               VecSubf(min, min, cent);
-               
-               /* calculate rotation */
-               Mat3One(mat);
-               if(done) {
-                       float dot;
-                       
-                       VECCOPY(vec, min);
-                       Normalize(vec);
-                       dot= INPR(vec, nor);
-
-                       if( fabs(dot)<0.999) {
-                               float cross[3], si, q1[4];
-                               
-                               Crossf(cross, nor, vec);
-                               Normalize(cross);
-                               dot= 0.5f*saacos(dot);
-                               si= (float)sin(dot);
-                               q1[0]= (float)cos(dot);
-                               q1[1]= cross[0]*si;
-                               q1[2]= cross[1]*si;
-                               q1[3]= cross[2]*si;
-                               
-                               QuatToMat3(q1, mat);
-                       }
-               }
-               
-               extrudeflag(em, SELECT, nor);
-               rotateflag(em, SELECT, cent, mat);
-               translateflag(em, SELECT, min);
-               
-               recalc_editnormals(em);
-       }
-       else {
-               float mat[3][3],imat[3][3];
-               float *curs= give_cursor(scene, v3d);
-               
-               eve= addvertlist(em, 0, NULL);
-
-               Mat3CpyMat4(mat, G.obedit->obmat);
-               Mat3Inv(imat, mat);
-               
-               VECCOPY(eve->co, curs);
-               VecSubf(eve->co, eve->co, G.obedit->obmat[3]);
 
-               Mat3MulVecfl(imat, eve->co);
-               
-               eve->f= SELECT;
-       }
-       
-       retopo_do_all();
-       
-       BIF_undo_push("Add vertex/edge/face");
-// XXX DAG_object_flush_update(scene, G.obedit, OB_RECALC_DATA);       
-       
-       while(0); // XXX get_mbut()&R_MOUSE);
-
-}
+/* ********************** */
 
 /* selected faces get hidden edges */
-static void make_fgon(EditMesh *em, int make)
+int make_fgon(EditMesh *em, wmOperator *op, int make)
 {
        EditFace *efa;
        EditEdge *eed;
@@ -247,7 +131,7 @@ static void make_fgon(EditMesh *em, int make)
        float *nor=NULL;        // reference
        int done=0;
        
-       if(!make) {
+       if(make==0) {
                for(efa= em->faces.first; efa; efa= efa->next) {
                        if(efa->f & SELECT) {
                                efa->fgonf= 0;
@@ -255,12 +139,12 @@ static void make_fgon(EditMesh *em, int make)
                                efa->e2->h &= ~EM_FGON;
                                efa->e3->h &= ~EM_FGON;
                                if(efa->e4) efa->e4->h &= ~EM_FGON;
+                               done= 1;
                        }
                }
                EM_fgon_flags(em);      // redo flags and indices for fgons
-// XXX         DAG_object_flush_update(scene, G.obedit, OB_RECALC_DATA);       
-               BIF_undo_push("Clear FGon");
-               return;
+               
+               return done;
        }
 
        /* tagging edges. rule is:
@@ -311,14 +195,14 @@ static void make_fgon(EditMesh *em, int make)
                if(eve->f1==1) break;
        }
        if(eve) {
-               error("Cannot make polygon with interior vertices");
-               return;
+               BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices");
+               return 0;
        }
        
        // check for faces
        if(nor==NULL) {
-               error("No faces selected to make FGon");
-               return;
+               BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon");
+               return 0;
        }
 
        // and there we go
@@ -329,15 +213,73 @@ static void make_fgon(EditMesh *em, int make)
                }
        }
        
-       if(done==0) {
-               error("Didn't find FGon to create");
-       }
-       else {
+       if(done)
                EM_fgon_flags(em);      // redo flags and indices for fgons
+       return done;
+}
+
+static int make_fgon_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+
+       if( make_fgon(em, op, 1) ) {
+               DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
+       
+               WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 
-// XXX         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
-               BIF_undo_push("Make FGon");
+               BKE_mesh_end_editmesh(obedit->data, em);
+               return OPERATOR_FINISHED;
        }
+
+       BKE_mesh_end_editmesh(obedit->data, em);
+       return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_fgon_make(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Make F-gon";
+       ot->idname= "MESH_OT_fgon_make";
+       
+       /* api callbacks */
+       ot->exec= make_fgon_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int clear_fgon_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+       
+       if( make_fgon(em, op, 0) ) {
+               DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
+               
+               WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+               
+               BKE_mesh_end_editmesh(obedit->data, em);
+               return OPERATOR_FINISHED;
+       }
+
+       BKE_mesh_end_editmesh(obedit->data, em);
+       return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_fgon_clear(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Clear F-gon";
+       ot->idname= "MESH_OT_fgon_clear";
+       
+       /* api callbacks */
+       ot->exec= clear_fgon_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* precondition; 4 vertices selected, check for 4 edges and create face */
@@ -386,6 +328,8 @@ static EditFace *addface_from_edges(EditMesh *em)
        return NULL;
 }
 
+/* ******************************* */
+
 /* this also allows to prevent triangles being made in quads */
 static int compareface_overlaps(EditFace *vl1, EditFace *vl2)
 {
@@ -557,6 +501,7 @@ static void fix_new_face(EditMesh *em, EditFace *eface)
        }
 }
 
+/* only adds quads or trias when there's edges already */
 void addfaces_from_edgenet(EditMesh *em)
 {
        EditVert *eve1, *eve2, *eve3, *eve4;
@@ -600,18 +545,56 @@ void addfaces_from_edgenet(EditMesh *em)
 
        EM_select_flush(em);
        
-       BIF_undo_push("Add faces");
-// XXX DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+// XXX DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 }
 
-void addedgeface_mesh(EditMesh *em)
+static void addedgeface_mesh(Mesh *me, BMEditMesh *bem, wmOperator *op)
 {
+       EditMesh *em;
        EditVert *eve, *neweve[4];
        EditEdge *eed;
        EditFace *efa;
        short amount=0;
+       
+       /*return if bmesh vert connect does anything.*/
+       if (bem->selectmode & SCE_SELECT_VERTEX) {
+               BMesh *bm = bem->bm;
+               BMOperator bmop;
+               int len, ok;
+               
+               EDBM_InitOpf(bem, &bmop, op, "connectverts verts=%hv", BM_SELECT);
+               BMO_Exec_Op(bem->bm, &bmop);
 
-       if(multires_test()) return;
+               len = BMO_GetSlot(&bmop, "edgeout")->len;               
+
+               ok = EDBM_FinishOp(bem, &bmop, op, 1);
+               if (!ok) return OPERATOR_CANCELLED;
+
+               if (len) return;        
+       }
+
+       /*return if bmesh face dissolve finds stuff to
+         dissolve.  this entire tool should be
+         bmeshafied eventually, but until then
+         hacks like this to integrate with it
+         are necassary.*/
+       if (bem->selectmode & SCE_SELECT_VERTEX) {
+               BMesh *bm = bem->bm;
+               BMOperator bmop;
+               int len, ok;
+               
+               EDBM_InitOpf(bem, &bmop, op, "dissolvefaces faces=%hf", BM_SELECT);
+               BMO_Exec_Op(bem->bm, &bmop);
+
+               len = BMO_GetSlot(&bmop, "regionout")->len;             
+               
+               ok = EDBM_FinishOp(bem, &bmop, op, 1);
+               if (!ok) return OPERATOR_CANCELLED;
+
+               if (len) return;        
+       }
+
+       em = BKE_mesh_get_editmesh(me);
 
        /* how many selected ? */
        if(em->selectmode & SCE_SELECT_EDGE) {
@@ -631,29 +614,19 @@ void addedgeface_mesh(EditMesh *em)
        if(amount==2) {
                eed= addedgelist(em, neweve[0], neweve[1], NULL);
                EM_select_edge(eed, 1);
-               BIF_undo_push("Add edge");
-
-               // XXX          DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
+               
+               BKE_mesh_end_editmesh(me, em);
+               // XXX          DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); 
                return;
        }
        else if(amount > 4) {
-               
-               /* Python Menu removed XXX */
-               int ret;
-               
-               /* facemenu, will add python items */
-               char facemenu[4096]= "Make Faces%t|Auto%x1|Make FGon%x2|Clear FGon%x3";
-               
-               ret= pupmenu(facemenu);
-               
-               if(ret==1) addfaces_from_edgenet(em);
-               else if(ret==2) make_fgon(em, 1);
-               else if(ret==3) make_fgon(em, 0);
-               
+               addfaces_from_edgenet(em);
+               BKE_mesh_end_editmesh(me, em);
                return;
        }
        else if(amount<2) {
-               error("Incorrect number of vertices to make edge/face");
+               BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face");
+               BKE_mesh_end_editmesh(me, em);
                return;
        }
 
@@ -665,7 +638,7 @@ void addedgeface_mesh(EditMesh *em)
                        efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
                        EM_select_face(efa, 1);
                }
-               else error("The selected vertices already form a face");
+               else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
        }
        else if(amount==4) {
                /* this test survives when theres 2 triangles */
@@ -692,6 +665,7 @@ void addedgeface_mesh(EditMesh *em)
                                
                                if(count++ > 4){
                                        addfaces_from_edgenet(em);
+                                       BKE_mesh_end_editmesh(me, em);
                                        return;
                                } else {
                                /* if 4 edges exist, we just create the face, convex or not */
@@ -721,9 +695,9 @@ void addedgeface_mesh(EditMesh *em)
                                        }
                                }
                        }
-                       else error("The selected vertices already form a face");
+                       else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
                }
-               else error("The selected vertices already form a face");
+               else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
        }
        
        if(efa) {
@@ -732,70 +706,12 @@ void addedgeface_mesh(EditMesh *em)
                fix_new_face(em, efa);
                
                recalc_editnormals(em);
-               BIF_undo_push("Add face");
        }
-       
-// XXX DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
-}
-
-
-void adduplicate_mesh(EditMesh *em)
-{
-
-       TEST_EDITMESH
-       if(multires_test()) return;
-
-       waitcursor(1);
-
-       adduplicateflag(em, SELECT);
-
-       waitcursor(0);
 
-               /* We need to force immediate calculation here because 
-               * transform may use derived objects (which are now stale).
-               *
-               * This shouldn't be necessary, derived queries should be
-               * automatically building this data if invalid. Or something.
-               */
-// XXX DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
-       object_handle_update(G.obedit);
-
-// XXX BIF_TransformSetUndo("Add Duplicate");
-//     initTransform(TFM_TRANSLATION, CTX_NO_PET);
-//     Transform();
+       BKE_mesh_end_editmesh(me, em);
 }
 
-/* check whether an object to add mesh to exists, if not, create one
-* returns 1 if new object created, else 0 */
-static int confirm_objectExists(Scene *scene, Mesh **me, float mat[][3] )
-{
-       int newob = 0;
-       
-       /* if no obedit: new object and enter editmode */
-       if(G.obedit==NULL) {
-               /* add_object actually returns an object ! :-)
-               But it also stores the added object struct in
-               G.scene->basact->object (BASACT->object) */
-
-// XXX         add_object_draw(OB_MESH);
-
-               G.obedit= BASACT->object;
-               
-               where_is_object(G.obedit);
-               
-               make_editMesh(scene, G.obedit); 
-               newob= 1;
-       }
-       *me = G.obedit->data;
-       
-       /* deselectall */
-       EM_clear_flag_all((*me)->edit_mesh, SELECT);
-       
-       /* imat and center and size */
-       Mat3CpyMat4(mat, G.obedit->obmat);
-       
-       return newob;
-}
+/* ************************ primitives ******************* */
 
 // HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
 // this hack is only used so that scons+mingw + split-sources hack works
@@ -943,29 +859,40 @@ signed char monkeyf[250][4]= {
        // ------------------------------- end copied code
 
 
-void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
-               int subdiv, float dia, float d, int ext, int fill,
-        float cent[3])
+#define PRIM_PLANE             0
+#define PRIM_CUBE              1
+#define PRIM_CIRCLE            4
+#define PRIM_CYLINDER  5
+#define PRIM_CONE              7
+#define PRIM_GRID              10
+#define PRIM_UVSPHERE  11
+#define PRIM_ICOSPHERE         12
+#define PRIM_MONKEY            13
+
+static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
+               int subdiv, float dia, float depth, int ext, int fill)
 {
        /*
         * type - for the type of shape
         * dia - the radius for cone,sphere cylinder etc.
-        * d - depth for the cone
-        * ext - ?
+        * depth - 
+        * ext - extrude
         * fill - end capping, and option to fill in circle
         * cent[3] - center of the data. 
         * */
-       
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
        EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
        float phi, phid, vec[3];
        float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
        short a, b;
+       
+       EM_clear_flag_all(em, SELECT);
 
-       phid= 2*M_PI/tot;
-       phi= .25*M_PI;
+       phid= 2.0f*(float)M_PI/tot;
+       phi= .25f*(float)M_PI;
 
        switch(type) {
-       case 10: /*  grid */
+       case PRIM_GRID: /*  grid */
                /* clear flags */
                eve= em->verts.first;
                while(eve) {
@@ -976,10 +903,10 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                phi= 1.0; 
                phid= 2.0/((float)tot-1);
                for(a=0;a<tot;a++) {
-                       vec[0]= cent[0]+dia*phi;
-                       vec[1]= cent[1]- dia;
-                       vec[2]= cent[2];
-                       Mat3MulVecfl(imat,vec);
+                       vec[0]= dia*phi;
+                       vec[1]= - dia;
+                       vec[2]= 0.0f;
+                       Mat4MulVecfl(mat,vec);
                        eve= addvertlist(em, vec, NULL);
                        eve->f= 1+2+4;
                        if (a) {
@@ -990,13 +917,14 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                /* extrude and translate */
                vec[0]= vec[2]= 0.0;
                vec[1]= dia*phid;
-               Mat3MulVecfl(imat, vec);
+               Mat4Mul3Vecfl(mat, vec);
+               
                for(a=0;a<seg-1;a++) {
-                       extrudeflag_vert(em, 2, nor);   // nor unused
+                       extrudeflag_vert(obedit, em, 2, nor);   // nor unused
                        translateflag(em, 2, vec);
                }
                break;
-       case 11: /*  UVsphere */
+       case PRIM_UVSPHERE: /*  UVsphere */
                
                /* clear all flags */
                eve= em->verts.first;
@@ -1027,7 +955,7 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                QuatToMat3(q, cmat);
                
                for(a=0; a<seg; a++) {
-                       extrudeflag_vert(em, 2, nor); // nor unused
+                       extrudeflag_vert(obedit, em, 2, nor); // nor unused
                        rotateflag(em, 2, v1->co, cmat);
                }
 
@@ -1037,13 +965,12 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                eve= em->verts.first;
                while(eve) {
                        if(eve->f & SELECT) {
-                               VecAddf(eve->co,eve->co,cent);
-                               Mat3MulVecfl(imat,eve->co);
+                               Mat4MulVecfl(mat,eve->co);
                        }
                        eve= eve->next;
                }
                break;
-       case 12: /* Icosphere */
+       case PRIM_ICOSPHERE: /* Icosphere */
                {
                        EditVert *eva[12];
                        EditEdge *eed;
@@ -1074,13 +1001,14 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                        }
 
                        dia*=200;
-                       for(a=1; a<subdiv; a++) esubdivideflag(em, 2, dia, 0,1,0);
+
+                       for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0.0, 0, 1, 0);
+                       
                        /* and now do imat */
                        eve= em->verts.first;
                        while(eve) {
                                if(eve->f & 2) {
-                                       VecAddf(eve->co,eve->co,cent);
-                                       Mat3MulVecfl(imat,eve->co);
+                                       Mat4MulVecfl(mat,eve->co);
                                }
                                eve= eve->next;
                        }
@@ -1093,7 +1021,7 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                        }
                }
                break;
-       case 13: /* Monkey */
+       case PRIM_MONKEY: /* Monkey */
                {
                        //extern int monkeyo, monkeynv, monkeynf;
                        //extern signed char monkeyf[][4];
@@ -1119,26 +1047,27 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                        /* and now do imat */
                        for(eve= em->verts.first; eve; eve= eve->next) {
                                if(eve->f & SELECT) {
-                                       VecAddf(eve->co,eve->co,cent);
-                                       Mat3MulVecfl(imat,eve->co);
+                                       Mat4MulVecfl(mat,eve->co);
                                }
                        }
                        recalc_editnormals(em);
                }
                break;
        default: /* all types except grid, sphere... */
-               if(ext==0 && type!=7) d= 0;
+               if(type==PRIM_CONE);
+               else if(ext==0) 
+                       depth= 0.0f;
        
                /* vertices */
                vtop= vdown= v1= v2= 0;
                for(b=0; b<=ext; b++) {
                        for(a=0; a<tot; a++) {
                                
-                               vec[0]= cent[0]+dia*sin(phi);
-                               vec[1]= cent[1]+dia*cos(phi);
-                               vec[2]= cent[2]+d;
+                               vec[0]= dia*sin(phi);
+                               vec[1]= dia*cos(phi);
+                               vec[2]= b?depth:-depth;
                                
-                               Mat3MulVecfl(imat, vec);
+                               Mat4MulVecfl(mat, vec);
                                eve= addvertlist(em, vec, NULL);
                                eve->f= SELECT;
                                if(a==0) {
@@ -1147,20 +1076,20 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                                }
                                phi+=phid;
                        }
-                       d= -d;
                }
+                       
                /* center vertices */
-               /* type 7, a cone can only have 1 one side filled
+               /* type PRIM_CONE can only have 1 one side filled
                 * if the cone has no capping, dont add vtop */
-               if((fill && type>1) || type == 7) {
-                       VECCOPY(vec,cent);
-                       vec[2]-= -d;
-                       Mat3MulVecfl(imat,vec);
+               if((fill && type>1) || type == PRIM_CONE) {
+                       vec[0]= vec[1]= 0.0f;
+                       vec[2]= -depth;
+                       Mat4MulVecfl(mat, vec);
                        vdown= addvertlist(em, vec, NULL);
-                       if((ext || type==7) && fill) {
-                               VECCOPY(vec,cent);
-                               vec[2]-= d;
-                               Mat3MulVecfl(imat,vec);
+                       if((ext || type==PRIM_CONE) && fill) {
+                               vec[0]= vec[1]= 0.0f;
+                               vec[2]= depth;
+                               Mat4MulVecfl(mat,vec);
                                vtop= addvertlist(em, vec, NULL);
                        }
                } else {
@@ -1171,7 +1100,7 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                if(vdown) vdown->f= SELECT;
        
                /* top and bottom face */
-               if(fill || type==7) {
+               if(fill || type==PRIM_CONE) {
                        if(tot==4 && (type==0 || type==1)) {
                                v3= v1->next->next;
                                if(ext) v4= v2->next->next;
@@ -1197,7 +1126,7 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                                }
                        }
                }
-               else if(type==4) {  /* we need edges for a circle */
+               else if(type==PRIM_CIRCLE) {  /* we need edges for a circle */
                        v3= v1;
                        for(a=1;a<tot;a++) {
                                addedgelist(em, v3, v3->next, NULL);
@@ -1216,7 +1145,7 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                        }
                        addfacelist(em, v3, v1, v2, v4, NULL, NULL);
                }
-               else if(type==7 && fill) {
+               else if(type==PRIM_CONE && fill) {
                        /* add the bottom flat area of the cone
                         * if capping is disabled dont bother */
                        v3= v1;
@@ -1227,186 +1156,404 @@ void make_prim(EditMesh *em, int type, float imat[3][3], int tot, int seg,
                        addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
                }
        }
+       
+       EM_stats_update(em);
        /* simple selection flush OK, based on fact it's a single model */
        EM_select_flush(em); /* flushes vertex -> edge -> face selection */
        
        if(type!=0 && type!=13)
                righthandfaces(em, 1);  /* otherwise monkey has eyes in wrong direction */
+
+       BKE_mesh_end_editmesh(obedit->data, em);
+}
+
+
+/* uses context to figure out transform for primitive */
+/* returns standard diameter */
+static float new_primitive_matrix(bContext *C, float primmat[][4])
+{
+       Object *obedit= CTX_data_edit_object(C);
+       Scene *scene = CTX_data_scene(C);
+       View3D *v3d =CTX_wm_view3d(C);
+       RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+       float *curs, mat[3][3], vmat[3][3], cmat[3][3], imat[3][3];
+       
+       Mat4One(primmat);
+       
+       if(rv3d && (U.flag & USER_ADD_VIEWALIGNED)) {
+               Mat3CpyMat4(vmat, rv3d->viewmat);
+       } else
+               Mat3One(vmat);
+       
+       /* inverse transform for view and object */
+       Mat3CpyMat4(mat, obedit->obmat);
+       Mat3MulMat3(cmat, vmat, mat);
+       Mat3Inv(imat, cmat);
+       Mat4CpyMat3(primmat, imat);
+
+       /* center */
+       curs= give_cursor(scene, v3d);
+       VECCOPY(primmat[3], curs);
+       VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
+       Mat3Inv(imat, mat);
+       Mat3MulVecfl(imat, primmat[3]);
+       
+       if(v3d) return v3d->grid;
+       return 1.0f;
 }
 
-void add_primitiveMesh(Scene *scene, View3D *v3d, EditMesh *em, int type)
+/* ********* add primitive operators ************* */
+
+static int add_primitive_plane_exec(bContext *C, wmOperator *op)
 {
-       Mesh *me;
-       float *curs, d, dia, phi, phid, cent[3], imat[3][3], mat[3][3];
-       float cmat[3][3];
-       static int tot=32, seg=32, subdiv=2,
-               /* so each type remembers its fill setting */
-               fill_circle=0, fill_cone=1, fill_cylinder=1;
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       /* plane (diameter of 1.41 makes it unit size) */
+       dia*= sqrt(2.0f);
        
-       int ext=0, fill=0, totoud, newob=0;
-       char *undostr="Add Primitive";
-       char *name=NULL;
+       make_prim(obedit, PRIM_PLANE, mat, 4, 0, 0, dia, 0.0f, 0, 1);
        
-//     if(G.scene->id.lib) return;
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
        
-       /* this function also comes from an info window */
-// XXX if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+       return OPERATOR_FINISHED;       
+}
 
-       if (G.obedit && G.obedit->type==OB_MESH && multires_test()) return;
+void MESH_OT_primitive_plane_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Plane";
+       ot->idname= "MESH_OT_primitive_plane_add";
        
-       /* if editmode exists for other type, it exits */
-       check_editmode(OB_MESH);
+       /* api callbacks */
+       ot->exec= add_primitive_plane_exec;
+       ot->poll= ED_operator_editmesh;
        
-       if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
-               G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT);
-       }
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
-       totoud= tot; /* store, and restore when cube/plane */
+static int add_primitive_cube_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
        
-       dia= v3d->grid;
-       d= v3d->grid;
+       dia= new_primitive_matrix(C, mat);
+       /* plane (diameter of 1.41 makes it unit size) */
+       dia*= sqrt(2.0f);
        
-       /* ext==extrudeflag, tot==amount of vertices in basis */
-       switch(type) {
-       case 0:         /* plane */
-               tot= 4;
-               ext= 0;
-               fill= 1;
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Plane";
-               undostr="Add Plane";
-               break;
-       case 1:         /* cube  */
-               tot= 4;
-               ext= 1;
-               fill= 1;
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Cube";
-               undostr="Add Cube";
-               break;
-       case 4:         /* circle  */
-               add_numbut(0, NUM|INT, "Vertices:", 3, 500, &tot, NULL);
-               add_numbut(1, NUM|FLO, "Radius:", 0.001*v3d->grid, 100*v3d->grid, &dia, NULL);
-               add_numbut(2, TOG|INT, "Fill", 0, 0, &(fill_circle), NULL);
-               if (!(do_clever_numbuts("Add Circle", 3, 0))) return;
-               ext= 0;
-               fill = fill_circle;
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Circle";
-               undostr="Add Circle";
-               break;
-       case 5:         /* cylinder  */
-               d*=2;
-               add_numbut(0, NUM|INT, "Vertices:", 2, 500, &tot, NULL);
-               add_numbut(1, NUM|FLO, "Radius:", 0.001*v3d->grid, 100*v3d->grid, &dia, NULL);
-               add_numbut(2, NUM|FLO, "Depth:", 0.001*v3d->grid, 100*v3d->grid, &d, NULL);
-               add_numbut(3, TOG|INT, "Cap Ends", 0, 0, &(fill_cylinder), NULL);
-               if (!(do_clever_numbuts("Add Cylinder", 4, 0))) return;
-               ext= 1;
-               fill = fill_cylinder;
-               d/=2;
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) {
-                       if (fill)       name = "Cylinder";
-                       else            name = "Tube";
-               }
-               undostr="Add Cylinder";
-               break;
-       case 7:         /* cone  */
-               d*=2;
-               add_numbut(0, NUM|INT, "Vertices:", 2, 500, &tot, NULL);
-               add_numbut(1, NUM|FLO, "Radius:", 0.001*v3d->grid, 100*v3d->grid, &dia, NULL);
-               add_numbut(2, NUM|FLO, "Depth:", 0.001*v3d->grid, 100*v3d->grid, &d, NULL);
-               add_numbut(3, TOG|INT, "Cap End", 0, 0, &(fill_cone), NULL);
-               if (!(do_clever_numbuts("Add Cone", 4, 0))) return;
-               d/=2;
-               ext= 0;
-               fill = fill_cone;
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Cone";
-               undostr="Add Cone";
-               break;
-       case 10:        /* grid */
-               add_numbut(0, NUM|INT, "X res:", 3, 1000, &tot, NULL);
-               add_numbut(1, NUM|INT, "Y res:", 3, 1000, &seg, NULL);
-               if (!(do_clever_numbuts("Add Grid", 2, 0))) return; 
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Grid";
-               undostr="Add Grid";
-               break;
-       case 11:        /* UVsphere */
-               add_numbut(0, NUM|INT, "Segments:", 3, 500, &seg, NULL);
-               add_numbut(1, NUM|INT, "Rings:", 3, 500, &tot, NULL);
-               add_numbut(2, NUM|FLO, "Radius:", 0.001*v3d->grid, 100*v3d->grid, &dia, NULL);
-               
-               if (!(do_clever_numbuts("Add UV Sphere", 3, 0))) return;
-               
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Sphere";
-               undostr="Add UV Sphere";
-               break;
-       case 12:        /* Icosphere */
-               add_numbut(0, NUM|INT, "Subdivision:", 1, 8, &subdiv, NULL);
-               add_numbut(1, NUM|FLO, "Radius:", 0.001*v3d->grid, 100*v3d->grid, &dia, NULL);
-               if (!(do_clever_numbuts("Add Ico Sphere", 2, 0))) return;
-               
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Sphere";
-               undostr="Add Ico Sphere";
-               break;
-       case 13:        /* Monkey */
-               newob = confirm_objectExists(scene, &me, mat );
-               if(newob) name = "Suzanne";
-               undostr="Add Monkey";
-               break;
-       default:
-               newob = confirm_objectExists(scene, &me, mat );
-               break;
-       }
+       make_prim(obedit, PRIM_CUBE, mat, 4, 0, 0, dia, 1.0f, 1, 1);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
 
-       if( name!=NULL ) {
-               rename_id((ID *)G.obedit, name );
-               rename_id((ID *)me, name );
-       }
+void MESH_OT_primitive_cube_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Cube";
+       ot->idname= "MESH_OT_primitive_cube_add";
        
-       d = -d;
-       curs= give_cursor(scene, v3d);
-       VECCOPY(cent, curs);
-       cent[0]-= G.obedit->obmat[3][0];
-       cent[1]-= G.obedit->obmat[3][1];
-       cent[2]-= G.obedit->obmat[3][2];
+       /* api callbacks */
+       ot->exec= add_primitive_cube_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
-       if ( !(newob) || U.flag & USER_ADD_VIEWALIGNED) Mat3CpyMat4(imat, v3d->viewmat);
-       else Mat3One(imat);
-       Mat3MulVecfl(imat, cent);
-       Mat3MulMat3(cmat, imat, mat);
-       Mat3Inv(imat,cmat);
+static int add_primitive_circle_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia *= RNA_float_get(op->ptr,"radius");
        
+       make_prim(obedit, PRIM_CIRCLE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 0.0f, 0, 
+                         RNA_boolean_get(op->ptr, "fill"));
        
-       if(type == 0 || type == 1) /* plane, cube (diameter of 1.41 makes it unit size) */
-               dia *= sqrt(2.0);
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
 
-       phid= 2*M_PI/tot;
-       phi= .25*M_PI;
+void MESH_OT_primitive_circle_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Circle";
+       ot->idname= "MESH_OT_primitive_circle_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_circle_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500);
+       RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+       RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
+}
 
-       make_prim(em, type, imat, tot, seg, subdiv, dia, d, ext, fill, cent);
+static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia *= RNA_float_get(op->ptr, "radius");
+       
+       make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
+                         RNA_float_get(op->ptr, "depth"), 1, 1);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
 
-       if(type<2) tot = totoud;
+void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Cylinder";
+       ot->idname= "MESH_OT_primitive_cylinder_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_cylinder_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+       RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+       RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
+}
 
-       /* simple selection flush OK, based on fact it's a single model */
-       EM_select_flush(em); // flushes vertex -> edge -> face selection
+static int add_primitive_tube_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia *= RNA_float_get(op->ptr, "radius");
+       
+       make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
+                         RNA_float_get(op->ptr, "depth"), 1, 0);
        
-       if(type!=0 && type!=13) righthandfaces(em, 1);  /* otherwise monkey has eyes in wrong direction... */
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
 
-// XXX DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+void MESH_OT_primitive_tube_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Tube";
+       ot->idname= "MESH_OT_primitive_tube_add";
        
-       /* if a new object was created, it stores it in Mesh, for reload original data and undo */
-       if ( !(newob) || U.flag & USER_ADD_EDITMODE) {
-               if(newob) load_editMesh(scene, G.obedit);
-       } else {
-               exit_editmode(2);
-       }
+       /* api callbacks */
+       ot->exec= add_primitive_tube_exec;
+       ot->poll= ED_operator_editmesh;
        
-       BIF_undo_push(undostr);
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+       RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+       RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
 }
 
+static int add_primitive_cone_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia *= RNA_float_get(op->ptr, "radius");
+       
+       make_prim(obedit, PRIM_CONE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
+                         RNA_float_get(op->ptr, "depth"), 0, RNA_boolean_get(op->ptr, "cap_end"));
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
+
+void MESH_OT_primitive_cone_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Cone";
+       ot->idname= "MESH_OT_primitive_cone_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_cone_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+       RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
+       RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
+       RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", "");
+
+}
+
+static int add_primitive_grid_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia*= RNA_float_get(op->ptr, "size");
+       
+       make_prim(obedit, PRIM_GRID, mat, RNA_int_get(op->ptr, "x_subdivisions"), 
+                         RNA_int_get(op->ptr, "y_subdivisions"), 0, dia, 0.0f, 0, 1);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
+
+void MESH_OT_primitive_grid_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Grid";
+       ot->idname= "MESH_OT_primitive_grid_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_grid_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000);
+       RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisons", "", 3, 1000);
+       RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, FLT_MAX);
+}
+
+static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float mat[4][4];
+       
+       new_primitive_matrix(C, mat);
+       
+       make_prim(obedit, PRIM_MONKEY, mat, 0, 0, 2, 0.0f, 0.0f, 0, 0);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
+
+void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Monkey";
+       ot->idname= "MESH_OT_primitive_monkey_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_monkey_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia*= RNA_float_get(op->ptr, "size");
+
+       make_prim(obedit, PRIM_UVSPHERE, mat, RNA_int_get(op->ptr, "rings"), 
+                         RNA_int_get(op->ptr, "segments"), 0, dia, 0.0f, 0, 0);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
+
+void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add UV Sphere";
+       ot->idname= "MESH_OT_primitive_uv_sphere_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_uvsphere_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
+       RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500);
+       RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, 100.00);
+}
+
+static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       float dia, mat[4][4];
+       
+       dia= new_primitive_matrix(C, mat);
+       dia*= RNA_float_get(op->ptr, "size");
+       
+       make_prim(obedit, PRIM_ICOSPHERE, mat, 0, 0, 
+                         RNA_int_get(op->ptr, "subdivisions"), dia, 0.0f, 0, 0);
+       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;       
+}
+
+void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Ico Sphere";
+       ot->idname= "MESH_OT_primitive_ico_sphere_add";
+       
+       /* api callbacks */
+       ot->exec= add_primitive_icosphere_exec;
+       ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* props */
+       RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
+       RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
+}